I created a listview with a custom adapter. The items have a checkbox next to them for each item in the array list/listview.
I basically want to set the values of the objects in the array list to true if they are clicked.
Looked in to isChecked() method But I'm having trouble understanding how it checks each checkbox for each item in the list when I only have 1 checkbox in my layout
I have a decent amount of java knowledge but trying to transfer the code I created there into a workable app has proven difficult.
Attaching your implementation would be helpful but here is the general idea:
Your ListView (hopefully RecyclerView, but not mandatory) contains logic for how to lay out particular items in the list of data that fuels it. These reusable layouts and UI components are maintained in the ViewHolder pattern (which explains your single check box in the layout but you see 10 on the screen if your list has 10 items in it). In each ViewHolder you have access to its respective CheckBox so you can setup a listener on the CheckBox to subscribe to its state changes (being checked or unchecked). Inside the listener, you can call a function to update an element in your list. ViewHolders have a nice variable internal to them called adapterPosition which, as you may have guessed, is the VH's position in the adapter (zero based). This is usually super helpful since you can pass this variable around or reference your list directly with the index and it will match up to the correct item in your list.
Hope this helps, and I would be more than happy to assist you with the implementation if you provide some code samples!
You can add one boolean parameter i.e. isSelected to model class that is used in adapter.
add listener to checkbox
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//update isChecked value to model class of list at current position
list.get(position).setChecked(isChecked);
}
});
Then you can easily get checked items from data list of adapter.
Related
I am writing my self a ListView that will contain multiple types of items. I have done that using ArrayAdapter and a ListView now my issue is that I need to have some Items inside my Adapter that is gonna expand and that will have inner items of any type. Now the issue is how can I do this? I know I can use ExpandableListView but I don't need some items to be expanded. I saw this post about something similar, The person suggested to use ExpandableListView or a Custom Item, I would like to do the Custom Item but my concern is that the OP of the answer quoted this.
If the number of items is low consider using a linearlayout to look
like a listview and another linearlayout for the last item.
I'm not sure what they mean by "low" How many items can I have inside it? Would it cause lag?
so my question is what is the best way to do this? I need to put items
in a ListView that is of multiple types, and one of the types can
expand and have inner views that can again contain the same types and
so on.
Edit: Since 2 of you confused of what I want. I want to do the following inside my ArrayAdapter
Item
Item
Item
ExpandableItem {
Item
Item
Item
Item
}
Item
Item
I am trying to make some of the Items expand to have more items inside them and control the onClick of the inner items and such.
About the meaning of "low": I think it's about performance but devices today are better than devices were in 2013 when the linked post was written - maybe you'll never experience a sluggish UI with your approach. Of course this depends not only on your UI structure but also on the type of data you'll be showing (videos or just text?) and on other factors like does the device have to perform heavy work in the background or not.
RecyclerView was developed to be a "better ListView", so if performance can be an issue, then maybe it is a good choice. (The adapters for both ViewGroups can handle different View types but RecyclerView offers a better means of showing changes to single items and customizing change animations, another point in its favor)
How can I do this?
Have different View types for expandable and flat items
You can "manually" expand/ shrink a View (AFAIK your only choice when working with ListView) by using some type of animation (or the Transition framework) but you always have to...
Keep track of the expanded state of each expandable item (e.g. in the Adapter) and use them in getView() respectively onBindViewHolder().
Add another ListView like RecyclerView on clicking of any item.
I have a RecyclerView that displays a list of applications currently installed on the device. Each row includes the name of the application, its package name, and a switch. When the Switch isChecked, the package name is added to an ArrayList. If the user clicks back into that Activity, I need to repopulate the list and set the state of Switches based on what was previously added to the ArrayList.
The overall idea I have to achieve this is to do a comparison of the package names in the RecyclerView to those stored in the ArrayList, and when there is a match the Switch for that row needs to be set to checked.
I am not sure how to best accomplish this. I think it needs to be done in the Activity using the Adapter, not the Adapter itself. I know it is also going to involve a loop.
Anyone have any idea how to achieve this?
OP (30 Jan 2018): https://coderanch.com/t/690164/mobile/Set-Switch-State-Based-Comparison
You could implement it like this:
Your Adapter gets handed in a list of ViewModels that have
String displayName;
String identifier;
boolean isChecked;
Your Adapter could notify a Listener
interface AdapterListener {
void onSwitchChanged(ViewModel viewModel);
}
Ýour listener could be a Presenter or a ViewModel. Your listener might also manage all your ViewModels (as he may have created or got them from another instance). When you need your ArrayList, you can
a) instantiate it on demand (iterate your ViewModels and extract those that are checked)
b) your Listener can manage the List directly. You can make a List<String> and add / remove the app-identifiers. You do not need to loop through, you can just call list.remove("THEAPPIDKEY"); and the list will correctly delete the key you wanted to remove.
I usually have the Adapter class as a sub class within my Activity class. This way, the Adapter can access fields belonging to the Activity.
In any case, the adapter has to know about the values it should show as 'switched on'. So, if you have a separate class for the Adapter you'll need to pass your ArrayList to the adapter (e.g. via its Constructor).
Store the data in a custom class and create an array list from that. When that list is passed to the adapter you can pull the value back out.
class PhoneItem{
boolean switchState;
String blah;
String foo;
}
//get the data from the originating class
ArrayList<phoneItem>phones = new Arraylist();
mMySwitch.setChecked(phones.get(viewHolderCount).switchState);
I have list/rows of checkboxes inside recycle view. In my case, the user can only select 3 checkboxes out of many. As soon as the user selects the third checkbox, I want to disable rest of the checkboxes in different rows.
I am capturing selecting/deselecting checkboxes inside adapter class.
As far as I know, I can enable/disable checkboxes inside onBindViewHolder class.
But in my case, I want to enable/disable checkboxes, after they have been rendered.
One of the approaches I can think is, to call notifyDataSetChanged(); from Activity class and then rerender all the recycled view.
But I hope there is the better way than doing this, inside the adapter class itself.
ps: I am new to android/java.
notifyDataSetChanged() will defently work in your case.
Please note that you don't have to call this method from the Activity.
You can call it internally within your adapter after the third checkbox was selected.
From the top of my head, One way to do this would be to store the "checked" positions indide an array within the adapter, then inside onBindViewHolder() check to see if the current position should be enabled or disabled.
In your model class you can have a boolean variable that decide whether the item should be enabled or not and another boolean variable to keep track of the checked state, or if the item is checked or not. In onBindViewHolder check the variable to enable or disable the item.Keep track of the selected items and then after every check and uncheck, check if the selected items exceeds the limit. Then loop through your items and then check if the item is checked or not. if the item is not checked set the value to false and after the loop send a notifyDataSetChanged() and in onBindViewHolder() check for the value and enable or disable the item/checkbox
You can use SparseBooleanArray to record all the changes for each item based on their positions.
You can use the following method in RecyclerView adapter:
notifyItemInserted(int)
notifyItemRemoved(int)
notifyItemRangeChanged(int, int)
notifyItemRangeInserted(int, int)
notifyItemRangeRemoved(int, int)
Read more at RecyclerView.Adapter.
Only use notifyDataSetChanged() as the last resort. Because calling notifyDataSetChanged() will force the views to rebind and relayout. As in the documentation says:
void notifyDataSetChanged ()
Notify any registered observers that the data set has changed.
There are two different classes of data change events, item changes
and structural changes. Item changes are when a single item has its
data updated but no positional changes have occurred. Structural
changes are when items are inserted, removed or moved within the data
set.
This event does not specify what about the data set has changed,
forcing any observers to assume that all existing items and structure
may no longer be valid. LayoutManagers will be forced to fully rebind
and relayout all visible views.
RecyclerView will attempt to synthesize visible structural change
events for adapters that report that they have stable IDs when this
method is used. This can help for the purposes of animation and visual
object persistence but individual item views will still need to be
rebound and relaid out.
If you are writing an adapter it will always be more efficient to use
the more specific change events if you can. Rely on
notifyDataSetChanged() as a last resort.
how to update ReyclerView adapter without make OnCreateViewHolder(...) being called?
Because when i do
mRecyclerView.getAdapter().notifiItemChanged(position)
it goes inside OnCreateViewHolder(...) what i don't want to. The reason why i don't want is because I have expanded item view and onCreateViewHolder(...) will reinflate it so make collapsed. I only want to OnBindViewHolder(...) being called
Have anyone faced with it?
UPD:
Just found that OnCreateViewHolder(...) is called only one first time, in all next times it's not being called. What is the reason?
t
You could add a boolean isExpanded to your data objects in your dataset, and then in the onBindViewHolder method check whether isExpanded is true, if so expand the view programmatically. (and ofcourse don't forget to switch the boolean when expanding/collapsing the view)
This is the whole point of RecyclerView : it handle a pool of view holders, which are created once (calling OnCreateViewHolder()) then reused (or recycled, hence the view name) as much as possible via OnBindViewHolder().
OnCreateViewHolder() is used to create the views, while OnBindViewHolder (re)set the views state (like text content, selected state, ...)
It follows that any state associated with an item (like the expanded / collapsed state) should not be stored in the ViewHolder. You can for example use a private List in the adapter.
I tried to found a method, but no results. I want a ListView like below, and when I click on an element, like "Word", it'll be like this picture :
Is it possible ?
What you described is what an ExpandableListView does.
Basically it's like a listview so you'll still have to create your own adapter, but it lets you click a row to inflate a bigger item that you can then stuff your text into.
I would recommend creating your own class that extends ArrayAdapter or BaseAdapter. Then you can make use of the getView() method that gets called every time the screen gets redrawn for the user. You can then design multiple views for each selection and choose which one to display in the getView() function. So when the user selects an item, you set a flag in your custom class, and then notifyDataSetChanged() and you're good to go!