Android如何在CheckBox检查事件后更新RecyclerView内TextView的文本样式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android如何在CheckBox检查事件后更新RecyclerView内TextView的文本样式相关的知识,希望对你有一定的参考价值。
我正在尝试制作一种简单的购物清单应用程序,其中每个项目都在带有一个CheckBox和两个ImageButton的RecyclerView中显示。选中复选框后,我想将项目文本显示为删除线。
这是我的RecyclerView适配器布局文件:
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/adapterCardItemDisplay"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/adapterTvItemName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/adapterTvItemNameBeg"
android:textSize="18sp"
android:layout_margin="1dp"
/>
<TextView
android:id="@+id/adapterTvItemQuantity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/adapterTvItemQuantityBeg"
android:textSize="18sp"
android:layout_margin="1dp"
/>
<TextView
android:id="@+id/adapterTvItemColor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/adapterTvItemColorBeg"
android:textSize="18sp"
android:layout_margin="1dp"
/>
<TextView
android:id="@+id/adapterTvItemSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/adapterTvItemSizeBeg"
android:textSize="18sp"
android:layout_margin="1dp"
/>
<TextView
android:id="@+id/adapterTvItemRemarks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/adapterTvItemRemarksBeg"
android:textSize="18sp"
android:layout_margin="1dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="15dp"
>
<CheckBox
android:id="@+id/adapterChkItemChecked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="start"
>
<ImageButton
android:id="@+id/adapterImgBtnEdit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFFCFC"
android:src="@android:drawable/ic_menu_edit"
android:layout_marginEnd="10dp"/>
<ImageButton
android:id="@+id/adapterImgBtnDelete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#F8F4F4"
android:src="@android:drawable/ic_delete" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
这是我的适配器Java文件:
public class ItemDisplayAdapter extends RecyclerView.Adapter <ItemDisplayAdapter.ViewHolder>
private static final String TAG = "ItemDisplayAdapter";
private CardView adapterCardItemDisplay;
private TextView adapterTvItemName;
private TextView adapterTvItemQuantity;
private TextView adapterTvItemColor;
private TextView adapterTvItemSize;
private TextView adapterTvItemRemarks;
private CheckBox adapterChkItemChecked;
private ImageButton adapterImgBtnEdit;
private ImageButton adapterImgBtnDelete;
private Context context;
private ArrayList<Item> adapterItemArrayList;
public ItemDisplayAdapter(Context context, ArrayList<Item> adapterItemArrayList)
this.context = context;
this.adapterItemArrayList = adapterItemArrayList;
private void checkAnItem (boolean isChecked,int position)
if (isChecked)
Log.d(TAG, "checkAnItem: here");
adapterTvItemName.setPaintFlags(adapterTvItemName.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
adapterTvItemQuantity.setPaintFlags(adapterTvItemQuantity.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
adapterTvItemColor.setPaintFlags(adapterTvItemColor.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
adapterTvItemSize.setPaintFlags(adapterTvItemSize.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
adapterTvItemRemarks.setPaintFlags(adapterTvItemRemarks.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
else
adapterTvItemName.setPaintFlags(adapterTvItemName.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
adapterTvItemQuantity.setPaintFlags(adapterTvItemQuantity.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
adapterTvItemColor.setPaintFlags(adapterTvItemColor.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
adapterTvItemSize.setPaintFlags(adapterTvItemSize.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
adapterTvItemRemarks.setPaintFlags(adapterTvItemRemarks.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
//invalidateViews();
private void invalidateViews ()
adapterTvItemName.invalidate();
adapterTvItemQuantity.invalidate();
adapterTvItemColor.invalidate();
adapterTvItemSize.invalidate();
adapterTvItemRemarks.invalidate();
private void editAnItem ()
private void deleteAnItem ()
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_item_list_view,parent,false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position)
//Log.d(TAG, "onBindViewHolder: "+position);
Item item = adapterItemArrayList.get(position);
adapterCardItemDisplay.setTag(item.getId());
String nameString = context.getResources().getString(R.string.adapterTvItemNameBeg)+
" "+item.getName();
adapterTvItemName.setText(nameString);
String quantityString = context.getResources().getString(R.string.adapterTvItemQuantityBeg)+
" "+item.getQuantity();
adapterTvItemQuantity.setText(quantityString);
if (item.getColor().isEmpty())
adapterTvItemColor.setVisibility(View.GONE);
else
adapterTvItemColor.setVisibility(View.VISIBLE);
String colorString = context.getResources().getString(R.string.adapterTvItemColorBeg) +
" " + item.getColor();
adapterTvItemColor.setText(colorString);
if (item.getSize() == 0)
adapterTvItemSize.setVisibility(View.GONE);
else
adapterTvItemSize.setVisibility(View.VISIBLE);
String sizeString = context.getResources().getString(R.string.adapterTvItemSizeBeg)+
" "+item.getSize();
adapterTvItemSize.setText(sizeString);
if (item.getRemarks().isEmpty())
adapterTvItemRemarks.setVisibility(View.GONE);
else
adapterTvItemRemarks.setVisibility(View.VISIBLE);
String remarksString = context.getResources().getString(R.string.adapterTvItemRemarksBeg)+
" "+item.getRemarks();
adapterTvItemRemarks.setText(remarksString);
adapterChkItemChecked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
Log.d(TAG, "onCheckedChanged: here");
checkAnItem(isChecked,position);
notifyItemChanged(position);
adapterChkItemChecked.setChecked(isChecked);
);
adapterImgBtnEdit.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
editAnItem();
);
adapterImgBtnDelete.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
deleteAnItem();
);
@Override
public int getItemCount()
return adapterItemArrayList.size();
public class ViewHolder extends RecyclerView.ViewHolder
public ViewHolder(@NonNull View itemView)
super(itemView);
adapterCardItemDisplay = itemView.findViewById(R.id.adapterCardItemDisplay);
adapterTvItemName = itemView.findViewById(R.id.adapterTvItemName);
adapterTvItemQuantity = itemView.findViewById(R.id.adapterTvItemQuantity);
adapterTvItemColor = itemView.findViewById(R.id.adapterTvItemColor);
adapterTvItemSize = itemView.findViewById(R.id.adapterTvItemSize);
adapterTvItemRemarks = itemView.findViewById(R.id.adapterTvItemRemarks);
adapterChkItemChecked = itemView.findViewById(R.id.adapterChkItemChecked);
adapterImgBtnEdit = itemView.findViewById(R.id.adapterImgBtnEdit);
adapterImgBtnDelete = itemView.findViewById(R.id.adapterImgBtnDelete);
我无法获得预期的行为。单击一个CheckBox,不会对该项目产生删除线效果,也许再次单击会更改另一个项目(例如,单击项目0的复选框实际上会对项目4的删除线进行更改),有时我在重复点击时获得删除线效果,但那时该复选框并未处于选中状态。所以我无所适从。
使视图无效,notifyItemChanged(position)方法也无效。
有任何建议吗?
更新:因此我遵循了丹尼尔的建议,它摆脱了问题的50%,但是在视图更新后,该复选框一直处于未选中状态,我认为这是自期望的行为,因为视图正在更新,这就是为什么我拥有“ checkedChangeListener”中的代码,在“ notifyItemChanged(position)”之后设置带有“ isChecked”参数的复选框,但它似乎无法正常工作。我在做什么错?
适配器类的更新代码:
public class ItemDisplayAdapter extends RecyclerView.Adapter <ItemDisplayAdapter.ViewHolder>
private static final String TAG = "ItemDisplayAdapter";
private Context context;
private ArrayList<Item> adapterItemArrayList;
public ItemDisplayAdapter(Context context, ArrayList<Item> adapterItemArrayList)
this.context = context;
this.adapterItemArrayList = adapterItemArrayList;
private void checkAnItem (ViewHolder holder,boolean isChecked,int position)
if (isChecked)
Log.d(TAG, "checkAnItem: here");
holder.adapterTvItemName.setPaintFlags(holder.adapterTvItemName.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.adapterTvItemQuantity.setPaintFlags(holder.adapterTvItemQuantity.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.adapterTvItemColor.setPaintFlags(holder.adapterTvItemColor.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.adapterTvItemSize.setPaintFlags(holder.adapterTvItemSize.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.adapterTvItemRemarks.setPaintFlags(holder.adapterTvItemRemarks.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
else
holder.adapterTvItemName.setPaintFlags(holder.adapterTvItemName.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
holder.adapterTvItemQuantity.setPaintFlags(holder.adapterTvItemQuantity.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
holder.adapterTvItemColor.setPaintFlags(holder.adapterTvItemColor.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
holder.adapterTvItemSize.setPaintFlags(holder.adapterTvItemSize.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
holder.adapterTvItemRemarks.setPaintFlags(holder.adapterTvItemRemarks.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
//invalidateViews();
private void invalidateViews (ViewHolder holder)
holder.adapterTvItemName.invalidate();
holder.adapterTvItemQuantity.invalidate();
holder.adapterTvItemColor.invalidate();
holder.adapterTvItemSize.invalidate();
holder.adapterTvItemRemarks.invalidate();
private void editAnItem ()
private void deleteAnItem ()
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_item_list_view,parent,false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position)
//Log.d(TAG, "onBindViewHolder: "+position);
Item item = adapterItemArrayList.get(position);
holder.adapterCardItemDisplay.setTag(item.getId());
String nameString = context.getResources().getString(R.string.adapterTvItemNameBeg)+
" "+item.getName();
holder.adapterTvItemName.setText(nameString);
String quantityString = context.getResources().getString(R.string.adapterTvItemQuantityBeg)+
" "+item.getQuantity();
holder.adapterTvItemQuantity.setText(quantityString);
if (item.getColor().isEmpty())
holder.adapterTvItemColor.setVisibility(View.GONE);
else
holder.adapterTvItemColor.setVisibility(View.VISIBLE);
String colorString = context.getResources().getString(R.string.adapterTvItemColorBeg) +
" " + item.getColor();
holder.adapterTvItemColor.setText(colorString);
if (item.getSize() == 0)
holder.adapterTvItemSize.setVisibility(View.GONE);
else
holder.adapterTvItemSize.setVisibility(View.VISIBLE);
String sizeString = context.getResources().getString(R.string.adapterTvItemSizeBeg)+
" "+item.getSize();
holder.adapterTvItemSize.setText(sizeString);
if (item.getRemarks().isEmpty())
holder.adapterTvItemRemarks.setVisibility(View.GONE);
else
holder.adapterTvItemRemarks.setVisibility(View.VISIBLE);
String remarksString = context.getResources().getString(R.string.adapterTvItemRemarksBeg)+
" "+item.getRemarks();
holder.adapterTvItemRemarks.setText(remarksString);
holder.adapterChkItemChecked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
Log.d(TAG, "onCheckedChanged: here");
checkAnItem(holder,isChecked,position);
notifyItemChanged(position);
holder.adapterChkItemChecked.setChecked(isChecked);
);
holder.adapterImgBtnEdit.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
editAnItem();
);
holder.adapterImgBtnDelete.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
deleteAnItem();
);
@Override
public int getItemCount()
return adapterItemArrayList.size();
public static class ViewHolder extends RecyclerView.ViewHolder
private CardView adapterCardItemDisplay;
private TextView adapterTvItemName;
private TextView adapterTvItemQuantity;
private TextView adapterTvItemColor;
private TextView adapterTvItemSize;
private TextView adapterTvItemRemarks;
private CheckBox adapterChkItemChecked;
private ImageButton adapterImgBtnEdit;
private ImageButton adapterImgBtnDelete;
public ViewHolder(@NonNull View itemView)
super(itemView);
adapterCardItemDisplay = itemView.findViewById(R.id.adapterCardItemDisplay);
adapterTvItemName = itemView.findViewById(R.id.adapterTvItemName);
adapterTvItemQuantity = itemView.findViewById(R.id.adapterTvItemQuantity);
adapterTvItemColor = itemView.findViewById(R.id.adapterTvItemColor);
adapterTvItemSize = itemView.findViewById(R.id.adapterTvItemSize);
adapterTvItemRemarks = itemView.findViewById(R.id.adapterTvItemRemarks);
adapterChkItemChecked = itemView.findViewById(R.id.adapterChkItemChecked);
adapterImgBtnEdit = itemView.findViewById(R.id.adapterImgBtnEdit);
adapterImgBtnDelete = itemView.findViewById(R.id.adapterImgBtnDelete);
这里是描述问题的GIF:
GIF depicting the workings of the view
我希望您能看到复选框如何保持自身重置。
谢谢,最好的问候。
这里可能有多个问题,但让我们从一个问题开始。
您的视图引用在适配器类中。
private CardView adapterCardItemDisplay;
private TextView adapterTvItemName;
private TextView adapterTvItemQuantity;
private TextView adapterTvItemColor;
private TextView adapterTvItemSize;
private TextView adapterTvItemRemarks;
private CheckBox adapterChkItemChecked;
private ImageButton adapterImgBtnEdit;
private ImageButton adapterImgBtnDelete;
它应该在视图持有者类中。
理由是每个视图都有其自己的视图引用集。
现在要更正此问题,使内部类为static
,并将以上引用移至视图持有者类内部。
static class ViewHolder extends RecyclerView.ViewHolder
private CardView adapterCardItemDisplay;
private TextView adapterTvItemName;
private TextView adapterTvItemQuantity;
private TextView adapterTvItemColor;
private TextView adapterTvItemSize;
private TextView adapterTvItemRemarks;
private CheckBox adapterChkItemChecked;
private ImageButton adapterImgBtnEdit;
private ImageButton adapterImgBtnDelete;
ViewHolder(@NonNull View itemView)
...
通过在前面附加onBindViewHolder
来调整holder.
中的用法。
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position)
...
holder.adapterTvItemName.setText(nameString);
holder.adapterTvItemQuantity.setText(quantityString);
holder.adapterChkItemChecked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
Log.d(TAG, "onCheckedChanged: here");
checkAnItem(holder, isChecked,position);
notifyItemChanged(position);
holder.adapterChkItemChecked.setChecked(isChecked);
);
holder.adapterImgBtnEdit.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
editAnItem();
);
... etc...
将视图持有者作为新参数添加到checkAnItem
,并使用视图持有者访问随附的视图引用。与onBindViewHolder
中的想法相同。
private void checkAnItem (ViewHolder holder, boolean isChecked,int position)
...
holder.adapterTvItemSize.setPaintFlags(holder.adapterTvItemSize.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
...
仅此而已。让我知道进度。
编辑:
复选框随机取消选中的问题是众所周知的。参见this answer。基本上,当选中它时,您需要在适配器中切换一个布尔值,以跟踪选中了哪个项目。
以上是关于Android如何在CheckBox检查事件后更新RecyclerView内TextView的文本样式的主要内容,如果未能解决你的问题,请参考以下文章
android中如何获得listview中的checkbox的值?
如何在不引发事件的情况下设置 checkbox.isChecked
为啥android的checkbox的setChecked方法不触发onCheckedChanged事件