Как переместить элемент в последнюю позицию, когда установлен флажок?(RecyclerView, ViewHolder) - PullRequest
0 голосов
/ 17 декабря 2018

enter image description here

Я пытаюсь создать RecyclerView, который содержит флажки (если что-то уже куплено).Я хочу переместить элемент в последнюю позицию проверенного изменения CheckBox и установить фон в зеленый цвет.Я попытался удалить элемент из ArrayList, а затем добавить его снова, но он работает только с именем строки, он не сохраняет состояние (состояние флажка или цвет).В других случаях выдается исключение: невозможно вызвать этот метод, пока RecyclerView вычисляет макет или прокрутку.Может кто-нибудь подскажет, что я делаю не так?

Прошу прощения за мой английский.

import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> 
{
private ArrayList<String> mDataset;
private ArrayList<FinalListItem> finalListItems;
public MyAdapter(ArrayList<String> mDataset) {
this.mDataset = mDataset;
[enter image description here][1]finalListItems = new ArrayList<>();
    for (String a : mDataset) {
        finalListItems.add(new FinalListItem(a, false));
    }
}
@Override
public long getItemId(int position) {
    return position;
}
@Override
public int getItemViewType(int position) {
    return position;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
    holder.final_list_TextView1.setText(finalListItems.get(position).getName());
    if(finalListItems.get(position).isChecked){
        holder.linearLayout.setBackgroundColor(Color.rgb(0, 225, 0));
    }
    else{
        holder.linearLayout.setBackgroundColor(Color.rgb(255, 255, 255));
    }
    holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            FinalListItem finalItem = new FinalListItem(finalListItems.get(position).getName(),true);
            if (isChecked) {
                holder.linearLayout.setBackgroundColor(Color.rgb(0, 225, 0));
                finalListItems.remove(finalListItems.get(position));
                finalListItems.add(finalItem);
                notifyDataSetChanged(); //weird behaviour of app
            } else {
                holder.linearLayout.setBackgroundColor(Color.rgb(255, 255, 255));
            }

        }
    });
}
@Override
public int getItemCount() {
    return finalListItems.size();
}

private class FinalListItem {
    private String name;
    private boolean isChecked;

    public FinalListItem(String name, boolean isChecked) {
        this.name = name;
        this.isChecked = isChecked;
    }

    public boolean isChecked() {
        return isChecked;
    }

    public void setChecked(boolean isChecked) {
        this.isChecked = isChecked;
    }

    public String getName() {
        return name;
    }
}

public class MyViewHolder extends RecyclerView.ViewHolder {
    final public TextView final_list_TextView1;
    final public CheckBox checkBox;
    final public LinearLayout linearLayout;

    public MyViewHolder(View view) {
        super(view);
        final_list_TextView1 = (TextView) view.findViewById(R.id.final_list_TextView1);
        checkBox = (CheckBox) view.findViewById(R.id.checkBox1);
        linearLayout = (LinearLayout) view.findViewById(R.id.linearLayout1);
    }
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.finallist_list_layout, parent, false);
    return new MyViewHolder(view);
}

}

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

@ 0X0nosugar ответ правильный :), я обнаружил, что мы также можем использовать

notifyItemRemoved(currentposition); //after removing an item
notifyItemInserted(currentposition); //after inserting an item

Это дает нам хорошо выглядящую плавную анимацию для нашего адаптера.

0 голосов
/ 17 декабря 2018

Главное, что вы должны изменить в своем коде, это то, что важно только изменить данные и затем позволить адаптеру отобразить список в соответствии с измененными данными.Это означает, что вы не должны менять, например, фон самостоятельно, но вы должны изменить список FinalListItem и уведомить адаптер.

@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
    holder.final_list_TextView1.setText(finalListItems.get(position).getName());

    // remove the Listener before setting the checked state programmatically
    // and set all the attributes (checked state and background color) here
    holder.checkBox.setOnCheckedChangeListener(null);
    if(finalListItems.get(position).isChecked){
        holder.linearLayout.setBackgroundColor(Color.rgb(0, 225, 0));
        holder.checkBox.setChecked(true);
    }
    else{
        holder.linearLayout.setBackgroundColor(Color.rgb(255, 255, 255));
        holder.checkBox.setChecked(false);
    }
    holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            // Lint warning : don't use "final int position"
            int currentPosition = holder.getAdapterPosition();
            if (isChecked) {
                FinalListItem finalItemBefore = finalListItems.get(currentPosition);
                FinalListItem finalItemAfter = new FinalListItem(finalItemBefore.getName(),true);
                finalListItems.remove(finalItemBefore);
                finalListItems.add(finalItemAfter);
                notifyDataSetChanged();
            } else {
                finalListItems.get(currentPosition).setChecked(false);
                // no need to update the whole list since only one item has changed
                notifyItemChanged(currentPosition);
            }
        }
    });
}

Обратите внимание, что не стоит возвращать позицию из getItemViewType().Делая это, вы сообщаете среде выполнения, что каждый View уникален, а переработка View s невозможна, что отрицательно скажется на производительности RecyclerView.

Способ реализации вашего списка, одинТип View достаточен, поэтому вам вообще не нужно переопределять метод, поскольку это реализация по умолчанию:

@Override
public int getItemViewType(int position) {
    return 0;
}
...