1

I have multiple checkboxes (switches in my case), in a nested recycler view. It looks like the following :

enter image description here

I want to be able to retrieve all switch states on this screen when the user goes back and be able to identify which one’s are set to true. For example, I’m looking to obtain something in a similar format to this: [Item 0, Sub Item 1, TRUE], [Item 0, Sub Item 2, TRUE], [Item 1, Sub Item 0, TRUE] , etc.

My issue is that I’m not exactly sure how to store these switch states. I'm not sure how to get the specific switch values here when they're placed in a nested recycler view.

Here is the code I'm following:

MainActivity

package com.example.recycledviewpoolexample;

import android.nfc.Tag;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

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

        RecyclerView rvItem = findViewById(R.id.rv_item);
        LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
        ItemAdapter itemAdapter = new ItemAdapter(buildItemList());
        rvItem.setAdapter(itemAdapter);
        rvItem.setLayoutManager(layoutManager);
    }

    private List<Item> buildItemList() {
        List<Item> itemList = new ArrayList<>();
        for (int i=0; i<10; i++) {
            Item item = new Item("Item "+i, buildSubItemList());
            itemList.add(item);
        }
        return itemList;
    }

    private List<SubItem> buildSubItemList() {
        List<SubItem> subItemList = new ArrayList<>();
        for (int i=0; i<3; i++) {
            SubItem subItem = new SubItem("Sub Item "+i, false);
            subItemList.add(subItem);
        }
        return subItemList;
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");

        /*if Checkboxes are true, store/display them in the logs

        EXAMPLE OUTPUT:
        Item (String)
        SubItem (String)
         */
    }
}

Item.java

public class Item {
    private String itemTitle;
    private List<SubItem> subItemList;

    public Item(String itemTitle, List<SubItem> subItemList) {
        this.itemTitle = itemTitle;
        this.subItemList = subItemList;
    }

    public String getItemTitle() {
        return itemTitle;
    }

    public void setItemTitle(String itemTitle) {
        this.itemTitle = itemTitle;
    }

    public List<SubItem> getSubItemList() {
        return subItemList;
    }

    public void setSubItemList(List<SubItem> subItemList) {
        this.subItemList = subItemList;
    }
}

ItemAdapter

public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemViewHolder> {

    private RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
    private List<Item> itemList;

    ItemAdapter(List<Item> itemList) {
        this.itemList = itemList;
    }

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

    @Override
    public void onBindViewHolder(@NonNull ItemViewHolder itemViewHolder, int i) {
        Item item = itemList.get(i);
        itemViewHolder.tvItemTitle.setText(item.getItemTitle());

        // Create layout manager with initial prefetch item count
        LinearLayoutManager layoutManager = new LinearLayoutManager(
                itemViewHolder.rvSubItem.getContext(),
                LinearLayoutManager.VERTICAL,
                false
        );
        layoutManager.setInitialPrefetchItemCount(item.getSubItemList().size());

        // Create sub item view adapter
        SubItemAdapter subItemAdapter = new SubItemAdapter(item.getSubItemList());

        itemViewHolder.rvSubItem.setLayoutManager(layoutManager);
        itemViewHolder.rvSubItem.setAdapter(subItemAdapter);
        itemViewHolder.rvSubItem.setRecycledViewPool(viewPool);
    }

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

    class ItemViewHolder extends RecyclerView.ViewHolder {
        private TextView tvItemTitle;
        private RecyclerView rvSubItem;

        ItemViewHolder(View itemView) {
            super(itemView);
            tvItemTitle = itemView.findViewById(R.id.tv_item_title);
            rvSubItem = itemView.findViewById(R.id.rv_sub_item);
        }
    }
}

SubItem.java

package com.example.recycledviewpoolexample;

public class SubItem {
    private int subItemImage;
    private String subItemTitle;
    private boolean checkbox;

    public SubItem(String subItemTitle, boolean checkbox) {
        this.subItemTitle = subItemTitle;
        this.checkbox = checkbox;
    }

    public int getSubItemImage() {
        return subItemImage;
    }

    public void setSubItemImage(int subItemImage) {
        this.subItemImage = subItemImage;
    }

    public String getSubItemTitle() {
        return subItemTitle;
    }

    public void setSubItemTitle(String subItemTitle) {
        this.subItemTitle = subItemTitle;
    }

    public boolean isSelected() {
        return checkbox;
    }

    public void setCheckbox(boolean checkbox) {
        this.checkbox = checkbox;
    }
}

SubItemAdapter.java

public class SubItemAdapter extends RecyclerView.Adapter<SubItemAdapter.SubItemViewHolder> {

    private List<SubItem> subItemList;

    SubItemAdapter(List<SubItem> subItemList) {
        this.subItemList = subItemList;
    }

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

    @Override
    public void onBindViewHolder(@NonNull SubItemViewHolder subItemViewHolder, int i) {
        final SubItem subItem = subItemList.get(i);
        subItemViewHolder.tvSubItemTitle.setText(subItem.getSubItemTitle());
        subItemViewHolder.checkBox.setOnCheckedChangeListener(null);
        subItemViewHolder.checkBox.setChecked(subItem.isSelected());

        subItemViewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                subItem.setCheckbox(isChecked);

            }
        });
    }

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

    class SubItemViewHolder extends RecyclerView.ViewHolder {
        TextView tvSubItemTitle;
        Switch checkBox;

        SubItemViewHolder(View itemView) {
            super(itemView);
            tvSubItemTitle = itemView.findViewById(R.id.tv_sub_item_title);
            checkBox = itemView.findViewById(R.id.switch1);
        }
    }
}

layout_sub_item.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="12dp">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <ImageView
                android:id="@+id/img_sub_item"
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:background="@color/colorPrimaryDark"
                android:src="@drawable/ic_launcher_foreground"/>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_toEndOf="@id/img_sub_item"
                android:padding="12dp"
                android:orientation="vertical">
                <TextView
                    android:id="@+id/tv_sub_item_title"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textStyle="bold"
                    android:text="Sub item title"/>

                <Switch
                    android:id="@+id/switch1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
            </LinearLayout>

        </RelativeLayout>
    </android.support.v7.widget.CardView>

</FrameLayout>

layout_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardBackgroundColor="#f3f3f3"
        app:cardElevation="8dp"
        android:layout_margin="12dp">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="12dp"
            android:orientation="vertical">
            <TextView
                android:id="@+id/tv_item_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="12sp"
                android:textSize="18sp"
                android:text="Item Title"/>
            <android.support.v7.widget.RecyclerView
                android:id="@+id/rv_sub_item"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
        </LinearLayout>
    </android.support.v7.widget.CardView>

</LinearLayout>

Any help would be appreciated. Thanks!

pshaun
  • 47
  • 6
  • 1
    Please refer [this](https://stackoverflow.com/a/38929462/4613320) – Maddy Dec 03 '19 at 06:19
  • Thank you, that was helpful. I am able to get the sub item name and checkbox, but I don't know how to get the parent (main) item as well and store it in a similar format to this: [Item 0, Sub Item 1, TRUE], [Item 0, Sub Item 2, TRUE], [Item 1, Sub Item 0, TRUE] – pshaun Dec 03 '19 at 19:09
  • 1
    remove `subItem.setCheckbox(isChecked)` and make it `subItemList.get(getAdapterPosition()).setCheckbox(isChecked)` – Maddy Dec 04 '19 at 04:05
  • Could you help explain what this difference makes? I'm not entirely sure how I can get the Main item here. I know I can do `subItem.getSubItemTitle()` and `subItem.isSelected` to get the sub item and checkbox state respectively, but i'm still confused how to determine the parent Item from the Item.java class – pshaun Dec 04 '19 at 15:48
  • Okay so I think I was able to figure it out, but I tried storing just the Main Item and Sub Item values in a HashMap like this `hashMap.put(subItemList.get(position).getMainItemTitle(),subItemList.get(position).getSubItemTitle());` but it looks like it only stores one value at a time and gets overwritten whenever `setOnCheckedChangeListener()` is called . So if I select multiple checkboxes, it only contains the value of most recent switch that was pressed. What am I doing wrong here, and how can I fix this? – pshaun Dec 04 '19 at 22:03
  • No dear, you were updating the state of a model object which will be recycled when you scroll the RecyclerView, so I suggested to update the state to the arraylist directly – Maddy Dec 05 '19 at 04:13

0 Answers0