RecyclerView:如何添加OnClick()并保持onLongClick()工作?

时间:2017-12-13 00:13:57

标签: android checkbox android-recyclerview

我在onClickListener上为CheckBox设置RecyclerView,其中包含一个CardView列表。在ItemHolder扩展ViewHolder的{​​{1}}中设置了侦听器。初次点击CardView会检查CheckBox,并将CardView的背景颜色从默认的白色切换为红色。这工作正常。

我在OnClickListener本身也设置了CardViewOnClickListener已在onCreateViewHolder()中设置。点击CardView即可为CardView启动新的详情活动。这工作正常。

最后,我尝试在CardView上设置onLongClickListener。在{onCreateViewHolder()中设置了OnLongClickListener。 CardView上的longpress意味着将背景颜色切换为红色并启动AlertDialog,以便用户可以确认将从列表中删除CardView。这可以正常工作,但是当此代码添加到适配器时,CardView的CheckBox的OnClickListerner不再有效。就好像OnLongClickListner与CheckBox监听器冲突一样。注意我做"返回true"在itemHolder的onLongClick()代码中。我在这里缺少什么?

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>

5 个答案:

答案 0 :(得分:2)

  

为什么你没有使用 OnCheckedChangeListener 作为复选框?

CheckBox chkBox = ( CheckBox ) findViewById( R.id.checkbox );
chkBox.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
    {
        if ( isChecked )
        {
            // perform logic
        }

    }
});

答案 1 :(得分:0)

试试这个

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();
   }
}

答案 2 :(得分:0)

如果我正确理解了您的问题,请尝试使用此代码并告诉我它是否无法正常工作

适配器Java代码

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代码

<?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>

活动Java代码

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());
    }
}

只需使用此演示并相应地更改代码。

修改 这是使用的模型类。

 public class DemoData{
    public String item;
    public boolean checked;
    public DemoData(String item,boolean isChecked){
    this.item=item;
    this.checked=isChecked;
    }
    }

<强> | REY |

答案 3 :(得分:0)

看来你正试图在这里解决错误的问题。你应该不设置点击&amp;长期点击卡片视图上的听众本身。

  • 您可以在复选框
  • 上点击监听器或checkedChangeListener
  • 点击&amp;长按侦听器可以在 view_container
  • 的其余部分进行

如果您想选中/取消选中复选框,也可以点击view_container ,您可以在view_container onClick 听众。

修改: 我已经更新了你的布局文件,现在注意你在FrameLayout上作为RelativeLayout(view_container)&amp;的父级。复选框。

在RelativeLayout之后添加Checkbox时,它将在view_container之上显示。希望它对你有用。

现在您可以设置点击监听器,如上所述

更新了布局文件

<?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>

答案 4 :(得分:0)

你应该给你数据(mListItems)添加一个isChecked Fileds!你可以这样做

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;

}
});