Я пытаюсь создать приложение типа простого списка покупок, в котором каждый элемент отображается в RecyclerView с CheckBox и двумя кнопками ImageButton. Когда флажок установлен, я хочу отобразить тексты элементов как зачеркнутые.
Вот мой файл макета адаптера 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, который устанавливает checkBox с параметром isChecked после notifyItemChanged (position), но, похоже, работает неправильно. Что я делаю не так?
Обновлен код для класса адаптера:
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, изображающий работу view
Надеюсь, вы увидите, как checkBox продолжает сбрасывать себя.
Спасибо, и наилучшими пожеланиями.