I have SimpleAdapter in which I want to display an image from the Internet.
final String[] from = { ATTRIBUTE_NAME_TEXT, ATTRIBUTE_NAME_IMAGE,ATTRIBUTE_NAME_DESCRIPTION };
final int[] to = { R.id.tvText, R.id.ivImg,R.id.textDescr };
sAdapter = new SimpleAdapter(getActivity(), data, R.layout.itemvideo, from, to);
sAdapter.notifyDataSetChanged();
setListAdapter(sAdapter);
I fill the data in a separate thread
for (Element titles : title) {
m = new HashMap<String, Object>();
m.put(VideoList.ATTRIBUTE_NAME_TEXT, titles.select("a[href]").text());
m.put(VideoList.ATTRIBUTE_NAME_IMAGE, Uri.parse(titles.select("img").attr("abs:src")));
m.put(VideoList.ATTRIBUTE_NAME_DESCRIPTION,titles.select("div[style]").first().text());
m.put("link",titles.select("a[href]").attr("abs:href"));
data.add(m);
}
Displayed normal data adapter, but the picture is not displayed. if doing so
m.put(VideoList.ATTRIBUTE_NAME_IMAGE, R.drawable.ic_launcher);
then the standard output adapter icon android, but I need to display an image from the Internet
Hi you can use an Universal Image loader for this purpose, what you can do is make a custom list , before show a progress icon or dialog and later replace that with an image loaaded from the internet please visit
https://github.com/nostra13/Android-Universal-Image-Loader
It is much better to use a custom adapter as #Raghunandan suggested. You have much more control and it's not that hard.
First, create a class that extends ArrayAdapter and pass the type of object you want to handle:
public class MyCustomAdapter extends ArrayAdapter<MyObjectModel> {
Your adapter must contain a Collection (Lists are fine) of your MyModelObject objects. You can pass this list in the constructor of the adapter and keep a reference in a variable. Each object should have a property with the URL of an image.
Second, create a simple layout for each item in your list. Your layout must contain an ImageView somewhere:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" ... >
<ImageView
android:id="#+id/myImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
... />
Third, back to your adapter, you must implement the getView() method. This method returns a view, based on your custom layout, that contains the info from your MyObjectModel object at the given position in the list.
Inflate your layout : view = inflater.inflate(R.layout.custom_list_item, null);
Get your ImageView component : imageView = (ImageView)view.findViewById(R.id.myImage);
Get the object from the list : item = list.get(position);
Download the image in an asynctask or use a 3rd party tool such as Universal Image Loader, Picasso etc. Personally I use UrlImageViewHelper : UrlImageViewHelper.setUrlDrawable(imageView, item.imageURL, ...);
IMO it's the only way to have a nice and custom list because default Android options don't allow much customization.
Have a look at http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/ for some tips to improve your custom adapter.
Related
In Base adapter, I have used some imageview, can I change the image src in activity?
You should not access the adapter views directly in activity. Write a method in adapter instead. Call adapter.change image from your activity.
public void changeImage(int imgResId) {
likeButton.setImageResource(imgResId);
}
If Image src is provided from activity then you can call notifyDataSetChanged() after changing data.
Eg.
adapter = new MYAdapter(data);
list.setAdapter(adapter);
//change data here
adapter.notifyDataSetChanged();
You need to update the model data which is associated with ViewHolder after that just notify the adapter and adapter will update your item with new model data.
Take example if you have Array of 10 objects and you want to update ImageView on 5th position then update your 5th model in ArrayList and call adapter.notifyDataSetChange() it will update desired image view.
I am trying to do a data analysis And set image view visibility based on those data. Is that possible to put a variable inside a image view declaration so that I can use an array to analyse data and call the respective image view based on the variable for example
For(inti =0,i<20;i++)
Imageview(i).setvibility(gone)
This will prevent me from calling the image view over and over again .
You can solve this by creating a list of ImageViews.
List<ImageView> list = new ArrayList<>();
list.add((ImageView) findViewById(R.id.yourImageViewID);
list.add((ImageView) findViewById(R.id.anotherID);
for (int i=0;i<list.size();i++) {
ImageView view = list.get(i);
view.visible(false);
}
Now you can iterate through your views.
I have viewflipper which contains 3 childs, one GridView and two custom ListView, every view has different adapter , and every adapter has a image loader with Universal Image Loader library.
The items are the same for all adapters, my goal is to show content in different way (grid , list , and big list), but in this way every image loads 3 times. Is there any way to load images once and show them to their childs?
So you need an object common to the three views, which manages image loading and holds memory. You have it: it's the Adapter. Use a single one and just switch layouts.
For instance, you could define this method inside the adapter:
int layoutResId;
public void changeLayout(int layoutResId) {
this.layoutResId = layoutResId;
notifyDataSetChanged(); //force the adapter to call getView() again
}
Then in your getView() method you just inflate the layout defined by layoutResId.
Well the thing that you seem to be asking is if you can pass the images along to the other adapters. It would be something like if image is not empty them use it in the other views, if not then use the image loader.
public class Constants {
public static Constants INSTANCE = new Constants();
public Constants() {
}
public Uri IMAGE_PATH = Uri.EMPTY;
public File IMAGE_FILE = null;
public Bitmap IMAGE = null;
}
Presumably you would choose only one of these kinds to save from your view. And then check them to see if constants possesses an image for you to display.
I am using listview in my app.I am adding items to list with this line:
conversationsAdapter.add(user);
and this initializes list
conversationsAdapter=new ArrayAdapter<JsonObject>(this,0) {
#Override
public View getView(int c_position,View c_convertView,ViewGroup c_parent) {
if (c_convertView == null) {
c_convertView=getLayoutInflater().inflate(R.layout.random_bars,null);
}
JsonObject user=getItem(c_position);
String name=user.get("name").getAsString();
String image_url="http://domain.com/photos/profile/thumb/"+user.get("photo").getAsString();
TextView nameView=(TextView)c_convertView.findViewById(R.id.tweet);
nameView.setText(name);
ImageView imageView=(ImageView)c_convertView.findViewById(R.id.image);
Ion.with(imageView)
.placeholder(R.drawable.twitter)
.load(image_url);
return c_convertView;
}
};
ListView conversationsListView = (ListView)findViewById(R.id.conversationList);
conversationsListView.setAdapter(conversationsAdapter);
conversationsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
startChat(conversationsAdapter.getItem(position));
}
});
My list view is looking like this:
I want to update an item in the list.How can I do this ?
Example:We can write a method like: changeName when this method calls,method sets name "Tolgay Toklar" to "Tolgay Toklar Test" so I want to update custom listview item attributes.
I totally disagree with tyczj. You never want to externally modify an ArrayAdapter's list and yes it's possible to update just an individual item. Lets start with updating an individual item.
You can just invoke getItem() and directly modify the object and call notifyDataSetChanged(). Example:
JSONObject object = conversationAdapter.getItem(position);
object.put("name", data);
conversationAdapter.notifyDataSetChanged();
Why does this work? Because the adapter will feed you the same object reference used internally, allowing you to modify it and update the adapter. No problem. Of course, I'd recommend instead building your own custom adapter to perform this directly on the adapter's internal list. As an alternative, I highly recommend using the ArrayBaseAdapter instead. It already provides that ability for you while fixing some other major bugs with Android's ArrayAdapter.
So why is tyczj wrong about modifying the external list? Simple. There's no guarantee that your external list is the same as the adapters. Once you perform a filter on the ArrayAdapter, your external list and the adapters are no longer the same. You can get into a dangerous scenario where (for example) index 5 no longer represents position 5 in the adapter because you later added an item to the adapter. I suggest reading Problems with ArrayAdapter's Constructors for a little more insight.
Update: How External List Fails
Lets say you create a List of objects to pass into an ArrayAdapter. Eg:
List<Data> mList = new ArrayList<Data>();
//...Load list with data
ArrayAdapter<Data> adapter = new ArrayAdapter<Data>(context, resource, mList);
mListView.setAdapter(adapter);
So far so good. You have your external list, you have an adapter instantiated with it and assigned to listview. Now lets say at some later point, the adapter is filtered and cleared.
adapter.filter("test");
//...later cleared
adapter.filter("");
Now at this point mList is NOT the same as the adapter. So if the adapter is modified:
adapter.add(newDataObject);
You'll find that mList does not contain that new data object. Hence why external lists like this can be dangerous as the filter creates a NEW ArrayList instance. It won't continue to use your mList referenced one. You could even try adding items to mList at this point and it won't be reflected in the adapter.
If you change the data in your list you need to call notifyDatasetCanged on the adapter to notify the list that the underlying data has changed needs to be updated and.
Example
List<MyData> data = new ArrayList<MyData>();
private void changeUserName(String name){
//find the one you need to change from the list here
.
.
.
data.set(myUpdatedData);
notifyDatasetChanged()
}
I asked a question before about splitting string but maybe it wasn't clear enough.
I made a simple activity which has an example to what my problem is.
I have a message and it's a long one coming from a server.
I need to split this message and put it inside a listview, I'll show you my code.
public class Page1 extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity6);
String message = "0---12,,,2013-02-12 08:04,,,this is a test,,,0---11,,,2013-02-12 08:05,,,and this is why it is damaged,,,0---10,,,2013-02-12 08:06,,,what comes from select data randomly";
String[] variables = message.split(",");
ListView listView1 = (ListView) findViewById(R.id.listView12);
String[] items = { variables.toString() };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, items);
listView1.setAdapter(adapter);
}
}
Now let's say that the split is commas ", " so it will be
0---12 ------->ID1
2013-02-12 08:04 ------------>date1
this is a test ----------->subject1
0---11 ------->ID2
2013-02-12 -8:05 ------------>date2
and this is why it is damaged ----------->subject2
And so on, now what I can't do is that I want to put these strings in a loop and write them to a listview such that the subject1 should be in item1 and date1 should be in subitem1 like this
Subject1
Date1
------
Subject2
Date2
------
This is how the listview should look like
Can anyone help me with this please?
You would need to create a custom ArrayAdapter to populate a ListView from your objects the way you want.
The advantage of this technic is that you gain a Views recycle mechanism that will recycle the Views inside you ListView in order to spend less memory.
In Short you would have to:
1. Create an object that represents your data for a single row.
2. Create an ArrayList of those objects.
3. Create a layout that contains a ListView or add a ListView to you main layout using code.
4. Create a layout of a single row.
5. Create a ViewHolder that will represent the visual aspect of you data row from the stand point of Views.
6. Create a custom ArrayAdapter that will populate the rows according to you needs, in it you will override the getView method and use the position parameter you receive for the corrent row View to indicate the row index.
7. Finally assign this ArrayAdapter to your ListView in onCreate.
You can get an idea of how to implement this by reading this blog post I wrote:
Create a Custom ArrayAdapter
Please note that ArrayAdaper is designed for items containing only one single TextView. From the docs:
A concrete BaseAdapter that is backed by an array of arbitrary objects. By default this class expects that the provided resource id references a single TextView
Consider subclassing ArrayAdapter (docs) and override its getView method.