Reputation: 1649
I have an onClickListener
set on a CheckBox
for a RecyclerView
that holds a list of CardViews. The listener is set up in my ItemHolder
that extends ViewHolder
. An initial click on a CardView
checks the CheckBox
and toggles the CardView's background color from the default white color to red. This is working properly.
I also have an OnClickListener
set up on the CardView
itself. The OnClickListener
is set up in the onCreateViewHolder()
. A click on the CardView
launches a new Detail Activity for the CardView
. This is working properly.
Lastly, I tried to set up an onLongClickListener
on the CardView itself. The OnLongClickListener
is set up in the onCreateViewHolder(). A longpress on the CardView is meant to toggle the background color to red and launch an AlertDialog so the user can confirm that the CardView will be deleted from the list. This works properly but when this code is added to the Adapter then the OnClickListerner
for the CardView's CheckBox no longer works. It is as if the the OnLongClickListner
is in conflict with the CheckBox listener. Note I do "return true" in the itemHolder's onLongClick()
code. What am I missing here?
Adapter.java
public MyRecylerAdapter(Context context, ArrayList<ListItem> listItems, ArrayList<ListItem> selectedList) {
this.mContext = context;
this.mListItems = listItems;
this.selectedItemsList = selectedList;
}
private int selectedPos = -1;
...
private class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private CardView cardView;
private CheckBox chkSelected;
private ItemHolder(final View itemView) {
super(itemView);
cardView = (CardView) itemView.findViewById(R.id.singlecard_view1);
chkSelected = (CheckBox) itemView.findViewById(R.id.chkSelected);
chkSelected.setOnClickListener(this);
}
public void onClick(View v) {
int adapterPos = getAdapterPosition();
if (adapterPos == android.support.v7.widget.RecyclerView.NO_POSITION) return;
if (recyclerItemClickListener !=null) {
recyclerItemClickListener.onCheckBoxClick(v, adapterPos);
}
Integer iPos = adapterPos;
if (((CheckBox)v).isChecked()) {
checkedListItems.add(iPos);
}
else {
checkedListItems.remove(iPos);
}
}
void bind(int position) {
if (checkedListItems.contains(position)) {
chkSelected.setChecked(true);
}
else {
chkSelected.setChecked(false);
}
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent, false);
final ItemHolder itemHolder = new ItemHolder(view);
itemHolder.itemView.setOnClickListener(new View.OnClickListener() {
// Handles the row being clicked.
@Override
public void onClick(View view) {
ListItem adapterItem = MyRecylerAdapter.this.getItem(itemHolder.getAdapterPosition());
if (recyclerItemClickListener != null) {
recyclerItemClickListener.onItemClick(itemHolder.itemView, adapterItem);
}
}
});
itemHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
ListItem adapterItem2 = MyRecylerAdapter.this.getItem(itemHolder.getAdapterPosition());
if (recyclerItemClickListener != null) {
recyclerItemClickListener.onItemLongClick(itemHolder.itemView, adapterItem2);
}
int adapterPos2 = itemHolder.getAdapterPosition();
if (adapterPos2 != android.support.v7.widget.RecyclerView.NO_POSITION) {
int lastSelectedPosition = selectedPos;
selectedPos = adapterPos2;
notifyItemChanged(lastSelectedPosition);
notifyItemChanged(selectedPos);
}
return true;
}
});
return itemHolder;
}
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
final ListItem listItem = mListItems.get(position);
final ItemHolder itemHolder = (ItemHolder) holder;
itemHolder.bind(position);
if (checkedListItems.contains(position)) {
itemHolder.cardView.setActivated(true);
}
else {
itemHolder.cardView.setActivated(false);
}
// **The addition of the below code causes the "itemHolder.cardView.
// setActivated(true);" in onBindViewHolder method to no longer fire, as
// a click on the CheckBox no longer changes the CardView background
// color.**
if (itemHolder.getAdapterPosition() == selectedPos) {
itemHolder.cardView.setActivated(true);
} else {
itemHolder.cardView.setActivated(false);
}
list_contact_item.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/singlecard_view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/statelist_cardview_background" >
<CheckBox
android:id="@+id/chkSelected"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:gravity="center" />
<TextView
android:id="@+id/cardType1"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_toRightOf="@+id/chkSelected"
android:layout_toEndOf="@+id/chkSelected"
android:layout_alignParentTop="true"
android:paddingStart="3dp"
android:paddingLeft="3dp"
android:paddingEnd="6dp"
android:paddingRight="6dp"
android:layout_marginTop="4dp"
android:gravity="center"
android:textColor="#ffffff"
android:textStyle="bold|italic"
style="@style/Base.TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/cardBlankText1"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/cardType1"
android:layout_toEndOf="@+id/cardType1"
android:layout_toLeftOf="@+id/cardBlankTextNumstotal"
android:layout_toStartOf="@+id/cardBlankTextNumstotal"
android:layout_marginTop="4dp"
android:gravity="center_vertical|end"
android:text="#"
android:textColor="@color/colorFlLabelFinal"
android:textStyle="bold"
android:maxLines="1"
style="@style/Base.TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/cardBlankTextNumstotal"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:gravity="center"
android:text="actual card #"
android:layout_marginTop="4dp"
android:layout_marginRight="4dp"
android:layout_marginEnd="4dp"
android:freezesText="true"
android:textColor="@android:color/black"
android:maxLines="1"
style="@style/Base.TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/cardBlankText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/chkSelected"
android:layout_marginTop="4dp"
android:layout_marginLeft="6dp"
android:layout_marginStart="6dp"
android:text="todo"
android:textColor="@android:color/black"
android:textStyle="bold"
android:background="@drawable/todo_underline"
android:maxLines="1"
style="@style/Base.TextAppearance.AppCompat.Headline" />
...
</RelativeLayout>
</android.support.v7.widget.CardView>
statelist_cardview_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true"
android:drawable="@color/item_selected" />
<item android:state_activated="false"
android:drawable="@color/list_contact_item_default" />
</selector>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="list_contact_item_default">#FFFFFF</color>
<color name="item_selected">#FF0000</color>
</resources>
Upvotes: 7
Views: 3963
Reputation: 6697
It seems you are trying to solve the wrong problem here. You should not set click & long click listeners on card view itself.
Here if you want to check/uncheck the checkbox also on click of view_container, you can easily do it in view_container's onClick listener.
Edit: I have updated your layout file, notice now you have on FrameLayout as parent of RelativeLayout(view_container) & Checkbox.
As Checkbox is added after RelativeLayout it will be visible on top of view_container. Hope it will work for you.
Now you can set click listeners as I explained above.
Updated layout file
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/singlecard_view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/view_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/statelist_cardview_background" >
<TextView
android:id="@+id/cardType1"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginLeft="30dp"
android:layout_marginStart="30dp"
android:layout_alignParentTop="true"
android:paddingStart="3dp"
android:paddingLeft="3dp"
android:paddingEnd="6dp"
android:paddingRight="6dp"
android:layout_marginTop="4dp"
android:gravity="center"
android:textColor="#ffffff"
android:textStyle="bold|italic"
style="@style/Base.TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/cardBlankText1"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/cardType1"
android:layout_toEndOf="@+id/cardType1"
android:layout_toLeftOf="@+id/cardBlankTextNumstotal"
android:layout_toStartOf="@+id/cardBlankTextNumstotal"
android:layout_marginTop="4dp"
android:gravity="center_vertical|end"
android:text="#"
android:textColor="@color/colorFlLabelFinal"
android:textStyle="bold"
android:maxLines="1"
style="@style/Base.TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/cardBlankTextNumstotal"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:gravity="center"
android:text="actual card #"
android:layout_marginTop="4dp"
android:layout_marginRight="4dp"
android:layout_marginEnd="4dp"
android:freezesText="true"
android:textColor="@android:color/black"
android:maxLines="1"
style="@style/Base.TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/cardBlankText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="34dp"
android:layout_marginLeft="6dp"
android:layout_marginStart="6dp"
android:text="todo"
android:textColor="@android:color/black"
android:textStyle="bold"
android:background="@drawable/todo_underline"
android:maxLines="1"
style="@style/Base.TextAppearance.AppCompat.Headline" />
...
</RelativeLayout>
<CheckBox
android:id="@+id/chkSelected"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:gravity="center" />
</FrameLayout>
</android.support.v7.widget.CardView>
Upvotes: 0
Reputation: 311
you should give you data(mListItems) add a isChecked Fileds!and you can do this
holder.checkebox.setchecked(false);
if(mListItems.get(position).ischekced){
holder.checkebox.setchecked(true);
}
holder.checkebox..setOnCheckedChangeListener(new OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
mListItems.get(position).isChecked=isChecked;
}
});
Upvotes: 0
Reputation: 687
How come you are not using OnCheckedChangeListener for checkbox?
CheckBox chkBox = ( CheckBox ) findViewById( R.id.checkbox );
chkBox.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if ( isChecked )
{
// perform logic
}
}
});
Upvotes: 2
Reputation: 1915
If I understood your question correctly Please try this code and let me know if it doesn't work
Adapter Java Code
public class Adapter extends RecyclerView.Adapter<Adapter.ItemHolder> {
private ArrayList<DemoData> mDemoData;
public Adapter() {
mDemoData = new ArrayList<>();
for (int i = 0; i <= 100; i++) {
mDemoData.add(new DemoData("Item " + i, false));
}
}
@Override
public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ItemHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.recyler_card, parent, false));
}
@Override
public void onBindViewHolder(ItemHolder holder, int position) {
//Check if the item is check and toggle the checkbox
if (mDemoData.get(position).checked) {
holder.mCheckBox.setChecked(true);
} else {
holder.mCheckBox.setChecked(false);
}
//Set text to the textview
holder.mTextView.setText(mDemoData.get(position).item);
}
@Override
public int getItemCount() {
return mDemoData.size();
}
public class ItemHolder extends RecyclerView.ViewHolder {
private TextView mTextView;
private CheckBox mCheckBox;
public ItemHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.textView);
mCheckBox = (CheckBox) itemView.findViewById(R.id.checkbox);
//set OnClickListener
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mCheckBox.getContext(), "Clicked", Toast.LENGTH_SHORT).show();
}
});
//set OnLongClickListener
itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
//if handled return true if not return false;
Toast.makeText(mCheckBox.getContext(), "Long Clicked", Toast.LENGTH_SHORT).show();
return false;
}
});
mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mDemoData.get(getAdapterPosition()).checked = isChecked;
}
});
}
}
}
ItemView XML Code
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="75dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="75dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.CardView>
Activity Java Code
public class RecyclerDemoActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_demo);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
mRecyclerView.setAdapter(new Adapter());
}
}
Just use this demo and change your code accordingly.
Edit: This is the model class which is used.
public class DemoData{
public String item;
public boolean checked;
public DemoData(String item,boolean isChecked){
this.item=item;
this.checked=isChecked;
}
}
|REY|
Upvotes: 0
Reputation: 5043
try this
public class MyRecylerAdapter extends RecyclerView.Adapter<MyRecylerAdapter.ItemHolder> {
...
public MyRecylerAdapter(Context context, ArrayList<ListItem> listItems,
ArrayList<ListItem> selectedList) {
this.mContext = context;
this.mListItems = listItems;
this.selectedItemsList = selectedList;
}
private int selectedPos = -1;
public class ItemHolder extends RecyclerView.ViewHolder {
private CardView cardView;
private CheckBox chkSelected;
private ItemHolder(final View itemView) {
super(itemView);
cardView = (CardView) itemView.findViewById(R.id.singlecard_view1);
chkSelected = (CheckBox) itemView.findViewById(R.id.chkSelected);
}
void bind(int position) {
if (checkedListItems.contains(position)) {
chkSelected.setChecked(true);
} else {
chkSelected.setChecked(false);
}
}
}
@Override
public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent, false);
final ItemHolder itemHolder = new ItemHolder(view);
return itemHolder;
}
public void onBindViewHolder(final ItemHolder itemHolder, final int position) {
final ListItem listItem = mListItems.get(position);
itemHolder.bind(position);
if (checkedListItems.contains(position)) {
itemHolder.cardView.setActivated(true);
} else {
itemHolder.cardView.setActivated(false);
}
if (itemHolder.getAdapterPosition() == selectedPos) {
itemHolder.cardView.setActivated(true);
} else {
itemHolder.cardView.setActivated(false);
}
itemHolder.itemView.setOnClickListener(new View.OnClickListener() {
// Handles the row being clicked.
@Override
public void onClick(View view) {
if (recyclerItemClickListener != null) {
recyclerItemClickListener.onItemClick(itemHolder.itemView, listItem);
}
}
});
itemHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if (recyclerItemClickListener != null) {
recyclerItemClickListener.onItemLongClick(itemHolder.itemView, listItem);
}
int adapterPos2 = itemHolder.getAdapterPosition();
if (adapterPos2 != android.support.v7.widget.RecyclerView.NO_POSITION) {
int lastSelectedPosition = selectedPos;
selectedPos = adapterPos2;
notifyItemChanged(lastSelectedPosition);
notifyItemChanged(selectedPos);
}
return true;
}
});
itemHolder.chkSelected.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (position == android.support.v7.widget.RecyclerView.NO_POSITION) return;
if (recyclerItemClickListener != null) {
recyclerItemClickListener.onCheckBoxClick(v, position);
}
Integer iPos = position;
if (((CheckBox) v).isChecked()) {
checkedListItems.add(iPos);
} else {
checkedListItems.remove(iPos);
}
}
});
}
@Override
public int getItemCount() {
return mListItems.size();
}
}
Upvotes: 0