I have a gridview using an image adapter for the elements,
it's implemented like in this example:
http://developer.android.com/resources/tutorials/views/hello-gridview.html
Additionally I added a click listener for each item in the getView method, which sends the clicked position to the main class (outside of ImageAdapter) using a handler.
Now I want to update only the concerned imageView, but:
I don't know how to get the imageView outside of the ImageAdapter class (send with the handler? It's not serializable - create a buffer in ImageAdapter and getter?)
I'm not sure which method to use to change the image.
Currently I'm updating the whole grid each time:
((ImageAdapter)gridview.getAdapter()).setImages(imageIds);
gridview.invalidate();
ImageAdapter:
public void setImages(int[] images) {
mImages = images;
notifyDataSetChanged();
}
Thanks in advance
What you are currently doing is somewhat correct.
As an optimization, you could use an ArrayList<int> as the images and create a method in your adapter class to modify the value of a given index using ArrayList.set(int index, E element). Then calling notifyDataSetChanged() method should "theoretically" update the changed image view only :)
Related
In the layout I'm using for my custom adapter that I use to display my listview, there is a TextView. I would like to modify the value of this textview programmatically, but without clicking on anything. The new value is obtained on the main activity and is updated every 1s from a bound service. Is there a way to access the setText method of a textview in a specific row in a listview? Should I use a listener in the custom adapter to update the value?
Thanks a lot.
Yes You can do it all you need to do is datasource that is attached to the listView
e.g. ArrayList of data from where you show the initial data to the list item.
You need to update it when you got data from the service and after datasource is updated you just need to call the notifiydatasetChanged method
e.g. mAdapter.notifyDataSetChanged();
it will refresh your list with the updated data. In your case Textview text.
You can put your conditional logic inside getView() of your adapter to modify the TextView. For example , if you want to change the TextView when the listview item position is 2 , inside your getView() have something like
if(position==2){
//modify your textview as per requirement
}
Here the code:
So pretend that you already created a ListView Adapter then
if you want to edit your list view just put this code and remember dont forget to put adapter.notifyDataSetChanged();
//The Count of your array position // your getter and setter
data.set(datacount , new URLKeylistData(*Your parameter that show in UI*)
adapter.notifyDataSetChanged(); // this is important dont miss
List_lv.setAdapter(new URLKeyAdapter(getBaseContext(), data)); //set again your adapter
Please see the image to understand the question better.
I have a fragment with an ExpandableListView and few buttons.
The ExpandableListView -> has ListViews as each child elements -> each row in ListView is a combination of ImageView, TextView and a checkbox.
The ExpandableListView is populated by a CustomAdapter ( which is a separate java file from the Fragment )
Question is - how do i find out which Child of the ExpandableListView is selected, from the button.
I could store the information in SharedPreferences, but I might have to use a complex java Collections object. I want to avoid this.
Fragment and Adapter are two separate files and to my knowledge have no systematic callback.
What is the standard way of - a Fragment being able to access each of its child view's information ??
Any help or pointers welcome !! Thanks in advance.
Create a listener call back interface, something like:
public interface ListenerChildSelected
{
public void onChildSelected(int childNum);
}
Then, make your Fragment implement this listener:
public class FragmentTest implements ListenerChildSelected
Then, when you instantiate your custom Adapter, pass in the listener:
//kv 3rd parameter would be listener
CustomBaseAdapter customBaseAdapter = new CustomBaseAdapter(this, items, this);
Then, in the constructor of your CustomBaseAdapter, set a member field to the listener:
public CustomBaseAdapter(Context context, ArrayList<Item> items, ListenerChildSelected listenerChildSelected)
{
mListenerChildSelected = listenerChildSelected;
...
}
Then, every time an item is checked, call:
mListenerChildSelected.onChildSelected(rowNum);
Get the ExpandableListView in onCreateView() and store a reference to it.
In your button's anonymous onClick() handler, call getSelectedPosition() on the reference stored in step 1.
I have a Custom Array Adapter For a list view that contains an Image View. In the custom adapter class I have an asynctask that Downloads a unique picture from a unique url of each item in the list . The problem is the ImageViews for each item keeps changing pictures continously . Please what is there any problem with getting Images from urls through an AsyncTask in a custom array adapter class .
Help is needed (In any form)
Take a look of those libraries that can help you :)
Picasso
Universal Image Loader
The problem with starting an asynchronously loading things for a ListView (or any other adapter sourced view) is that Views can get reused once they are off the screen. The easiest way to deal with this is to use a library to do it for you, my favorite is AQuery
If you don't want to go that route, you'll have to role your own. To do this, you will need to check if the view at the completion of the AsyncTask is showing the same stuff as when it started. Call setTag(tag) on the View you're returning in the adapter's getView(). Then before you set the image to the ImageView, call getTag() on the view and check it equals the same object as what you set it as. It should look something like this:
final View view = MY VIEW;
final Object tag = new Object();
view.setTag(tag);
new AsyncTask() {
...
public void onPostExecute(Bitmap bar) {
if(tag.equals(view.getTag()) {
imageView.setImage(bar);
}
}
...
}.execute();
return view;
And then you can start caching and things like that. Complex right? So yeah, you should use a library.
I have seen related answers and I do not know ehich one is the appropriate for me.
I have a listView and each row has a textview. I want given some conditions, each row to get different color.(Imagine that I am getting data from a DB, and given the value I get, i want text set to different color) My code is shown below:
public class TrailsConditionScreen extends ListActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
seeTrails();
}
private void seeTrails() {
String[] help=new String[] {"foo","bar"};
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,R.layout.row,R.id.text1,help);
setListAdapter(adapter);
}
}
This code so far just prints them on the list.
Now I want when retrieving values from the db, given the value i get set a different color on each row. imagine that my codes retrieves data from a table an I want when reading the first line , given the number set the appropriate color on the first line of the listview. Then go to second lone of the db,set color for the second line of the list and so on.. i have successfully implemented the reading from the db but i do not know how to set color on specific row. In pseudo-code it looks like this.
for i=0 to number of lines in db{
read_data();
if key_value=0 then color_of_line(i)=red;
else color_of_line_i)=green;
}
Any help for this?
You must create a custom adapter to handle this instead of using the ArrayAdapter. Extend the ArrayAdapter and override the getView method. And inside the getView method based on the condition you can change the color of the text on your textView.setTextColor.
To write a custom adapter check the tutorial here (6. Tutorial: Implementing your own adapter). This example doesn't use the holder pattern but you should.
Your best bet is to extend ArrayAdapter and create your own class.
In the getView() method, execute your condition and set the color to be drawn. There are a lot of good tutorials on creating your own adapters. Check, for instance, http://www.ezzylearning.com/tutorial.aspx?tid=1763429&q=customizing-android-listview-items-with-custom-arrayadapter.
Hope it helps!
Inorder to achieve this, you will need to use a custom adapter. Since you mentioned, you are getting the data from a database, I am assuming here that you will have information in a cursor adapter. Hence, a good place to start would be to extend cursor adapter.
Within your new custom adapter, you should override getView() method. The view to be used for each item in list view is specified there. Additionally, you can also set the properties of the view there.
Depending on your business logic, you should set the text color in getView.
A tutorial here:
http://www.ezzylearning.com/tutorial.aspx?tid=1763429&q=customizing-android-listview-items-with-custom-arrayadapter
What I would do is create a CustomAdapter for the list view
public class MyCustomAdapter extends BaseAdapter
and in the funcion
public View getView(int position, View convertView, ViewGroup parent)
you have the position and you can change whatever you want.
If you search google by custom adapter listview you will get some examples
Different Color For different list item ,yes this can be achieved only if items are static only , but for dynamic content it's hard to do ...
I am having a situation where I want to update my Custom List View using BaseAdapter whenever my Database is updated. I have tried calling invalidate() on this Custom List but it didn't work, similarly I even tried having a timer to update my list after sometime, that didn't work either. Please let me know of possible solution.
Update:
This is how I am making my custom list view
li= (ListView)findViewById(R.id.id_lv_row);
ColorDrawable divcolor = new ColorDrawable(Color.DKGRAY);
registerForContextMenu(li);
li.setDivider(divcolor);
li.setDividerHeight(2);
li.setAdapter(new FriendsPositionAdapter(this));
BaseAdapter.notifyDataSetChanged() should do the trick as long as the data behind the adapter actually changed. That's all you need to do to refresh the list.
Invalidate is for repainting views only, you have to tell to the List adapter (BaseAdapter) that dataset has changed.
When the data changes, asign the new dataset to the adapter, and later call notifyDataSetChanged()...
in order to make functional notifyDataSetChanged() the adapter data must be changed. Remember that the original data that change is not reflected automatically to the adapter.
//here i retrieve the new list, named "beans"
lista = (BeanList) result.getDataObject();
Vector<Bean>beans = list.getBeanList();
((BeanListAdapter)listAdapter).syncData(beans);
((BeanListAdapter)listAdapter).notifyDataSetChanged();
//now the syncData method
public void syncData( List<PINPropiedad> newData ){
for(Object o : newData){
add(o);
}
}