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事件

android如何让checkbox实现互斥以及android验证端cession登录注意事项

Kendo Checkbox 检查事件

如何检测 DataGridView CheckBox 事件变化?