how to make an expandable list of cardviews?
Asked Answered
B

2

8

I searched a lot to find a direct and clear solution for I think a popular problem but unfortunately I couldn't find it.

We want to have a list of cardviews so each card bind to a specific data and each card has a list inside that shows meta or detail data about its parent.

So we have a nested list inside a cardview.

With a simple search, we know that we should use expanded list view which parents items are cardviews and we must have another layout for its child.

So when you click on cards a list of items appears below of your cards on the root. But we want to show child list inside of cards?

And there is no access to the something like child list id or any other things to refer to a transition animation and change of layout.

So the clear question is how to add a listview inside a cardview?

i follow my work by using tablelayout and table row. and prefer not to use external libraries for stability and version problems. this is what i mean.

Image that describe my question

image that describe my question

Boyhood answered 7/7, 2016 at 3:0 Comment(2)
i use expandableListView and BaseExpandableListAdapter with two layouts, one for the card which inflates in groupgetView and one for detail list inflate in child GetView. by this the list add below and outside of the cards, i tried to attach the childview to the parent by inflate.inflate(layout,parent,true); but its need addview. and try to include the child layout in parent layout but it doesn't work too. i done my work know by tablerows. i edit my answer by adding a picBoyhood
i prefer not to use external libraries...Boyhood
G
23

If you don't want to use an external library, you can make your CardView expand like this:

Layout file for an expandable CardView

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/cv"
android:layout_marginTop="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
card_view:cardCornerRadius="5dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="48dp"
            >

            <TextView
                android:id="@+id/textView_name"
                android:layout_marginTop="10dp"
                android:layout_marginBottom="10dp"
                android:textSize="18sp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textStyle="bold" />

            <!--My dropdown Button -->
            <RelativeLayout
                android:id="@+id/button"
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:layout_gravity="end"
                android:layout_alignParentRight="true"
                android:gravity="center"
                >

                <View
                    android:layout_width="12dp"
                    android:layout_height="12dp"
                    android:background="@drawable/triangle"
                    android:layout_alignParentRight="false"
                    android:layout_alignParentEnd="false" />
            </RelativeLayout>
        </RelativeLayout>
         <!--The layout below is my ExpandableLayout -->
        <LinearLayout
            android:id="@+id/expandableLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            >

            <android.support.v7.widget.AppCompatImageView
                android:id="@+id/imageView_Owner"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/textView_Owner"
                    android:textSize="16sp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />
                <TextView
                    android:id="@+id/textView_OwnerUrl"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />


            </LinearLayout>

        </LinearLayout>

    </LinearLayout>

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

My ExpandableRecyclerAdapter Class

import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.squareup.picasso.Picasso;
import java.util.List;


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

private List<Repo> repos;
private SparseBooleanArray expandState = new SparseBooleanArray();
private Context context;

public ExpandableRecyclerAdapter(List<Repo> repos) {
    this.repos = repos;
    //set initial expanded state to false
    for (int i = 0; i < repos.size(); i++) {
        expandState.append(i, false);
    }
}

@Override
public ExpandableRecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    this.context = viewGroup.getContext();
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.expandable_card_row, viewGroup, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(final ExpandableRecyclerAdapter.ViewHolder viewHolder, final  int i) {

    viewHolder.setIsRecyclable(false);

    viewHolder.tvName.setText(repos.get(i).getName());

    viewHolder.tvOwnerLogin.setText("Owner: " +repos.get(i).getOwner().getLogin());
    viewHolder.tvOwnerUrl.setText(repos.get(i).getOwner().getUrl());

    Picasso.with(context)
            .load(repos.get(i).getOwner().getImageUrl())
            .resize(500, 500)
            .centerCrop()
            .into(viewHolder.ivOwner);

    //check if view is expanded
    final boolean isExpanded = expandState.get(i);
    viewHolder.expandableLayout.setVisibility(isExpanded?View.VISIBLE:View.GONE);

    viewHolder.buttonLayout.setRotation(expandState.get(i) ? 180f : 0f);
    viewHolder.buttonLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(final View v) {
            onClickButton(viewHolder.expandableLayout, viewHolder.buttonLayout,  i);
        }
    });
}

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

public class ViewHolder extends RecyclerView.ViewHolder{

    private TextView tvName,tvOwnerLogin, tvOwnerUrl;
    private ImageView ivOwner;
    public RelativeLayout buttonLayout;
    public LinearLayout expandableLayout;

    public ViewHolder(View view) {
        super(view);

        tvName = (TextView)view.findViewById(R.id.textView_name);
        tvId = (TextView)view.findViewById(R.id.textView_id);
        tvUrl = (TextView)view.findViewById(R.id.textView_url);
        tvOwnerLogin = (TextView)view.findViewById(R.id.textView_Owner);
        tvOwnerUrl = (TextView)view.findViewById(R.id.textView_OwnerUrl);
        ivOwner = (ImageView) view.findViewById(R.id.imageView_Owner);

        buttonLayout = (RelativeLayout) view.findViewById(R.id.button);
        expandableLayout = (LinearLayout) view.findViewById(R.id.expandableLayout);
    }
}

private void onClickButton(final LinearLayout expandableLayout, final RelativeLayout buttonLayout, final  int i) {

    //Simply set View to Gone if not expanded
    //Not necessary but I put simple rotation on button layout
    if (expandableLayout.getVisibility() == View.VISIBLE){
        createRotateAnimator(buttonLayout, 180f, 0f).start();
        expandableLayout.setVisibility(View.GONE);
        expandState.put(i, false);
    }else{
        createRotateAnimator(buttonLayout, 0f, 180f).start();
        expandableLayout.setVisibility(View.VISIBLE);
        expandState.put(i, true);
    }
}

//Code to rotate button
private ObjectAnimator createRotateAnimator(final View target, final float from, final float to) {
    ObjectAnimator animator = ObjectAnimator.ofFloat(target, "rotation", from, to);
    animator.setDuration(300);
    animator.setInterpolator(new LinearInterpolator());
    return animator;
}
}

In your Activity/Fragment, set up RecyclerView like this

private RecyclerView recyclerView;
private List<Repo> data;

recyclerView = (RecyclerView)findViewById(R.id.card_recycler_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
//fetch data and on ExpandableRecyclerAdapter
recyclerView.setAdapter(new ExpandableRecyclerAdapter(data));

So, its quite simple to create an expandable CardView without external Library. The code is almost exactly the same as using a normal CardView with RecyclerView, the main change is setting the View.GONE/View.VISIBLE on button click.

Grith answered 11/3, 2017 at 21:1 Comment(4)
no problem at all. simple clean perfect. nice one, thank youLabile
Thank you very much. Worked for me tooOstrich
Thanks, Worked for me!Philo
Thank you, saved my timeKumamoto
K
0

You can use ExpandLayout,and then add it in cardview.

<com.kyo.expandablelayout.ExpandableLayout
        android:id="@+id/expandlayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="12dp" >

        <ImageView
            android:id="@+id/imageview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:contentDescription="@null"
            android:scaleType="centerCrop"
            android:src="@drawable/parent" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="6dp"
            android:contentDescription="@null"
            android:scaleType="centerCrop"
            android:src="@drawable/child"
            app:canExpand="true" />
    </com.kyo.expandable.ExpandableLayout>
Kimberelykimberlee answered 7/7, 2016 at 3:51 Comment(1)
How do you add it to the cardview? Please provide complete answersDiapophysis

© 2022 - 2024 — McMap. All rights reserved.