Фильтруемый recyclerview с флажками

Цель: отслеживать выбранные элементы в recyclerview, используя изменяющийся Imageview для каждой строки. Практически я устанавливаю своего рода флажок.

Проверка работает нормально:

Фильтруемый recyclerview с флажками

но когда я пытаюсь найти некоторые элементы, отмеченные элементы меняются: проверяется только первый элемент моего списка:

Фильтруемый recyclerview с флажками

Я отправлю свой код ниже:

Выбранный интерфейс магазина

public interface NearestShopActivityAdapterListener {
    void onShopSelected(FShop shop, View view);
}

Держатель My View

public class MyHolder extends RecyclerView.ViewHolder{
    public TextView name, address;
    public ImageView logo;

    public MyHolder(View itemView) {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.activityNearestShopListItemUhop);
        address = (TextView) itemView.findViewById(R.id.activityNearestShopListItemAddress);
        logo = (ImageView) itemView.findViewById(R.id.activityNearestShopListItemImage);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onShopSelected(filteredShopList.get(getAdapterPosition()),view);
            }
        });
    }

onShopSelected функция

 @Override
public void onShopSelected(FShop shop, View view) {
    if (checkList.contains(shop.getShopId())){
        mImgViewCheckBox = (ImageView) view.findViewById(R.id.checkBoxNearestShop);
        mImgViewCheckBox.setImageResource(R.drawable.checkbox_selector_not_checked);
        checkList.remove(shop.getShopId());
    }else {
        mImgViewCheckBox = (ImageView) view.findViewById(R.id.checkBoxNearestShop);
        mImgViewCheckBox.setImageResource(R.drawable.ic_checked);
        checkList.add(shop.getShopId());
    }
}

Где я не прав? Я бы попытался связать ImageView mImgViewCheckBox с идентификатором магазина, а не с его позицией в recyclerview, но я понятия не имею, как это сделать. Спасибо заранее.

Я не уверен, что полностью следую первым двум абзацам. Возможно, вы сможете обновить его немного подробнее.

Jay Snayder 16.04.2018 13:30

Я попытался лучше объяснить свою проблему. Благодарю за ответ.

Vincenzo Laudato 16.04.2018 13:36

Попробуйте вызвать notifyDataSetChanged (); в onShopSelected () после внесения изменений в контрольный список

Shubham Srivastava 16.04.2018 13:41

Всякий раз, когда вы проверяете свой флажок .. обновите в своей модели, а затем примените notifydatasetChanged.

AbhayBohra 16.04.2018 13:41

вы должны сохранить флажок в массиве или хеш-карте.

Praveen Rawat 16.04.2018 13:43
0
5
3 213
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

я сделал это в контактных данных. Я предоставляю свой адаптер и метод, в котором вы можете изменить код в соответствии с вашими потребностями.

InviteContactAdapter.java

public class InviteContactAdapter extends RecyclerView.Adapter<InviteContactAdapter.ItemViewHolder> implements Filterable {
private List<UserContact> mContactList = new ArrayList<>();
private List<UserContact> mContectFilter = new ArrayList<>();
private Context mContext;
private CustomFilter mFilter;
public List<String> mEmailList = new ArrayList<>();

public InviteContactAdapter(Context context, List<UserContact> mContactList) {
    mContext = context;
    this.mContactList = mContactList;
    this.mContectFilter = mContactList;
    mFilter = new CustomFilter();
}

public onItemClickListener onItemClickListener;

public void setOnItemClickListener(InviteContactAdapter.onItemClickListener onItemClickListener) {
    this.onItemClickListener = onItemClickListener;
}

@Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.invite_contact_row_layout, viewGroup, false);
    return new ItemViewHolder(view);
}

public interface onItemClickListener {
    void onClick(UserContact contact);
}

@Override
public Filter getFilter() {
    return mFilter;
}

@Override
public void onBindViewHolder(final ItemViewHolder itemViewHolder, int i) {
    final UserContact contact = mContectFilter.get(i);
    itemViewHolder.mTvUserNane.setText(contact.getUserName().trim());
    itemViewHolder.mTvUserEmail.setText(contact.getUserEmail().trim());
    if (contact.isSelect())
        itemViewHolder.mIvSelect.setImageResource(R.drawable.check_contect);
    else
        itemViewHolder.mIvSelect.setImageResource(R.drawable.un_check_contact);


    itemViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            if (contact.isSelect()) {
                contact.setSelect(false);
                itemViewHolder.mIvSelect.setImageResource(R.drawable.un_check_contact);
            } else {
                contact.setSelect(true);
                itemViewHolder.mIvSelect.setImageResource(R.drawable.check_contect);
            }
        }
    });

}

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

public class ItemViewHolder extends RecyclerView.ViewHolder {
    private TextView mTvUserNane, mTvUserEmail;
    private ImageView mIvSelect;

    public ItemViewHolder(View itemView) {
        super(itemView);
        mTvUserEmail = itemView.findViewById(R.id.icrlTvUserEmail);
        mTvUserNane = itemView.findViewById(R.id.icrlTvUserName);
        mIvSelect = itemView.findViewById(R.id.icrlIvSelect);
    }
}

public List<String> getEmail() {
    mEmailList.clear();
    for (UserContact contact : mContectFilter) {
        if (contact.isSelect()) {
            mEmailList.add(contact.getUserEmail());
        }
    }
    return mEmailList;
}

/**
 * this class for filter data.
 */
class CustomFilter extends Filter {

    @Override
    protected FilterResults performFiltering(CharSequence charSequence) {
        FilterResults results = new FilterResults();
        if (charSequence != null && charSequence.length() > 0) {
            ArrayList<UserContact> filters = new ArrayList<>();
            charSequence = charSequence.toString().toUpperCase();
            for (int i = 0; i < mContactList.size(); i++) {
                if (mContactList.get(i).getUserName().toUpperCase().contains(charSequence) || mContactList.get(i).getUserEmail().toUpperCase().contains(charSequence)) {
                    UserContact contact = new UserContact();
                    contact.setUserName(mContactList.get(i).getUserName());
                    contact.setUserEmail(mContactList.get(i).getUserEmail());
                    filters.add(contact);

                }
            }
            results.count = filters.size();
            results.values = filters;

        } else {
            results.count = mContactList.size();
            results.values = mContactList;
        }
        return results;
    }

    @Override
    protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
        mContectFilter = (ArrayList<UserContact>) filterResults.values;
        notifyDataSetChanged();
    }
}

}

затем после привязки контактных данных к просмотру ресайклера и поиску данных на основе имени и адреса электронной почты .. сделать набор адаптеров метод ..

  private void setAdapter(){
    if (!mContactList.isEmpty()) {
        inviteContactAdapter = new InviteContactAdapter(getActivity(), mContactList);
        mRvData.setAdapter(inviteContactAdapter);
        inviteContactAdapter.setOnItemClickListener(new InviteContactAdapter.onItemClickListener() {
            @Override
            public void onClick(UserContact contact) {
                mEmailList.add(contact.getUserEmail());
            }
        });
    } else {
        mTvEmpty.setVisibility(View.VISIBLE);
    }
}

затем после создания метода данных поиска ...

   /**
 * this method sort data.
 */
private void sortData(View root) {
    mEtSearchData = (EditText) root.findViewById(R.id.icffEtSearch);
    mEtSearchData.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (inviteContactAdapter != null) {
                inviteContactAdapter.getFilter().filter(s);
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    });

}

после получения контактных данных будет работать. и вы можете изменить свой код в соответствии с.

Я изменил свой код на основе вашего, и он отлично работал! Спасибо, мужик!

Vincenzo Laudato 16.04.2018 14:43

У меня также есть несколько шаблонов, которые я использую каждый раз, когда мне нужен режим ресайклера.

Разница в том, что я использую еще одно дополнительное свойство в каждом элементе списка, поэтому в основном вы не зависите от фильтрации, сортировки или чего-то еще.

Это XML для активности:

<?xml version = "1.0" encoding = "utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:app = "http://schemas.android.com/apk/res-auto"
    xmlns:tools = "http://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    tools:context = "com.arnela.nihad.expresssaladbar.RecyclerViewExample.RecyclerViewActivity">

    <SearchView
        android:id = "@+id/searchViewBox"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:layout_marginEnd = "8dp"
        android:layout_marginStart = "8dp"
        android:layout_marginTop = "8dp"
        android:layout_marginBottom = "8dp"
        android:layout_weight = "1"
        android:iconifiedByDefault = "false"
        android:queryHint = "HINT"
        app:layout_constraintEnd_toEndOf = "parent"
        app:layout_constraintStart_toStartOf = "parent"
        app:layout_constraintTop_toTopOf = "parent" />

    <android.support.v7.widget.RecyclerView
        android:id = "@+id/recycler_view"
        android:layout_width = "0dp"
        android:layout_height = "0dp"
        android:layout_marginTop = "8dp"
        android:clipToPadding = "false"
        app:layout_constraintBottom_toBottomOf = "parent"
        app:layout_constraintEnd_toEndOf = "parent"
        app:layout_constraintStart_toStartOf = "parent"
        app:layout_constraintTop_toBottomOf = "@+id/searchViewBox" />

</android.support.constraint.ConstraintLayout>

Следующий Java-класс RecyclerViewActivity:

public class RecyclerViewActivity extends AppCompatActivity {

    private RecyclerView mRecyclerList;
    private RecyclerViewAdapter mRecyclerAdapter;
    private List<DataVm> mSourceList = new ArrayList<>();
    private SearchView txtSearchBox;
    private Data data;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recyler_view);


        data = new Data();
        mSourceList.addAll(data.getSourceList(""));

        // this is recycler view from xml
        mRecyclerList = findViewById(R.id.recycler_view);
        InitRecyclerView();

        txtSearchBox = findViewById(R.id.searchViewBox);

        txtSearchBox.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {

                mSourceList.clear();

                mSourceList.addAll(data.getSourceList(s));

                mRecyclerAdapter.notifyDataSetChanged();

                return false;
            }

            @Override
            public boolean onQueryTextChange(String s) {
                mSourceList.clear();

                mSourceList.addAll(data.getSourceList(s));

                mRecyclerAdapter.notifyDataSetChanged();

                return false;
            }
        });

    }

    public void InitRecyclerView() {

        mRecyclerList.setLayoutManager(new LinearLayoutManager(RecyclerViewActivity.this));
        mRecyclerAdapter = new RecyclerViewAdapter(mSourceList, new IClickListenerAddRemove() {

            @Override
            public void onPositionClicked(int position, boolean isPicked) {

                mSourceList.get(position).setPicked(isPicked);
            }

        });

        mRecyclerList.setAdapter(mRecyclerAdapter);
    }
}

Затем у меня есть два вспомогательных класса, один для создания данных макета с методом поиска:

public class Data {

    private List<DataVm> sourceList = null;

    public Data() {

        this.sourceList = new ArrayList<>();

        // Items of the list and set all items to isPicked to false
        sourceList.add(new DataVm(1, "Title 1", "Description 1", "", false));
        sourceList.add(new DataVm(2, "Title 2", "Description 2", "", false));
        sourceList.add(new DataVm(3, "Title 3", "Description 3", "", false));
        sourceList.add(new DataVm(4, "Title 4", "Description 4", "", false));
        sourceList.add(new DataVm(5, "Title 5", "Description 5", "", false));
        sourceList.add(new DataVm(6 , "Title 6 ", "Description 6 ", "", false));
        sourceList.add(new DataVm(7 , "Title 7 ", "Description 7 ", "", false));
        sourceList.add(new DataVm(8 , "Title 8 ", "Description 8 ", "", false));
        sourceList.add(new DataVm(9 , "Title 9 ", "Description 9 ", "", false));
        sourceList.add(new DataVm(10, "Title 10", "Description 10", "", false));
        sourceList.add(new DataVm(11, "Title 11", "Description 11", "", false));
        sourceList.add(new DataVm(12, "Title 12", "Description 12", "", false));
    }

    public List<DataVm> getSourceList(String searchTitle) {

        if (searchTitle.equals(""))
            return sourceList;

        List<DataVm> filteredList = new ArrayList<>();

        for (DataVm item : sourceList) {

            if (item.getTitle().contains(searchTitle)) {
                filteredList.add(item);
            }
        }

        return filteredList;
    }

    public void setSourceList(List<DataVm> sourceList) {
        this.sourceList = sourceList;
    }
}

А второй вспомогательный класс - это в основном элемент класса для каждой строки:

public class DataVm {

    private int ItemId;
    private String Title;
    private String Description;
    private String Image;
    private boolean IsPicked;

    public DataVm (int itemId, String title, String description, String image, boolean isPicked) {
        ItemId = itemId;
        Title = title;
        Description = description;
        Image = image;
        IsPicked = isPicked;
    }

    public int getItemId() {
        return ItemId;
    }

    public void setItemId(int itemId) {
        ItemId = itemId;
    }

    public String getTitle() {
        return Title;
    }

    public void setTitle(String title) {
        Title = title;
    }

    public String getDescription() {
        return Description;
    }

    public void setDescription(String description) {
        Description = description;
    }

    public String getImage() {
        return Image;
    }

    public void setImage(String image) {
        Image = image;
    }

    public boolean isPicked() {
        return IsPicked;
    }

    public void setPicked(boolean picked) {
        IsPicked = picked;
    }
}

Наконец, два последних класса - это адаптер для списка и держатель представления для него.

Класс адаптера:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<DataVm> mItemList;
    private IClickListenerAddRemove listener;

    public RecyclerViewAdapter(List<DataVm> itemList, IClickListenerAddRemove listener) {

        mItemList = itemList;
        this.listener = listener;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.salad_creation_item_template, parent, false);
        return new RecyclerViewHolder(view, listener);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {

        RecyclerViewHolder holder = (RecyclerViewHolder) viewHolder;
        DataVm item = mItemList.get(position);

        holder.setTitle(item.getTitle());
        holder.setDescription(item.getDescription());
        holder.setIsPicked(item.isPicked());

        if (item.isPicked())
            holder.setButtonDrawable(R.drawable.ic_remove_24dp);
        else
            holder.setButtonDrawable(R.drawable.ic_add_24dp);
    }

    @Override
    public int getItemCount() {
        return mItemList == null ? 0 : mItemList.size();
    }

}

И последний - держатель просмотра для списка:

public class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private TextView txtTitle;
    private TextView txtDescription;
    private ImageButton btnChecking;
    private WeakReference<IClickListenerAddRemove> listenerRef;
    private boolean mIsPicked = false;

    public RecyclerViewHolder(View root, IClickListenerAddRemove listener) {
        super(root);

        listenerRef = new WeakReference<>(listener);
        txtTitle = root.findViewById(R.id.txtTitle);
        txtDescription = root.findViewById(R.id.txtDescription);
        btnChecking = root.findViewById(R.id.btnAction);

        btnChecking.setOnClickListener(this);
    }

    public void setIsPicked(boolean mIsPicked) {
        this.mIsPicked = mIsPicked;
    }

    public void setTitle(CharSequence text) {
        txtTitle.setText(text);
    }

    public void setDescription(CharSequence text) {
        txtDescription.setText(text);
    }

    public void setButtonDrawable(int drawableId) {
        btnChecking.setImageResource(drawableId);
    }

    @Override
    public void onClick(View v) {

        if (v.getId() == btnChecking.getId()) {

            if (!mIsPicked) {
                btnChecking.setImageResource(R.drawable.ic_remove_24dp);
                mIsPicked = true;
            }
            else {
                btnChecking.setImageResource(R.drawable.ic_add_24dp);
                mIsPicked = false;
            }
            listenerRef.get().onPositionClicked(getAdapterPosition(), mIsPicked);
        }
    }
}

Структура этого выглядит так: Structure

Другие вопросы по теме