How to create an Expandable CardView in Android

Expandable Cardview provides to create expansion panels without too much hassle and without writing boilerplate code. An expandable card-view becomes quite useful when it comes to an efficient and systematic presentation of data or information on the screen. It is used in a variety of apps, for example, the Contacts app or the Gallery app. Here, in this tutorial, we’ll create a simple Expandable CardView in Android using Java.
Expandable card view

Approach

Step 1: Create a New Project in Android Studio

  1. Click on File, then New => New Project.
  2. Choose “Empty Activity” for the project template.
  3. Select language as Java.
  4. Select the minimum SDK as per your need.

Step 2: Add the CardView Dependency

To be able to use the CardView element, you’ll first have to add it’s dependency in the project. In the build.gradle (Module: app) file add the following dependency and click on Sync now to synchronize the changes made.

implementation ‘androidx.cardView:cardView:1.0.0’



Step 3: Add all the Required Drawable Resources in the Drawable Folder

Choose the drawable resources as per the requirement. Here, in the CardView, use two images of the GeeksforGeeks icons and 2 other icons to indicate either of the ‘expand more’ or ‘expand less’ options. The following are the geeksforgeeks icons used:
icon_one
icon_two

The image below shows the use of expansion icons:
exapnsion icons

The expansion icons used here are imported as a vector asset from the Android Studio itself. The steps for the same are as follows:

  1. Right-click on the drawable resource folder.
  2. Go to new.
  3. Click on Vector Asset.
  4. The following box pops up. Click on the icon next to Clip Art.
    vector asset
  5. From the variety of icons shown, choose the following two icons:
    list of icons

    ic_baseline_expand_more_24
    ic_baseline_expand_less_24
    

    The following files get added to the drawable folder:

    ic_baseline_expand_more_24

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24"
        android:tint="?attr/colorControlNormal">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M16.59, 8.59L12, 13.17 7.41, 
                           8.59 6, 10l6, 6 6, -6z"/>
    </vector>

    chevron_right

    
    

    ic_baseline_expand_less_24

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24"
        android:tint="?attr/colorControlNormal">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M12, 8l-6, 6 1.41, 1.41L12, 
                          10.83l4.59, 4.58L18, 14z"/>
    </vector>

    chevron_right

    
    

Step 4: Modify the XML Layout

In the XML file, create the entire layout along with the portion that you want to be displayed after the CardView is expanded. The basic idea here is to set the visibility of the expandable element to ‘gone’ or ‘visible’.

Note: Set the visibility to ‘gone’ and not ‘invisible’ because ‘gone’ removes that particular element completely as if it was never there. However, ‘invisible’ only makes the element disappears while it still exists in the layout.

In the below layout, expanded the CardView to display a list of three subjects. The following is the code for activity_main.xml file.

filter_none

edit
close

play_arrow

link
brightness_4
code

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#E4E3E3"
    tools:context=".MainActivity">
  
    <!--Base CardView-->
    <androidx.cardview.widget.CardView
        android:id="@+id/base_cardview"
        style="@style/Base.CardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.473"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.021">
  
        <!--This is a ConstraintLayout for the entire CardView 
                   including the expandable portion-->
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="@+id/base_cardview"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.511"
            tools:layout_editor_absoluteX="-55dp">
  
            <!--This is a ConstraintLayout for the fixed portion
                of the CardView. The elements 
                that lie within the fixed portion of the CardView
                can be constrained to this layout.-->
            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/fixed_layout"
                android:layout_width="match_parent"
                android:layout_height="150dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintVertical_bias="0.0">
  
  
                <ImageView
                    android:id="@+id/icon"
                    android:layout_width="150dp"
                    android:layout_height="150dp"
                    android:src="@drawable/icon_one"
                    app:layout_constraintBottom_toBottomOf="@+id/fixed_layout"
                    app:layout_constraintEnd_toEndOf="@+id/fixed_layout"
                    app:layout_constraintHorizontal_bias="0.0"
                    app:layout_constraintStart_toStartOf="@+id/fixed_layout"
                    app:layout_constraintTop_toTopOf="@+id/fixed_layout"
                    app:layout_constraintVertical_bias="1.0" />
  
                <TextView
                    android:id="@+id/heading"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="GeeksforGeeks"
                    android:textColor="#006600"
                    android:textSize="25dp"
                    android:textStyle="bold"
                    app:layout_constraintBottom_toBottomOf="@+id/fixed_layout"
                    app:layout_constraintEnd_toEndOf="@+id/fixed_layout"
                    app:layout_constraintHorizontal_bias="0.926"
                    app:layout_constraintStart_toStartOf="@+id/fixed_layout"
                    app:layout_constraintTop_toTopOf="@+id/fixed_layout"
                    app:layout_constraintVertical_bias="0.198" />
  
                <TextView
                    android:id="@+id/list_of_subjects"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="20dp"
                    android:layout_marginBottom="58dp"
                    android:text="List of subjects"
                    android:textSize="20dp"
                    app:layout_constraintBottom_toBottomOf="@+id/fixed_layout"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintHorizontal_bias="0.878"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/heading"
                    app:layout_constraintVertical_bias="0.0" />
  
                <!--This is ImageButton for the expansion icon.-->
                <ImageButton
                    android:id="@+id/arrow_button"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/ic_baseline_expand_more_24"
                    app:layout_constraintBottom_toBottomOf="@id/fixed_layout"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintHorizontal_bias="0.802"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/list_of_subjects"
                    app:layout_constraintVertical_bias="0.0" />
  
            </androidx.constraintlayout.widget.ConstraintLayout>
  
            <!--The following is the expandable portion whose 
                visibility is initially set to 'gone'.
                The parent LinearLayout contains 3 child LinearLayouts
                that hold a subject name and an icon each.-->
            <LinearLayout
                android:id="@+id/hidden_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:visibility="gone"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/fixed_layout">
  
                <!--Child LinearLayout 1-->
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="horizontal">
  
                    <ImageView
                        android:layout_width="50dp"
                        android:layout_height="50dp"
                        android:layout_marginStart="20dp"
                        android:layout_marginTop="10dp"
                        android:layout_marginEnd="10dp"
                        android:layout_marginBottom="10dp"
                        android:src="@drawable/gfg_icon_black" />
  
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="20dp"
                        android:layout_marginTop="20dp"
                        android:text="Database Management"
                        android:textColor="#000000"
                        android:textSize="20dp" />
                </LinearLayout>
  
                <!--Child LinearLayout 2-->
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="horizontal">
  
                    <ImageView
                        android:layout_width="50dp"
                        android:layout_height="50dp"
                        android:layout_marginStart="20dp"
                        android:layout_marginTop="10dp"
                        android:layout_marginEnd="10dp"
                        android:layout_marginBottom="10dp"
                        android:src="@drawable/gfg_icon_black" />
  
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="20dp"
                        android:layout_marginTop="20dp"
                        android:text="Data Structures"
                        android:textColor="#000000"
                        android:textSize="20dp" />
                </LinearLayout>
  
                <!--Child LinearLayout 3-->
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="horizontal">
  
                    <ImageView
                        android:layout_width="50dp"
                        android:layout_height="50dp"
                        android:layout_marginStart="20dp"
                        android:layout_marginTop="10dp"
                        android:layout_marginEnd="10dp"
                        android:layout_marginBottom="10dp"
                        android:src="@drawable/gfg_icon_black" />
  
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="20dp"
                        android:layout_marginTop="20dp"
                        android:text="Operating Systems"
                        android:textColor="#000000"
                        android:textSize="20dp" />
                </LinearLayout>
            </LinearLayout>
  
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>
  
</androidx.constraintlayout.widget.ConstraintLayout>

chevron_right


Step 5: Modify the Java File

In the MainActivity.java, using the if-else statements, specify the conditions to manipulate the visibility of the expandable element.

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.android.expandable_cardview;
  
import android.os.Bundle;
import android.transition.AutoTransition;
import android.transition.TransitionManager;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.cardview.widget.CardView;
  
public class MainActivity extends AppCompatActivity {
  
    ImageButton arrow;
    LinearLayout hiddenView;
    CardView cardView;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
  
        cardView = findViewById(R.id.base_cardview);
        arrow = findViewById(R.id.arrow_button);
        hiddenView = findViewById(R.id.hidden_view);
  
        arrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
  
                // If the CardView is already expanded, set its visibility
                //  to gone and change the expand less icon to expand more.
                if (hiddenView.getVisibility() == View.VISIBLE) {
  
                    // The transition of the hiddenView is carried out
                    //  by the TransitionManager class.
                    // Here we use an object of the AutoTransition 
                    // Class to create a default transition.
                    TransitionManager.beginDelayedTransition(cardView, 
                                                  new AutoTransition());
                    hiddenView.setVisibility(View.GONE);
                    arrow.setImageResource(R.drawable.ic_baseline_expand_more_24);
                }
  
                // If the CardView is not expanded, set its visibility 
                // to visible and change the expand more icon to expand less.
                else {
  
                    TransitionManager.beginDelayedTransition(cardView,
                                                new AutoTransition());
                    hiddenView.setVisibility(View.VISIBLE);
                    arrow.setImageResource(R.drawable.ic_baseline_expand_less_24);
                }
            }
        });
    }
}

chevron_right


Output: Run on Emulator

Attention reader! Don’t stop learning now. Get hold of all the important Java and Collections concepts with the Fundamentals of Java and Java Collections Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :
Practice Tags :


1


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.