I'm trying to put different images (.jpg , .png) dynamically into a ListView from res/drawable .
The names from the images I get from a database.
The images themselves are in the res/drawable folder.
This is what I already have, With an error of :D
String imgName; --> There are the img names I need from the database
Drawable drawable;
drawable = Class.appContext.getResources().getDrawable(Class.appContext.getResources().getIdentifier("com.example.test:drawable/"+imgName,null,null));
Then I get this into a ArrayList for every image in the database(+- 200 images):
ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
HashMap<String, Object> map = new HashMap<String, Object>();
map = new HashMap<String, Object>();
map.put("img",drawable);
map.put("text", "some text");
list.add(map);
Now I RETURN list;
In the Class where I call :
listReceive = Class.getImages(appContext);
listSetup = new SimpleAdapter(this, listReceive, R.layout.row,
new String[] {"img", "text"}, new int[] {R.id.IMG_CELL, R.id.TEXT_CELL});
lvList.setAdapter(listSetup);
XML row is an ImageView and a TextView.
System.out :resolveUri failed on bad
bitmap uri:
android.drawable.bitmapDrawable#405739
resolveUri failed on bad bitmap uri:
android.drawable.bitmapDrawable#405639
resolveUri failed on bad bitmap uri:
android.drawable.bitmapDrawable#405959
resolveUri failed on bad bitmap uri:
android.drawable.bitmapDrawable#405677...
... ...
I got it working when I saved images into local or SDcard memory, and then put the path inside the arraylist like:
map.put("img","/data/data/com.example.test/images/" + imgName);
I can't use this because then i will need to copy the pictures from res/drawable onto local or SD.This takes up 2 times the memory. can't have that of.
There must be a way to get images dynamically from the drawable.
Any one knows what I'm missing here?
Thanks.
The SimpleAdapter expects an integer or string that specifies a resource or image URI:
public void setViewImage (ImageView v, String value)
Since: API Level 1
Called by bindView() to set the image for an ImageView but only if there is no existing ViewBinder or if the existing ViewBinder cannot handle binding to an ImageView. By default, the value will be treated as an image resource. If the value cannot be used as an image resource, the value is used as an image Uri. This method is called instead of setViewImage(ImageView, int) if the supplied data is not an int or Integer.
I believe should use setViewBinder to provide a ViewBinder for the SimpleAdapter to handle binding the Drawable data to the ImageView. Basically, the setViewValue() method should return false unless it is called for your image view. When it is called for your image view, the method should set the data in the view and return true. The return value indicates whether the ViewBinder was able to set the view or whether the adapter should try to bind the data itself via its default behavior.
Maybe something like:
private final SimpleAdapter.ViewBinder mViewBinder =
new SimpleAdapter.ViewBinder() {
#Override
public boolean setViewValue(
final View view,
final Object data,
final String textRepresentation) {
if (view instanceof ImageView) {
((ImageView) view).setImageDrawable((Drawable) data);
return true;
}
return false;
}
};
...
listSetup .setViewBinder(mViewBinder);
I've done a similar thing with a SimpleCursorAdapter and its ViewBinder.
The simple adapter expects String in the map. But your map contains a drawable for the key "img".
Instead try extending the BaseAdapter class. Override the getView method and then manually set the drawable to the imageview and text to textview.
Another thought, it might not be a good idea to keep every drawable in memory. Rather get the drawable dynamically while rendering that particular row of the list
This following method or way also works - if anyone is still interested
List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
Integer flags[] = new Integer[listdetail.size()];
Resources resources = getResources();
for (int i = 0; i < listdetail.size(); i += 2) {
listName = listdetail.get(i).getName();
int dynamicId = resources.getIdentifier(listdetail.get(i).getName().replaceAll(" ", "").toLowerCase(), "drawable", getActivity().getPackageName());
if(dynamicId == 0) {
dynamicId = R.drawable.test_image;
flags[i] = dynamicId;
}else {
flags[i] = dynamicId;
}
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("value1", listdetail.get(i).getName());
hm.put("valueImage1", Integer.toString(flags[i]));
list.add(hm);
}
String[] from = { "value1", "valueImage1"};
int[] to = { R.id.textview, R.id.imageView };
SimpleAdapter adapter = new SimpleAdapter(getActivity().getBaseContext(), list, R.layout.listlayout, from, to);
ListView listView = (ListView) getActivity().findViewById(R.id.listview);
listView.setAdapter(adapter);
Related
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().
I have a listview which i want it for displaying a text and corrs image. I have used an arrayadapter for it. I am able to get an arraylist of hashmaps containing the values of the text and the url for the image.
<Arraylist<Hashmap<String,string>> testdata : "name" and "image_url"
Now i am trying to bind it. But no image is shown and the logcat shows resolveuri failed on bad bitmap.
( my url is "/com.example.vocab.MainActivity/res/drawable-hdpi/right_icon.png" ). What am i doing wrong? Thanx in advance for any help.
// Binding resources Array to ListAdapter
this.setListAdapter(new SimpleAdapter(Grammar_tab_all.this, testdata ,
R.layout.list_item, new String[] { "name","img_url"},
new int[] { R.id.module_name_item, R.id.img_recom}));
final ListView lv = getListView();
To show the drawable images in listview, best method is to store only the int id of drawable image.
Try this.
listItems = new ArrayList<HashMap<String,Integer>>();
String fieldName = "image_id";
HashMap<String, Integer> listData1 = new HashMap<String, Integer>();
HashMap<String, Integer> listData2 = new HashMap<String, Integer>();
listData1.put(fieldName, R.drawable.camera_icon_focus_dim);
listData2.put(fieldName, R.drawable.camera_icon_scene_mode);
listItems.add(listData1);
listItems.add(listData2);
SimpleAdapter listItemAdapter = new SimpleAdapter(
this,
listItems,
R.layout.image_list_item,
new String[] { fieldName },
new int[] { R.id.listitem_img });
Instead of this <Arraylist<Hashmap<String,string>> testdata try with this <Arraylist<Hashmap<String,Object>> testdata if you need more refer this link http://developerboards.att.lithium.com/t5/AT-T-Developer-Program-Blogs/Developing-Apps-for-Android-Beyond-quot-Hello-World-quot-Part-I/ba-p/28983/page/2
You have to use a custom list view :
check out this website
http://blog.sptechnolab.com/2011/02/01/android/android-custom-listview-items-and-adapters/
If you use images from android resources folder then you can use the
// get Drawable from resources folder
Resources res = context.getResources();
Drawable drawable = res.getDrawable( R.drawable.myImage );
ImageView mImageView.setImageDrawable( mDrawable );
// or
ImageView mImageView.setImageBitmap( mBitmap );
The ImageView is the one from your ListItems layout. I wrote for every ListView a own ListAdapter in which i inflate the special layout and set the data to the layout.
You need a custom listadapter if you want to have different images and this one is the best tutorial I have ever found on internet about this topic :)
I'm creating a game and here's the code I'm using to show a list of games with the user names, score, date etc. But how do I get the values of the TextViews tv_playerScore and tv_opponentScore so I can compare them and change the textColors of them? Because what I want is to parseInt and see which has the highest value and set its textcolor to green, and the others textcolor to red.
private void showGames(JSONArray games) throws JSONException {
ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map = new HashMap<String, String>();
for (int i = 0; i < games.length(); i++) {
map.put("challenger", games.getJSONObject(i).getString("challengerName"));
map.put("active", games.getJSONObject(i).getString("active"));
map.put("opponent", games.getJSONObject(i).getString("opponentName"));
map.put("date", games.getJSONObject(i).getString("date"));
map.put("gameID", games.getJSONObject(i).getString("gameID"));
map.put("amount", games.getJSONObject(i).getString("amount"));
map.put("playerScore", games.getJSONObject(i).getString("challengerScore"));
map.put("opponentScore", games.getJSONObject(i).getString("opponentScore"));
if (Integer.parseInt(games.getJSONObject(i).getString("active")) == 2) {
mylist.add(map);
}
map = new HashMap<String, String>();
}
SimpleAdapter sadapter = new SimpleAdapter(this, mylist, R.layout.list, new String[]
{"amount", "active", "gameID", "challenger", "opponent", "date", "playerScore", "opponentScore"},
new int[] {R.id.tv_amount, R.id.tv_activte, R.id.tv_gameID, R.id.tv_player, R.id.tv_opponent, R.id.tv_date, R.id.tv_playerScore, R.id.tv_opponentScore});
listView.setAdapter(sadapter);
}
If you want to get the values of a textview must use findViewById function from Activity.
TextView tv_playerScore = (TextView) findViewById (R.id.tv_playerScore);
If the showGames() method is not a class that inherits from Activity (or similiar), you should make a setter injection of the elements of sight to those who want to access.
To compare:
tv_playerScore.getText().toString().compareTo(tv_opponentScore.getText().toString());
Finally, to change the color:
tv_playerScore.setTextColor(Color.CYAN);
Regards.
I think you should have a closer look in how ListViews work ( http://developer.android.com/resources/tutorials/views/hello-listview.html )
In short I guess you'll have to write your own Adpater class (e.g. extend SimpleAdapater) and write over its getView method. Here you can set the color of the textviews depending on the according value. (I think it would make sense to have them sorted before instead of checking them every time a list element is drawn...
Is it possible to pass both strings and drawables as objects in the same HashMap, and then use this hashmap to populate a ListView via SimpleAdapter ?
I want this because I first get JSON data which also contains the URL to a thumbnail. Then I download this thumbnail. Relevant code (I think):
for (...) {
...
InputStream is = (InputStream)content;
Drawable image = Drawable.createFromStream(is, "src");
// Hashmap
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("title", new String(jsonObject.getString("Title")));
map.put("thumb", image);
mylist.add(map);
}
ListAdapter adapter = new SimpleAdapter(getActivity(), mylist, R.layout.listitem,
new String[] { "title", "thumb"},
new int[] { R.id.title, R.id.thumb });
setListAdapter(adapter);
R.id.title = TextView, and R.id.thumb = ImageView
This works for the title string, but not for the drawable. Is this approach just stupid?
Thanks in advance.
you should create a XML layout file for your row representation in the list and a custom adapter that inflate your row
As far as I can tell from the SimpleAdapter documentation, ImageViews are supported only for binding with a resource identifier or a String, which (the String, I mean) must represent an image resource or an image URI. It won't work if you pass it directly a Drawable object.
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);