I use a CheckBox in my Activity, which is defined in "main.xml" (cbSetAll).
I also have a BaseAdapter, using "item.xml", for setting customized ListItems in a ListView in "main.xml".
Now i want to check all CheckBoxes, depending on cbSetAll. When I fetch the value of cbSetAll, the app crashes. I do this by
boolean bCheckAll = ((CheckBox) view.findViewById(R.id.cbSetAll)).isChecked();
to set the CheckBoxes in BaseAdapter by
((CheckBox)view.findViewById(R.id.cbSetItem)).setChecked(bCheckAll);
If I define
boolean bCheckAll = true;
everything works. I think, the error is, that the CB is in "main.xml" instead of "item.xml" and so the "view" is scoping in the Nirvana. Can someone give a hint?
One way to solve it is to create an additional variable in your custom adapter and set this variable from the parent activity. This way you can control the behaviour in the adapter.
You can add this variable to the constructor of the adapter.
You spotted the problem, you can't access views outside a row from inside. A quick way to do this, would be defining bCheckAll as an instance static variable of your Activity.-
static boolean bCheckAll;
In onCreate method, add a listener to cbSetAll CheckBox so that you can update bCheckAll value, and access it from you adapter's getView method.
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.
While writing my own adapter that extends the ArrayAdapter class, I came across the different constructors available and I noticed they all require a textViewResourceId parameter. So initially, I decided that I would feed my custom adapter class android.R.id.text1:
MyAdapter adapter = new MyAdapter(this, R.layout.myRow, android.R.id.text1);
However, later on during my development, I decided to override getView method where I would
TextView label = (TextView) myRow.findViewById(android.R.id.text1);
label.setText("Position #" + position);
Which worked fine. But then this question came to mind: if I'm doing the logic for how to display the row, is it really necessary to provide a textViewResourceId to the constructor when I initiate my custom adapter? Or is it the case that when you override getView, that parameter is no longer necessary? If my thinking is correct, what is the common practice for instantiating the adapter knowing that you will be overriding the display behavior anyways?
If you are overriding getView you do NOT need to specify a proper textViewResourceId.. You can pass in 0. The only time the ArrayAdapter tries to access that ID is within getView.. Since you are overriding getView and providing your own view textViewResourceId is never accessed..
Since the super class expects a view ID.. you still need to pass in a view ID into the super call.. however, it can just be 0 since it will never be used
ArrayAdapter Source confirming all of this
If you do not specify a proper textViewResourceId and do not override getView.. getView in the ArrayAdapter assumes your entire view is a TextView.. If your view is not a TextView.. you will end up with crashes from a ClassCastException..
you don't need to use any kind of build in adapter.
you can extend the BaseAdapter and make your own rules of what to show , what type of data to hold etc...
in fact , i almost never used the built in adapters that android has out of the box , because using the baseAdapter is very easy as it is.
I have a list of items which is fetched from the local database. Every item has property isNew. I want to make visible TextView with text "new" only for items which match isNew = true. I solve this problem with two ways, and now I want to know which is best method.
Method 1:
I write a class MyViewBinder which implements SimpleCursorAdapter.ViewBinder and overrides public boolean setViewValue(view, cursor, columnIndex) method with my logic next to that.
Method 2:
Create MySimpleCursorAdapter which extends SimpleCursorAdapter, overwrite getView method and wrote logic there.
Now I'm working with the second method. Can anyone suggest me which is the best method or if there any other best methods.
If, depending on the value of the column is necessary to make many changes over the item in the list, the second method is more convenient.
I have a ListView where I want each item to have an ID number attached to it (not the same as the position number). I was hoping this could be done by setting a tag to each View item in the ListView using setTag() when these Views are being created.
Right now I'm creating the ListView like this:
final ListView listview = (ListView) findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, names);
listview.setAdapter(adapter);
The names variable in the ArrayAdapter parameters above is an ArrayList, and each string value in this list also has a unique ID that I want to link to this string somehow.
Is there any way I can get access to and modify each of the Views with a tag? One idea was to create my own extended class of ArrayAdapter and override the getView() method, but I don't really understand how it works and how I would go about doing this.
Or is there a better way to link IDs with each string like this than adding tags like I'm trying to do?
Create a ViewBinder and set the tags as the ListView is being populated with whatever you need. You can check all properties of the view to determine what tag goes where, so this should be what you're looking for.
myAdapter.setViewBinder(new MyViewBinder());
public class MyViewBinder implements ViewBinder {
#Override
public boolean setViewValue(View view, Object data, String text){
//Since it iterates through all the views of the item, change accordingly
if(view instanceof TextView){
((TextView)view).setTag("whatever you want");
}
}
}
I just used this exact same answer on another question (albeit slightly different) yesterday.
about getView , it works by using a method of recycling views. i will try to explain it in a simple way.
suppose you have tons of items that can be viewed . you don't want to really create tons of views too , since that would take a lot of memory . google thought of it and provide you the means to update only the views that need to be shown at any specific time.
so , if there is an empty space on the listview , it will be filled with a new view . if the user scrolls , the view that becomes hidden is recycled and given back to you on the getView , to be updated with the data of the one that is shown instead .
for example , if you scroll down , the upper view becomes hidden for the end user , but in fact it becomes the exact same view that is on the bottom .
in order to understand how to make the listview have the best performance and see in practice how and why it works as i've talked about , watch this video:
http://www.youtube.com/watch?v=wDBM6wVEO70
as for tags , i think you want to do something else , since the data itself (usually some sort of collection, like an arrayList) already knows where to update , because you get the position via the getView . if you want a specific view to update , you might be able to do so by using a hashmap that keeps upadting , which its key is the position in the collection , and the value is the associated view . on each time you go to getView , you need to remove the entry that belong to the view (if exists) and assign the new position with the view that you got/created .
Thanks for the answers. thisMayhem's answer would probably have been easier in the end, but on my quest to learn more I ended up making my own adapter according to this tutorial. I pass down the names and the IDs into the adapter and set the names as the text of the TextViews and the IDs as the tags.
I would rather go with the solution discussed in this thread. It is always the easiest to have all related data in same place and in this case you just create a class to hold all the information you will need for every item.