Setting checkbox dynamically from sqlite in a Fragment - android

I'm having trouble figuring out the best way to store and display checkboxes in a listview.
Right now I have the code in the getView method:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
//final ViewHolder holder;
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.grid_item, null);
}
ImageView img = (ImageView) convertView.findViewById(R.id.grid_item_img);
cb = (CheckBox) convertView.findViewById(R.id.chk_box_griditem);
if(photos.get(position).getIshidden()){
cb.setChecked(false);
}else{
cb.setChecked(true);
}
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
MySQLiteHelper db = MySQLiteHelper.getInstance(getActivity());
Log.d("checkbox", "status: " + photos.get(position).getIshidden());
if (isChecked) {
photos.get(position).setIshidden(true);
cb.setChecked(true);
Log.d("checkbox", "isChecked");
db.updatePhoto(photos.get(position));
} else {
photos.get(position).setIshidden(false);
cb.setChecked(false);
Log.d("checkbox", "isCheckedelse");
db.updatePhoto(photos.get(position));
}
}
});
imageLoader.displayImage(imgUrls[position], img, options, animateFirstListener);
//img.setImageResource(mImgRes);
return convertView;
}
The db helper takes a photo object as an argument and updates the row if it exists. So right now I update the current photo object isHidden() to be true or false then pass the updated object to db helper.
The physical database seems to be updating correctly. However a problem occurs when the checkboxes state is being set. The checkboxes seem to be randomly set as checked or unchecked.
Also I feel like doing this in the getView is cpu greedy but am not sure how else to do this.

First remove cb.setOnCheckedChangeListener...You do not need to set the OnCheckedChangeListener every time getView is called.you have already written the below code which will set check-box state(checked or unchecked) when list-view loads.
if(photos.get(position).getIshidden())
cb.setChecked(false);
else
cb.setChecked(true);
Now set onItemClick listener as below on list view :
mListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,long arg3)
{
MySQLiteHelper db = MySQLiteHelper.getInstance(getActivity());
Log.d("checkbox", "status: " + photos.get(position).getIshidden());
if(photos.get(position).getIshidden())
{
((CheckBox)arg0.getChildAt(position).findViewById(R.id.chk_box_griditem)).setChecked(true);
photos.get(position).setIshidden(false);
db.updatePhoto(photos.get(position));
}
else
{
((CheckBox)arg0.getChildAt(position).findViewById(R.id.chk_box_griditem)).setChecked(false);
photos.get(position).setIshidden(true);
db.updatePhoto(photos.get(position));
}
}
});
by that way you can check or uncheck the check-box and at the same time the check-box state(checked or unchecked) will be saved in your database.
I hope it will work.If not let me know..:)

When you are initializing your checkbox you set the Check state to false if the image is hidden.
if(photos.get(position).getIshidden()){
cb.setChecked(false);
}else{
cb.setChecked(true);
}
But in the Listener you set the image to hide when the checkbox is checked.
if (isChecked) {
photos.get(position).setIshidden(true);
...
This is actually the inverse. You are probably disturbed by that.
And you do not have to set the checked state again in the listener.
So your code in the listener could look like this:
if (isChecked) {
photos.get(position).setIshidden(false);
Log.d("checkbox", "isChecked");
db.updatePhoto(photos.get(position));
} else {
photos.get(position).setIshidden(true);
Log.d("checkbox", "isCheckedelse");
db.updatePhoto(photos.get(position));
}

1) Do not set the checkbox in the listener
2) Attach the listener in the checkbox only if convertView is null (i.e. when inflating). When you get your view from the convertview it has its listener set already.

Change and then log. OnCheckedChange you can get away with no if statements and just use the boolean. You don't need to set the value in of the check box in the checkedchanged listener. Intialize db in onResume so it's available no telling how many times a user will click something and the db initialization will slow things down.
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
photos.get(position).setIshidden(isChecked);
db.updatePhoto(photos.get(position));
Log.d("checkbox", isChecked.toString());
}
});
#Override
protected void onResume() {
if (db==null) {
db = MySQLiteHelper.getInstance(getActivity());
}
}

Related

How to fix Checkbox in RecyclerView when no solution works?

I'm trying to set up a checkbox in my recycler view, but I'm facing the common problem of random checks without my control. I check one item and some more random items are being checked at the same time.
I realise this is a common question here, but the solutions I found here don't seem to work. Among many others I was trying to follow different instructions in this thread:
Android RecyclerView checkbox checks itself
but what seems to be the problem is that functions isSelected and setSelected can't be resolved.
My best guess is that the reason for this complication might be that my onCheckedChange action is actually interfaced from the main activity, as you can see at the bottom of the code below. Is that what complicates the code (can't avoid it)?
public LocationRecyclerViewAdapter(List<IndividualLocation> styles,
Context context, ClickListener cardClickListener, OnCheckedChangeListener checkedChangeListener, int selectedTheme) {
this.context = context;
this.listOfLocations = styles;
this.selectedTheme = selectedTheme;
this.clickListener = cardClickListener;
this.onCheckedChangeListener = checkedChangeListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int singleRvCardToUse = R.layout.single_location_map_view_rv_card;
View itemView = LayoutInflater.from(parent.getContext()).inflate(singleRvCardToUse, parent, false);
return new ViewHolder(itemView);
}
public interface ClickListener {
void onItemClick(int position);
}
public interface OnCheckedChangeListener {
void onCheckboxClick(int position);
}
#Override
public int getItemCount() {
return listOfLocations.size();
}
#Override
public void onBindViewHolder(final ViewHolder card, int position) {
final IndividualLocation locationCard = listOfLocations.get(position);
card.nameTextView.setText(locationCard.getName());
card.addressTextView.setText(locationCard.getAddress());
card.hoursTextView.setText(locationCard.getHours());
card.priceTextView.setText(locationCard.getPrice());
card.categoryTextView.setText(locationCard.getCategory());
card.cuisineTextView.setText(locationCard.getCuisine());
card.happyHourTextView.setText(locationCard.getHappyHour());
card.lunchDealTextView.setText(locationCard.getLunchDeal());
card.websiteTextView.setText("WEBSITE");
card.newPlaceTextView.setText(locationCard.getNewPlace());
card.websiteTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String url = locationCard.getWebsite();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
context.startActivity(intent);
}
});
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView nameTextView;
TextView addressTextView;
TextView priceTextView;
TextView hoursTextView;
TextView categoryTextView;
TextView cuisineTextView;
TextView happyHourTextView;
TextView lunchDealTextView;
TextView newPlaceTextView;
ConstraintLayout constraintUpperColorSection;
CardView cardView;
ImageView backgroundCircleImageView;
ImageView emojiImageView;
Button websiteTextView;
CheckBox checkBox;
ViewHolder(View itemView) {
super(itemView);
nameTextView = itemView.findViewById(R.id.location_name_tv);
addressTextView = itemView.findViewById(R.id.location_description_tv);
priceTextView = itemView.findViewById(R.id.location_price_tv);
hoursTextView = itemView.findViewById(R.id.location_hours_tv);
backgroundCircleImageView = itemView.findViewById(R.id.background_circle);
emojiImageView = itemView.findViewById(R.id.emoji);
constraintUpperColorSection = itemView.findViewById(R.id.constraint_upper_color);
categoryTextView = itemView.findViewById(R.id.location_type_tv);
cuisineTextView = itemView.findViewById(R.id.location_cuisine_tv);
happyHourTextView = itemView.findViewById(R.id.happyhour_tv);
lunchDealTextView = itemView.findViewById(R.id.lunchdeal_tv);
cardView = itemView.findViewById(R.id.map_view_location_card);
websiteTextView = itemView.findViewById(R.id.website);
newPlaceTextView = itemView.findViewById(R.id.new_place);
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
clickListener.onItemClick(getLayoutPosition());
}
});
checkBox = itemView.findViewById(R.id.checkBox);
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
onCheckedChangeListener.onCheckboxClick(getLayoutPosition());
}
}});
}
#Override
public void onClick(View view) {
}
}
}
I'm sure there is some simple solution to this, but I've been cracking my head over this for way too long now. Thanks!
First of all, you have to check the checkbox programatically, for every item. Your model should hold the data, a simple boolean could do it.
The second is the trickiest one
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(buttonView.isPressed()){
if (isChecked ) {
onCheckedChangeListener.onCheckboxClick(holder.getAdapterPosition()());
}}
}});
You have to check if the checkbox is actually checked, in order to avoid confusions,
Inside your onBindViewHolder you have to set your checkbox either checked or unchecked. if true, your checkbox will be selected, else unselected,
because recycler view will be recycled every time you scroll, so you need to make sure you need to tell adapter that checkbox need to be checked or unchecked at that particular position.
why are you using getLayoutPosition() for getting checkbox position
use like this holder.getAdapterPosition()
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
onCheckedChangeListener.onCheckboxClick(holder.getAdapterPosition()());
}
}});
and move this listener to your onBindViewHolder()
Your data model should have a boolean variable isChecked. You can also give it an default value false. Now, in your adapter function onBindViewHolder, you should set value of your checkbox ex.
card.checkBox.setChecked(locationCard.getIsChecked())
Also, in your onCheckedChanged you should update your data
locationCard.setIsChecked(isChecked)
Now each time your RecyclerView Adapter reuses and list item, it will set the value of its checkbox correctly. Hope this helps.

Checked checkbox outside the adapter class on listView

In my Activity i have a list view and a check box.I created an adapter and do all stuff about it.In adapter i have 4 checkbox that loaded into list view.
I want to when user check this man checkBox in activity all checkBoxs on adapter is checked so in order to In activity first i find check box and finally i override setOnCheckedChangeListener method.
To find out number of view in adapter i am using TmpAdp.getCount().TmpAdp is my instance adapter.
This is a completed code :
chb_allCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
for (int i = 0; i < TmpAdp.getCount(); i++) {
View view = Glist.getChildAt(i);
CheckBox ch_item = view.findViewWithTag(i);
// CheckBox ch_item = view.findViewById(R.id.chb_send_info); // this is not work like findViewWithTag
ch_item.setChecked(true);
}
TmpAdp.checkAll(TmpAdp.getCount());
TmpAdp.notifyDataSetChanged();
} else {
}
}
});
The problem is, when i checked mani check box (chb_allCheck), none of them of check boxs inside adapter is not checked ?
This is a part of adapter class and getView method:
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) Tmpcontext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.liststyle_saveed, parent, false);
BtnChangeToInPross = rowView.findViewById(R.id.BtnChangeToInPross);
TextView txtNosaziCodestr = rowView.findViewById(R.id.NosaziCodestr);
checkBox = rowView.findViewById(R.id.chb_send_info);
checkBox.setTag(position);
As you can see when i have clicked on Main check boxs, none of them of check box inside adapter is not checked
First of all make a Model class. In which you will take boolean isChecked.
Now in adapter class you will attach that model boolean to the list item checkbox.
checkbox.setChecked(model.isChecked());
When you check your main checkbox. Then just change isChecked boolean in your model list.
boolean isChecked = mainCheckBox.isChecked();
for(Model model : adapter.getList()){
model.setChecked(isChecked);
}
adapter.notifyDataSetChanged();
Here when you change checked status of model and notify your list. Then all your checkBox will be checked automatically, because these are attached to the model checked field.
It is logic, I did not write full code, you will make Model class, and will attach model by your list item.
Create a model class and make getter and setter method for check and uncheck Checkbox
Click of Main Checkbox in Activity
chb_allCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean
for (int i = 0; i < yourList.size; i++) {
if(checked){
yourlist.get(i).setCheckBoxAdapter(true);
}
else{
yourlist.get(i).setCheckBoxAdapter(false);
}
}
TmpAdp.notifyDataSetChanged();
}
});
in yourAdapterClass
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
CheckBoxModelClass modelclass= getItem(position);
if(modelclass.getCheckbox()){
adapterCheckBox.setChecked(true);
}
else{
adapterCheckBox.setChecked(false);
}
return convertView;
}
Tank you of your guys, You have made good suggestions but let me complete my way.
My problem was TmpAdp.notifyDataSetChanged();.When i removed this, code work completally.
I have completed my code and works perfectly and it can be an additional way to Select
all checkbox.
chb_allCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
for (int i = 0; i < TmpAdp.getCount(); i++) {
View view = Glist.getChildAt(i);
CheckBox ch_item = view.findViewById(R.id.chb_send_info);
ch_item.setChecked(true);
}
TmpAdp.checkAll(TmpAdp.getCount());
} else {
for (int i = 0; i < TmpAdp.getCount(); i++) {
View view = Glist.getChildAt(i);
CheckBox ch_item = view.findViewById(R.id.chb_send_info);
ch_item.setChecked(false);
}
TmpAdp.removeAll();
}
}
});

onClickListener in getView() method messes up MultiChoiceModeListener()

So I have a GridView that implements the multiple choice mode listener , and every time the user taps the item it should change it's background image ; and when he/she long taps , the multi choice toolbar should appear.
However since I have on click listener in getView() it somehow blocks the other one.
(if I remove the listener from getView() , the other one works just fine)
Any advices ?
Here's my code:
MultiChoiceListener:
gView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
checkedPos = new SparseBooleanArray();
gView.setMultiChoiceModeListener(new GridView.MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
currentArray = gView.getCheckedItemPositions();
int itemCount = gView.getCheckedItemCount();
switch (itemCount){
case 1:
mode.setSubtitle("One item selected.");
break;
default:
mode.setSubtitle(itemCount + " items selected.");
break;
}
...
getView():
convertView.setLongClickable(true);
final Holder finalHolder = holder;
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!pressed) {
finalHolder.img.setBackground(ContextCompat.getDrawable(context, R.drawable.ic_pause_bg));
pressed = true;
}
else{
finalHolder.img.setBackground(ContextCompat.getDrawable(context, R.drawable.ic_noise_bg));
pressed = false;
}
}
});
Thank you for your time!
Nevermind, I worked it out. I'm going to leave my answer if someone needs a solution for the same problem.
First of all forget about the listener in the getView() method , instead go where you have the code for your MultiChoiseModeListener and call setOnItemClickListener() for your gridView -> using the id of the image you want to change constantly:
gView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.setSelected(true);
ImageView image = (ImageView) view.findViewById(R.id.noise_image); //use the id given in your layout
if(!itemPressed.get(position)) {
image.setBackground(ContextCompat
.getDrawable(mContext, R.drawable.ic_running));
itemPressed.put(position,true);
}
else{
itemPressed.put(position,false);
image.setBackground(ContextCompat.getDrawable(mContext,R.drawable.ic_normal));
}
Doing so, both listeners will work.
Notice that itemPressed is a Map in order to memorize
which item was clicked so when changing background images , there is
no confusion.

Dynamically add and hiding textViews

I've got "for each" loop that creates textView for every obiect from the list and add them to the linear layout. It works great. Then I want to hide all of the textViews when user clicks on toggle button but here I've got problem - only the last textView from the list is being hidden , rest of them is still visible. I tried to solve this problem with many solutions ( for example with getChild()), but nothing works.
final List<FilterItem> filterItemList = filterData.getFilterItemList();
for (FilterItem filterItem : filterItemList) {
final TextView filter = new TextView(MainPanelActivity.this);
filter.setText(filterItem.getFilterItemName());
filter.setTextColor(R.color.black);
linearLayout.addView(filter);
filter.setVisibility(View.GONE);
textLine.setOnCheckedChangeListener(
new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
filter.setVisibility(View.VISIBLE);
} else {
filter.setVisibility(View.GONE);
}
}
});
Note that youre setting a listener for textLine inside the for loop - so for each iteration you set a new listener that changes the visibility of the TextView created in the current iteraton.
Move textLine.setOnCheckedChangeListener() outside of the for loop; and inside onCheckedChanged - loop through all children of linearLayout and set the visibility for each child.
textLine.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
for (View v : linearLayout.getChildren()) {
if (v instanceof TextView) {
if (isChecked) {
v.setVisibility(View.VISIBLE);
} else {
v.setVisibility(View.GONE);
}
}
}
You could keep a list of TextViews when you create them. Then set the click listener outside the for-loop as Dmitri says, which would iterate through the list of TextViews and set the visibility to GONE.
private void setup() {
List<View> textViews = new ArrayList<>();
for (FilterItem filterItem : filterData.getFilterItemList()) {
View view = createTextViewFor(filterItem);
linearLayout.addView(filter);
textViews.add(view);
}
updateVisibility(textViews, View.GONE);
textLine.setOnCheckedChangeListener(
new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int visibility = isChecked ? View.VISIBLE : View.GONE;
updateVisibility(textViews, visibility);
}
}
);
}
private View createTextViewFor(FilterItem filterItem) {
TextView view = new TextView(MainPanelActivity.this);
view.setText(filterItem.getFilterItemName());
view.setTextColor(R.color.black);
view.addFilter(filterItem);
return view;
}
private void updateVisibility(List<View> views, int visibility) {
for (View view : views) {
view.setVisibility(visibility);
}
}
In case you want to display textView dynamically, I think putting textView inside RecyclerView will be a better idea. RecyclerView has its own Adapter which will make it easy to play with data and textViews. Give recyclerView a try. RecycerView for what you are trying to do can be learnt in few hours and sky is the limit for what you can do with recyclerView :)

Check and Uncheck All CheckBoxes in ListView

I was surprised that I couldn't find an existing answer on Stack that I could use for this, so here I am.
I have a ListFragment with a list attached to a SimpleCursorAdapter comprised of the rows defined by the following row.xml file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="6dip" >
<CheckBox
android:id="#+id/story_check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:focusable="false"
android:focusableInTouchMode="false" />
<TextView
android:id="#+id/story"
android:layout_width="wrap_content"
android:layout_height="24sp"
android:lines="1"
android:scrollHorizontally="true"
android:singleLine="true"
android:layout_alignBaseline="#+id/story_check_box"
android:layout_alignBottom="#+id/story_check_box"
android:layout_toRightOf="#+id/story_check_box" />
</RelativeLayout>
I connect the list with the adapter with the following code in my ListFragment:
adapter = new SimpleCursorAdapter(getActivity(), R.layout.row, null, new String[] { CProvider.Stories.TITLE }, new int[] { R.id.story }, 0);
setListAdapter(adapter);
I then try to use a CheckBox in my fragment to toggle all the list checkboxes as follows:
CheckBox selectAll = (CheckBox) rootView.findViewById(R.id.select_check_box);
selectAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final ListView listView = getListView();
for(int i=0; i < getListAdapter().getCount(); i++){
View view = getViewByPosition(i, listView);
CheckBox cb = (CheckBox)view.findViewById(R.id.story_check_box);
if (isChecked) {
cb.setChecked(true);
}
else {
cb.setChecked(false);
}
}
}
});
I got getViewByPositionfrom here: Get ListView children that are not in view, and that almost works, but a few of the checkboxes don't get checked (and there is a pattern to it, but I can't seem to figure it out). It also seems a bit kludgier than I would think is necessary.
I want the checkboxes on the left, so I don't want to use checkedtextviews. Maybe I need to extend CursorAdapter and override getView?
Thanks in advance.
Maybe I'm not correctly understanding your question but what I understood was that you wanted to check and uncheck all the checkboxes thanks to one "Select All checkbox".
Then, what I would do is to put the state of the "select all checkbox" as a variable of the class (as a boolean) which is overwritten by your selectAll.setOnCheckedChangeListener and say to the adapter "Hey, my state changed!" every time the checkbox changed its state.
Something like this:
class Dummy{
boolean isAllSelected = false;
Checkbox selectAll = (find or create your CheckBox)
selectAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) isAllSelected = true;
else isAllSelected = false;
listView.getAdapter().notifyDataSetChanged();
}
}
And then, you just have to override the getView() of this adapter (like you suggested) adding a "if (isAllSlected)" condition.
To me, it sounds the easiest to do but it's maybe not that good to call the notifyDataSetChanged() method every time the user clicks on a checkbox (it's not that efficient for so minor changes). Anyway, hope it helps (the code I wrote is maybe not with the correct syntax: I wrote it directly on the website form)!
Below is what I wound up doing. In addition to taking care of the "select all/ unselect all" functionality, it handles checking/unchecking a checkbox when the text of a list item is selected/unselected, and vice versa. I was concerned about getView being called frequently, but setItemChecked causes getView to be called no matter what, so there's a limit to how much calls to getView can be avoided. As ataulm mentioned in a comment, maybe a composite view would a solution with less fuss.
In onCreateView:
selectAllCheckBox = (CheckBox) rootView.findViewById(R.id.select_all_check_box);
selectAllCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final ListView listView = getListView();
for(int i=0; i < getListAdapter().getCount(); i++){
listView.setItemChecked(i, isChecked);
}
}
});
I also created a custom SimpleCursorAdapter with the following code, which also uses a simple ViewHolder class. In getView I check which items in the list are selected and check the checkboxes corresponding to those items. There's also code that sets a list item as selected or not if its corresponding checkbox has been clicked (i.e., checked or unchecked).
class AvailableCursorAdapter extends SimpleCursorAdapter {
AvailableCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
ViewHolder holder = (ViewHolder)row.getTag();
if (holder == null) {
holder = new ViewHolder(row);
row.setTag(holder);
}
holder.storyCheckBox.setChecked(false);
holder.story.setTextColor(Color.LTGRAY);
long [] checkedIds = getListView().getCheckedItemIds();
if (checkedIds != null) {
for (int i = 0; i < checkedIds.length; i++) {
if (checkedIds[i] == getListAdapter().getItemId(position)) {
holder.storyCheckBox.setChecked(true);
holder.story.setTextColor(Color.WHITE);
break;
}
}
}
final boolean isChecked = holder.storyCheckBox.isChecked();
holder.storyCheckBox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
getListView().setItemChecked(position, !isChecked);
}
});
return(row);
}
}
.
class ViewHolder {
CheckBox storyCheckBox;
TextView story = null;
ViewHolder(final View row) {
storyCheckBox = (CheckBox) row.findViewById(R.id.story_check_box);
story = (TextView) row.findViewById(R.id.story);
}
}
Finally, the following code causes getView to be called when a single ListItem is clicked, so that its corresponding checkbox gets selected or unselected, as appropriate:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
ViewHolder holder = (ViewHolder) v.getTag();
holder.storyCheckBox.setChecked(false);
holder.story.setTextColor(Color.LTGRAY);
long [] checkedIds = l.getCheckedItemIds();
if (checkedIds != null) {
for (int i = 0; i < checkedIds.length; i++) {
if (checkedIds[i] == getListAdapter().getItemId(position)) {
holder.storyCheckBox.setChecked(true);
holder.story.setTextColor(Color.WHITE);
break;
}
}
}
}

Categories

Resources