On Android, How do I display html in ListView? - android

I am feeding a ListView from a database in this way (nothing special), except
COL_TXT_TRANSL2 contains html formatting:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
mCurrBookID = extras.getString("BookID");
mCurrChapterNum = extras.getString("ChapterNum");
mCurrChapterTitle = extras.getString("ChapterTitle");
mGitaDB= Central.mDB;
this.setTitle(mCurrChapterNum+"."+mCurrChapterTitle);
setContentView(R.layout.chapterdisplay);
//set chapter intro
TextView tvIntro=(TextView) findViewById(R.id.textIntro);
tvIntro.setText(Html.fromHtml(extras.getString("ChapterIntro")));
try {
String[] columns = new String[] { mGitaDB.COL_TXT_TEXT_NUM, mGitaDB.COL_TXT_TRANSL2 };
int[] to = new int[] { R.id.number_entry, R.id.title_entry };
mCursor=mGitaDB.GetGitaTexts(mCurrBookID, mCurrChapterNum);
mAdapter = new SimpleCursorAdapter(this,
R.layout.textslist_row, mCursor, columns, to);
setListAdapter(mAdapter);
}
catch (Exception e) {
String err="Error: " + e.getMessage();
Toast toast = Toast.makeText(Central.context, err, 15000);
toast.show();
}
}
Now the problem is that the text displayed in this ListView has HTML formatting.
How can I make listview display this HTML formatting? Currently it is displayed as a plain text with all tags.

Assuming the HTML is fairly simple you can run it through this method: http://developer.android.com/reference/android/text/Html.html#fromHtml(java.lang.String) The resulting Spannable can be sent to a TextView in the ListView. Beware the fromHtml method is very slow and may slow down scrolling, you might want to cache the Spannables.

Define a CharSequence ArrayList, include all the elements from your database to be displayed in this arraylist as HTML. Include a personal TextView layout for the individual entities of the listView, and display the Charsequence in the list. I had made use of the following code for my app:
List<CharSequence> styledItems = new ArrayList<CharSequence>();
droidDB.open();
articles = droidDB.getAllArticleTitles(feed.feedId);
droidDB.close();
for (Article article : articles) {
styledItems.add(Html.fromHtml(article.title));
}
ArrayAdapter<CharSequence> notes =
new ArrayAdapter<CharSequence>(this, R.layout.feeds_row,styledItems);
setListAdapter(notes);
For the feeds_row.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"/>
Hope this helps.

My problem was similar to yours. I was reading data from file in json format, where I have objects with id and text fields. text field is html. I have resolved problem this way:
ArrayList<MyObject> myObjectsList = new ArrayList<MyObject>();
ArrayList<HashMap<String, CharSequence>> tableElements = new ArrayList<HashMap<String, CharSequence>>();
String keyword = in.getStringExtra(TAG_KEYWORD);
InputStream is = this.getResources().openRawResource(R.raw.data);
JSONParser jParser = new JSONParser();
myObjectsList = jParser.searchForObjects(is, keyword);
for (MyObject element : myObjectsList)
{
String id = Integer.toString(element.id);
CharSequence text = Html.fromHtml(element.text);
// creating new HashMap
HashMap<String, CharSequence> map = new HashMap<String, CharSequence>();
// adding each child node to HashMap key => value
map.put(TAG_ID, id);
map.put(TAG_TEXT, text);
// adding HashList to ArrayList
tableElements.add(map);
}
ListAdapter adapter = new SimpleAdapter(this,tableElements,
R.layout.search_item,
new String[] { TAG_ID, TAG_TEXT.toString()}, new int[] {
R.id.exercise_id, R.id.text });
setListAdapter(adapter);

Related

How to make Android ListView clickable using Hashmap?

First of all, i am sorry because there is similar question that already been asked before. I've tried but it does not worked in my program. Hence, I need some help from you to help me to finish my program. Thank you.
Problem : my list cannot be click to go to next activity.
ListPending.java
public void getTable(String r) {
final ListView lv;
lv = (ListView) findViewById(R.id.lsApproval);
ArrayList<HashMap<String, String>> feedList= new ArrayList<HashMap<String, String>>();
try {
JSONArray jArray = new JSONArray(r);
JSONObject jInit = jArray.getJSONObject(0);
String valid = jInit.getString("valid");
String none="NO";
String empty="EMPTY";
TextView tv;
tv = (TextView)findViewById(R.id.tvNone);
if (valid.equals(none))
{
TextView tv1,tv2,tv3;
tv1 = (TextView)findViewById(R.id.tvSname);
tv2 = (TextView)findViewById(R.id.tvDest);
tv3 = (TextView)findViewById(R.id.tvDate);
tv.setText("\n\n\n\n\n\n" + "You do not have applicant under your approval" + "\n\n\n\n" );
tv1.setText("");
tv2.setText("");
tv3.setText("");
}
else if (valid.equals(empty))
{
TextView tv1,tv2,tv3;
tv1 = (TextView)findViewById(R.id.tvSname);
tv2 = (TextView)findViewById(R.id.tvDest);
tv3 = (TextView)findViewById(R.id.tvDate);
tv.setText("\n\n\n\n\n\n" + "No Pending List" + "\n\n\n\n" );
tv1.setText("");
tv2.setText("");
tv3.setText("");
}
else
{
String j=String.valueOf(jArray.length());
tv.setText("Have " +j+" applications need your approval");
for(int i=0; i<jArray.length();i++){
JSONObject json = jArray.getJSONObject(i);
String date = json.getString("dtfrom");
StringTokenizer tk = new StringTokenizer(date);
String dat = tk.nextToken(); // <--- yyyy-mm-dd
String staff = json.getString("staffname");
String dest = json.getString("destination");
HashMap<String, String> map = new HashMap<String, String>();
map.put("image", String.valueOf(R.mipmap.view));
map.put("staff", staff);
map.put("dest", dest);
map.put("date", dat);
feedList.add(map);
SimpleAdapter simpleAdapter = new SimpleAdapter(this, feedList, R.layout.list_pending,
new String[]{"staff", "dest","date","image"},
new int[]{R.id.tvStaff, R.id.tvDest, R.id.tvDate, R.id.ibView});
lv.setAdapter(simpleAdapter);
// React to user clicks on item
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parentAdapter, View view, int position,
long id) {
Toast.makeText(ListPending.this, "try" , Toast.LENGTH_SHORT).show();
}
});
}
}
it successfully show the data from database but not clickable.
This kind of problem occur when another object on the list is either focusable or clickable. The solution is to:
Inspect your layout xml file and make sure that none of the views you are having on your list has its android:clickable set to true.
Avoid to use any clickable view like a button on your list, as this will make your list not clickable.
First of all find the views which are getting focus and not allow list to be focused and touch in all other views put
focusable=false and focusintouchMode=false in xml
and if it is still not allowing your listview to be clicked then can share your problem again.
Seem your view is not taking focus in listview.It's the issue of view when you click the list row, it is always the capture other view event. apply below property to your main layout in row file (list_pending.xml) and let me know whether its works or not?
android:descendantFocusability="blocksDescendants"
or programmatically
listView.setDescendantFocusability(ListView.FOCUS_BLOCK_DESCENDANTS);

Android listview only first item is getting populated

Trying to make a listview with data from JSON. phonelist decalred below hold the data parsed from the json.
ArrayList<HashMap<String, String>> phonelist = new ArrayList<HashMap<String, String>>();
I am doing this in onCreateView of the fragment
for (int i = 0; i < phone.length(); i++) {
try {
JSONObject c = phone.getJSONObject(i);
String phId = c.getString("ph_id");
String phNo = c.getString("ph_no");
HashMap<String, String> map = new HashMap<String, String>();
map.put("ph_id", phId);
map.put("ph_no", phNo);
phonelist.add(map);
} catch (JSONException e) {
e.printStackTrace();
}
}
ListView list = (ListView) rootView.findViewById(R.id.listview1);
ListAdapter adapter = new SimpleAdapter(getActivity(), phonelist,
R.layout.list_item_phone,
new String[]{"ph_id", "ph_no"}, new int[]{
R.id.txtPhoneID, R.id.txtPhoneNum});
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//TODO
}
});
The phonelist is getting populated from json and here is its content
[{ph_id=1, ph_no=0120-2550000}, {ph_id=2, ph_no=1860-180-3474}, {ph_id=3, ph_no=0120-4698114}, {ph_id=4, ph_no=0361-2525256}, {ph_id=5, ph_no=033-2525368}, {ph_id=6, ph_no=011-25252525}, {ph_id=7, ph_no=0361-2525257}, {ph_id=8, ph_no=033-2525369}, {ph_id=9, ph_no=011-25252526}, {ph_id=10, ph_no=0361-2525258}, {ph_id=11, ph_no=033-2525370}, {ph_id=12, ph_no=011-25252527}]
For some reason though, only the first item shows up in the listview.
Edit:
Declaration of the phone variable
JSONArray phone = null;
And then I am getting its value onCreate like below
phone = ((JSonArrayParser) getArguments().getParcelable("phoneJsonArray")).getJsonArray();
phone.length is showing correct value (12)
HashMap is specified as key and value, based on webpage # Map. Search text for "put (K key, V value)" for reference. In your code:
map.put("ph_id", phId);
map.put("ph_no", phNo);
I can see only 2 keys are added into this map object, even though you added lots of data from JSON.
As a suggestion, instead of literal string "ph_id" as the key, you can have variable phId as key instead, and the value can be phNo. That can be one code design.
Maybe it's a good idea if you post the SimpleAdapter also, especially in getView().

Items from ListView to SQLite, SQLite to ListView

I'm trying to get all the items on my listview (I've attached some image uri) and put them in the database, then get them again and load them on the listview.
What I did is: String hex = array_list.toString(); and put that hex string in the database (sqlite).
FirstFragment:
ListView lv;
ArrayList<Uri> array_list = new ArrayList<Uri>();
ArrayAdapter<Uri> array_adapter;
OnCreate..
array_adapter = new ArrayAdapter<Uri>(getActivity(), android.R.layout.simple_list_item_1, array_list);
lv = (ListView) v.findViewById(R.id.list);
lv.setAdapter(array_adapter);
OnClick..
String hex = array_list.toString();
HashMap<String, String> rcfData = new HashMap<String, String>();
rcfData.put("dateTime", hex);
DataHolder dataHolder = new DataHolder(getActivity());
dataHolder.insertData(rcfData);
Here are the items before I put them in sqlite: (Before clicking OnClick)
SecondFragment:
ListView lv2;
ArrayList<Uri> array_list2 = new ArrayList<Uri>();
ArrayAdapter<Uri> array_adapter2;
OnCreate...
array_adapter2 = new ArrayAdapter<Uri>(getActivity(), android.R.layout.simple_list_item_1, array_list2);
lv2 = (ListView) v.findViewById(R.id.list2);
lv2.setAdapter(array_adapter2);
OnClick...
Intent intent = getActivity().getIntent();
String rcfDataId = intent.getStringExtra("unique_id");
DataHolder dataHolder = new DataHolder(getActivity());
HashMap<String, String> rcfData = dataHolder.get_rcfData(rcfDataId);
if(rcfData.size() !=0) {
String s = rcfData.get("dateTime");
Uri hello = Uri.parse(s);
array_list2.add(hello);
array_adapter2.notifyDataSetChanged();
}
The problem is, when I try to load that string from sqlite to listview of the SecondFragment, it became like this: (After clicking OnClick of SecondFragment)
What I want it to be like (after clicking OnClick of SecondFragment), is like this:
How can I load it like that?
I don't know DataHolder, and I don't know whether it's really backed by an sqlite DB, but this feels like a misuse - you'd probably want to insert each of your items from your ListView as a separate row to your table.
However, if you just want a quick workaround to make it work, you could just split the string you're reading, e.g:
if(rcfData.size() !=0) {
String s = rcfData.get("dateTime");
// Remove brackets
s = s.substring(1, s.length() - 1);
// Split string and insert to ListView
for(String sPart : s.split(", ")) {
Uri hello = Uri.parse(sPart);
array_list2.add(hello);
}
array_adapter2.notifyDataSetChanged();
}

How to dynamically add suggestions to autocompletetextview with preserving character status

Problem Description:
I am facing some problem with AutoCompleteTextView where I have to show suggestions after each keypress.
Thing is that, list of suggestion is dynamic like google's suggestion feature.
It means the new suggestions should be added as user keeps typing in plus all matching old suggestions should be displayed.
For example
I write "te" and then it should display previous suggestions like "test1" & "test2" and the new suggestions that I will get from Web API. Suppose web api gives me word "tea"& "tension ".
Now the AutoCompleteTextView will have "te" as string with all four suggestions showing below it.
This is exactly what I am looking for.
looks simple but it is showing a strange behaviour.
I am using default ArrayAdapter class instance of which I am declaring globally.
arrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line,suggestions);
word.setAdapter(arrayAdapter);
suggestions is ArrayList.
Upon getting new result from WebApi I simply call
arrayAdapter.notifyDataSetChanged();
to refresh the data observer and views attached with this (in our case AutoCompleteListView).
But it closes suggestions.
When I don't use notifyDataSetChanged(); it is showing all suggestions regardless of characters I have typed.
I tried it with custom filter as many suggested but none of them is helpful as I couldn't use notifyDataSetChanged().
I am posting an image to avoid confusions.
I have a confusion that why notifyDataSetChanged(); its not working. I haven't use any other reference of list with same arrayAdapter instance. I really doubt if it's a reference problem.
one of the easiest way of doing that (put the code in onCreate):
EDIT: addied wikipedia free opensearch (if https://en.wikipedia.org doesn't work try http://en.wikipedia.org)
AutoCompleteTextView actv = new AutoCompleteTextView(this);
actv.setThreshold(1);
String[] from = { "name", "description" };
int[] to = { android.R.id.text1, android.R.id.text2 };
SimpleCursorAdapter a = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, null, from, to, 0);
a.setStringConversionColumn(1);
FilterQueryProvider provider = new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
// run in the background thread
Log.d(TAG, "runQuery constraint: " + constraint);
if (constraint == null) {
return null;
}
String[] columnNames = { BaseColumns._ID, "name", "description" };
MatrixCursor c = new MatrixCursor(columnNames);
try {
String urlString = "https://en.wikipedia.org/w/api.php?" +
"action=opensearch&search=" + constraint +
"&limit=8&namespace=0&format=json";
URL url = new URL(urlString);
InputStream stream = url.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String jsonStr = reader.readLine();
// output ["query", ["n0", "n1", ..], ["d0", "d1", ..]]
JSONArray json = new JSONArray(jsonStr);
JSONArray names = json.getJSONArray(1);
JSONArray descriptions = json.getJSONArray(2);
for (int i = 0; i < names.length(); i++) {
c.newRow().add(i).add(names.getString(i)).add(descriptions.getString(i));
}
} catch (Exception e) {
e.printStackTrace();
}
return c;
}
};
a.setFilterQueryProvider(provider);
actv.setAdapter(a);
setContentView(actv, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
You have impletent the custome filter in the child class of ArrayAdapter, there in perform filter method you have to do network call and get data from server. You can set this data in your main arraylist.

Binding strings to TableView/TextView IDs

I have an Android activity that displays a list of log entries (using a cursor adapter and listview). When one of the entries is touched it kicks off an intent (passed with a bundle object containing the log details as strings) to another activity. The new activity is supposed to display the details in a custom TableView xml file I created, but I can not figure out how to bind the bundle strings to the id's defined in the TextView of the TableView.
I have included most my code below so you can see what I am trying to accomplish.
ViewEntry Class:
public class ViewEntry extends Activity{
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.view_list);
setTitle(R.string.view_entry_title);
TableView lv= (TableView)findViewById(R.id.viewlayout);
Bundle extras = getIntent().getExtras();
if (extras != null){
String date = extras.getString(plbDbAdapter.KEY_DATE);
String ident = extras.getString(plbDbAdapter.KEY_IDENT);
String type = extras.getString(plbDbAdapter.KEY_TYPE);
String from = extras.getString(plbDbAdapter.KEY_FROM);
String to = extras.getString(plbDbAdapter.KEY_TO);
String remark = extras.getString(plbDbAdapter.KEY_REMARK);
String[] from = new String[] { "date_h", "ident_h", "type_h", "from_h", "to_h", "remark_h"};
int[] to = new int[] { R.id.v_date, R.id.v_ident, R.id.v_type, R.id.v_from, R.id.v_to, R.id.v_remark };
ArrayAdapter details = new ArrayAdapter(this, R.layout.view_list, from, to);
setAdapter(details);
List<HashMap<String, String>> fillList = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map = new HashMap<String, String>();
map.put("date_h", date);
map.put("ident_h", ident);
map.put("type_h", type);
map.put("from_h", from);
map.put("to_h", to);
map.put("remark_h", remark);
fillList.add(map);
SimpleAdapter viewadapt = new SimpleAdapter(this, fillList, R.layout.view_list, from, to);
lv.setAdapter(viewadapt);
}
}
Here is view_list.xml I am trying to bind to:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/viewlayout"
android:stretchColumns="1">
<TableRow>
<TextView
android:gravity="left"
android:text="Date:"
android:padding="3dip" />
<TextView
android:id="#+id/v_date"
android:gravity="right"
android:padding="3dip" />
I know what I am trying to do isn't right but hopefully it helps illustrate my intention.
I never did find out if my approach above is possible, but I went a different direction to get the intended results. The solution I ended up using was to get the specific textview id and then set the the text with a string by using the setText() method in the code. This is probably the accepted way to approach this design issue, but it would be nice to be able to bind strings to xml instead of manipulating it with code.
I have pasted the code below for future coders reference to a solution:
public class ViewEntry extends Activity{
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.view_list);
setTitle(R.string.view_entry_title);
TextView tv_date = (TextView)findViewById(R.id.tv_date);
TextView tv_ident = (TextView)findViewById(R.id.tv_ident);
TextView tv_type = (TextView)findViewById(R.id.tv_type);
TextView tv_from = (TextView)findViewById(R.id.tv_from);
TextView tv_to = (TextView)findViewById(R.id.tv_to);
TextView tv_remark = (TextView)findViewById(R.id.tv_remark);
Bundle extras = getIntent().getExtras();
if (extras != null){
String date = extras.getString(plbDbAdapter.KEY_DATE);
String ident = extras.getString(plbDbAdapter.KEY_IDENT);
String type = extras.getString(plbDbAdapter.KEY_TYPE);
String from = extras.getString(plbDbAdapter.KEY_FROM);
String to = extras.getString(plbDbAdapter.KEY_TO);
String remark = extras.getString(plbDbAdapter.KEY_REMARK);
tv_date.setText(date);
tv_ident.setText(ident);
tv_type.setText(type);
tv_from.setText(from);
tv_to.setText(to);
tv_remark.setText(remark);
}
}

Categories

Resources