faizanjehangir
faizanjehangir

Reputation: 2841

Add multiple expandable cardviews to layout

I am using AleSpero's library to create expandable cardviews for my layout. Works as expected, but now I want to add multiple cardviews in the same fragment layout, dynamically binding to some async list data that loads. How would that be possible?

Followed the demo on the library. Here is how I am adding the cards in the layout:

<LinearLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/watchlist_holder"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="20dp"
    android:orientation="vertical"
    android:clipChildren="false"
    android:background="#FAFAFA">

    <com.alespero.expandablecardview.ExpandableCardView
         android:id="@+id/main_profile_card"
         android:layout_marginLeft="10dp"
         android:layout_marginRight="10dp"
         android:layout_marginTop="10dp"
         android:layout_marginBottom="10dp"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         app:title="My Watchlist"
         app:inner_view="@layout/watchlist_layout"
         app:expandOnClick="true" />
</LinearLayout>

@layout/watchlist_layout is a layout I want to repeat, it contain some textView and a recyclerView to show list data. Any help or guidance would be great.

Upvotes: 0

Views: 999

Answers (1)

Atish Agrawal
Atish Agrawal

Reputation: 2877

You will need to create different Adapter and Inner Row XML Layout files for each RecyclerView.

For Ex: You inflate a layout in a RecyclerView inside the MainActivity. You are using an Adapter class which is inflating the rows based on your List. Inside onBindViewHolder, you should get the object of the inner RecyclerView which is present in the row layout of the parent view. Once you have the object, create another list and initialize another adapter for the inner recyclerview. Use the new adapter to populate data inside it (similar to the first recyclerview).

Keep in mind, the process remains same, with each recyclerview

Steps:

  1. Create recylcerview inside the layout which is going to display the list
  2. Create a separate row_layout to be inflated in each row based on the number of list data
  3. Crete an Adapter class, which receives data from the parent class and inflates the layout (row_ayout) in the recyclerview
  4. Repeat these steps for N number of Nested RecyclerViews

For the demo, I am attaching sample codes with this answer to help you understand my concept.

activity_main.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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recylcerViewParent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

item_layout_row.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <com.alespero.expandablecardview.ExpandableCardView
        android:id="@+id/main_profile_card"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="10dp"
        app:expandOnClick="true"
        app:inner_view="@layout/watchlist_inner"
        app:title="My Watchlist" />

</RelativeLayout>

item_recycler_view_favorite.xml

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


    <TextView
        android:id="@+id/favorites_count"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/margin_small"
        android:layout_marginLeft="@dimen/margin_small"
        android:textSize="12sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/margin_small"
        android:layout_marginEnd="@dimen/margin_small"
        android:orientation="horizontal"
        android:weightSum="2">

        <Button
            android:id="@+id/btn_view_details"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:background="@android:color/transparent"
            android:gravity="start|center_vertical"
            android:padding="5dp"
            android:text="Atish"
            android:textColor="@color/colorPrimaryDark" />

        <Button
            android:id="@+id/btn_add_symbols"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:background="@android:color/transparent"
            android:gravity="end|center_vertical"
            android:padding="5dp"
            android:text="Agrawal"
            android:textColor="@color/colorPrimaryDark" />
    </LinearLayout>


</LinearLayout>

watchlist_inner.xml

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


    <TextView
        android:id="@+id/favorites_count"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/margin_small"
        android:layout_marginLeft="@dimen/margin_small"
        android:textSize="12sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/margin_small"
        android:layout_marginEnd="@dimen/margin_small"
        android:orientation="horizontal"
        android:weightSum="2">

        <Button
            android:id="@+id/btn_view_details"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:background="@android:color/transparent"
            android:gravity="start|center_vertical"
            android:padding="5dp"
            android:text="VIEW DETAILS"
            android:textColor="@color/colorPrimaryDark" />

        <Button
            android:id="@+id/btn_add_symbols"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:background="@android:color/transparent"
            android:gravity="end|center_vertical"
            android:padding="5dp"
            android:text="ADD SYMBOLS"
            android:textColor="@color/colorPrimaryDark" />
    </LinearLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view_favorite"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="@dimen/margin_small"
        android:layout_marginEnd="@dimen/margin_small"
        android:layout_marginBottom="@dimen/margin_small" />

</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {


    List<String> stringsList = new ArrayList<>();

    RecyclerView recyclerViewLayout;
    InnerAdapter adapter;


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


        recyclerViewLayout = findViewById(R.id.recylcerViewParent);


        //Dummy add 10 objects in the list

        for (int i = 0; i < 10; i++) {
            stringsList.add(String.valueOf(i));
        }


        populateRecyclerView();
    }


    /**
     * Create N items in the recycler view
     */
    private void populateRecyclerView() {


        //Initialize Adapter

        recyclerViewLayout.setLayoutManager(new LinearLayoutManager(this));
        recyclerViewLayout.setHasFixedSize(false);

        adapter = new InnerAdapter(recyclerViewLayout, this);
        adapter.setData(this.stringsList);
        recyclerViewLayout.setAdapter(adapter);


    }
}

InnerAdapter.java

public class InnerAdapter extends RecyclerView.Adapter<InnerAdapter.ViewHolder> {
    private List<String> data;
    private RecyclerView recyclerView;
    private int i = 0;
    private Context mContext;

    public InnerAdapter(RecyclerView recyclerView, Context context) {
        this.recyclerView = recyclerView;
        this.mContext = context;

    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        //Inflater creates rows from a given layout file


        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View v = inflater.inflate(R.layout.item_layout_row, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        //Method to perform actions on individual row based on the position. We will get back to this later


        //Change the title of the CardView
        holder.main_profile_card.setTitle(String.valueOf(position));


        //Creating a dummy adapter again to populate the inner recyclerview
        List<String> innerData = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            innerData.add(String.valueOf(i));
        }

        //Initialize Inner Adapter
        holder.recycler_view_favorite.setLayoutManager(new LinearLayoutManager(mContext));
        holder.recycler_view_favorite.setHasFixedSize(false);
        InnerFavAdapter adapter = new InnerFavAdapter(holder.recycler_view_favorite, mContext);
        adapter.setData(innerData);
        holder.recycler_view_favorite.setAdapter(adapter);

    }

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

    public void setData(List<String> data) {
        this.data = data;
    }

    class ViewHolder extends RecyclerView.ViewHolder {

        RecyclerView recycler_view_favorite;
        ExpandableCardView main_profile_card;

        ViewHolder(View itemView) {
            super(itemView);

            //Get the object of the views from the row layout
            main_profile_card = itemView.findViewById(R.id.main_profile_card);
            recycler_view_favorite = itemView.findViewById(R.id.recycler_view_favorite);
        }
    }
}

InnerFavAdapter.java

public class InnerFavAdapter extends RecyclerView.Adapter<InnerFavAdapter.ViewHolder> {
    private List<String> data;
    private RecyclerView recyclerView;
    private int i = 0;
    private Context mContext;

    public InnerFavAdapter(RecyclerView recyclerView, Context context) {
        this.recyclerView = recyclerView;
        this.mContext = context;

    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        //Inflater creates rows from a given layout file


        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View v = inflater.inflate(R.layout.inner_recycler_view_favorite, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        //Method to perform actions on individual row based on the position. We will get back to this later


    }

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

    public void setData(List<String> data) {
        this.data = data;
    }

    class ViewHolder extends RecyclerView.ViewHolder {

        ViewHolder(View itemView) {
            super(itemView);


        }
    }
}

Upvotes: 1

Related Questions