Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView: how to add OnClick() and keep onLongClick() working?

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>
like image 982
AJW Avatar asked Dec 13 '17 00:12

AJW


1 Answers

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
        }

    }
});
like image 143
AppHero2 Avatar answered Oct 06 '22 00:10

AppHero2