Tuesday, 7 March 2017

Android ExpandableListView With Custom Layout

    This two dependency add into your build.gradle file for the CardView. colors add into color.xml file and CardView style CardViewDefault add into style file.
build.gradle (dependency)

compile 'com.android.support:design:25.0.1'
compile 'com.android.support:cardview-v7:25.0.1'
colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>

    <color name="color_blue">#2672FF</color>
</resources>
styles.xml

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="CardViewDefault" parent="CardView">
        <item name="cardElevation">3dp</item>
        <item name="contentPadding">5dp</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_marginTop">5dp</item>
        <item name="android:layout_marginLeft">5dp</item>
        <item name="android:layout_marginRight">5dp</item>
        <item name="android:layout_marginBottom">5dp</item>
    </style>

</resources>
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:gravity="center"
    android:orientation="vertical"
    tools:context="com.androidsimplifycodes.example.MainActivity">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

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

            <android.support.v7.widget.CardView
                style="@style/CardViewDefault"
                app:contentPadding="0dp">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical">

                    <LinearLayout
                        android:id="@+id/llExpandableHeadingOneClick"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:background="@color/color_blue"
                        android:orientation="horizontal"
                        android:weightSum="1">

                        <TextView
                            android:layout_width="0dp"
                            android:layout_height="match_parent"
                            android:layout_weight="0.9"
                            android:padding="10dp"
                            android:text="Expandable Heading 1"
                            android:textAppearance="?android:textAppearanceMedium"
                            android:textColor="@android:color/white" />

                        <ImageView
                            android:layout_width="0dp"
                            android:layout_height="match_parent"
                            android:layout_gravity="center"
                            android:layout_weight="0.1"
                            android:contentDescription="@null"
                            android:padding="5dp"
                            android:src="@drawable/ic_arrow_down" />

                    </LinearLayout>

                    <LinearLayout
                        android:id="@+id/llExpandableHeadingOne"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                        android:padding="5dp">

                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:text="@string/my_text"
                            android:textAppearance="?android:textAppearanceMedium"
                            android:textColor="@android:color/black" />

                    </LinearLayout>

                    <View
                        android:layout_width="match_parent"
                        android:layout_height="1dp"
                        android:background="@android:color/white" />

                    <LinearLayout
                        android:id="@+id/llExpandableHeadingTwoClick"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:background="@color/color_blue"
                        android:orientation="horizontal"
                        android:weightSum="1">

                        <TextView
                            android:layout_width="0dp"
                            android:layout_height="match_parent"
                            android:layout_weight="0.9"
                            android:padding="10dp"
                            android:text="Expandable Heading 2"
                            android:textAppearance="?android:textAppearanceMedium"
                            android:textColor="@android:color/white" />

                        <ImageView
                            android:layout_width="0dp"
                            android:layout_height="match_parent"
                            android:layout_gravity="center"
                            android:layout_weight="0.1"
                            android:contentDescription="@null"
                            android:padding="5dp"
                            android:src="@drawable/ic_arrow_down" />

                    </LinearLayout>

                    <LinearLayout
                        android:id="@+id/llExpandableHeadingTwo"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                        android:padding="5dp">

                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:text="@string/my_text"
                            android:textAppearance="?android:textAppearanceMedium"
                            android:textColor="@android:color/black" />

                    </LinearLayout>

                </LinearLayout>

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

        </LinearLayout>

    </ScrollView>

</LinearLayout>
MainActivity.java

package com.androidsimplifycodes.example;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    protected Context context;
    protected LinearLayout llExpandableHeadingOneClick;
    protected LinearLayout llExpandableHeadingOne;
    protected LinearLayout llExpandableHeadingTwoClick;
    protected LinearLayout llExpandableHeadingTwo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        super.setContentView(R.layout.activity_main);

        context = MainActivity.this;
        initView();

        Util.collapseView(llExpandableHeadingOne);
        Util.collapseView(llExpandableHeadingTwo);

        llExpandableHeadingOneClick.setTag("Expand");
        llExpandableHeadingTwoClick.setTag("Expand");

        llExpandableHeadingOneClick.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (view.getTag().toString().equals("Expand")) {
                    Util.expandView(llExpandableHeadingOne);
                    llExpandableHeadingOneClick.setTag("Collapse");
                } else {
                    Util.collapseView(llExpandableHeadingOne);
                    llExpandableHeadingOneClick.setTag("Expand");
                }
            }
        });

        llExpandableHeadingTwoClick.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (view.getTag().toString().equals("Expand")) {
                    Util.expandView(llExpandableHeadingTwo);
                    llExpandableHeadingTwoClick.setTag("Collapse");
                } else {
                    Util.collapseView(llExpandableHeadingTwo);
                    llExpandableHeadingTwoClick.setTag("Expand");
                }
            }
        });
    }

    private void initView() {
        llExpandableHeadingOneClick = (LinearLayout) findViewById(R.id.llExpandableHeadingOneClick);
        llExpandableHeadingOne = (LinearLayout) findViewById(R.id.llExpandableHeadingOne);
        llExpandableHeadingTwoClick = (LinearLayout) findViewById(R.id.llExpandableHeadingTwoClick);
        llExpandableHeadingTwo = (LinearLayout) findViewById(R.id.llExpandableHeadingTwo);
    }
}
    These two function uses for the layout expand and collapse for, expand and Collapse create animation class instance and using interpolated Time multiplied with target height getting new integer value and this value assign for the view expand and collapse.
Util.java

package com.androidsimplifycodes.example;

import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Transformation;

/**
 * Created by Kishan Donga on 2/22/2017.
 */

public class Util {

    public static void expandView(final View v) {
        v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        final int targetHeight = v.getMeasuredHeight();

        v.getLayoutParams().height = 1;
        v.setVisibility(View.VISIBLE);
        Animation a = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                v.getLayoutParams().height = interpolatedTime == 1
                        ? ViewGroup.LayoutParams.WRAP_CONTENT
                        : (int) (targetHeight * interpolatedTime);
                v.requestLayout();
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        a.setDuration((int) (targetHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }

    public static void collapseView(final View v) {
        final int initialHeight = v.getMeasuredHeight();

        Animation a = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                if (interpolatedTime == 1) {
                    v.setVisibility(View.GONE);
                } else {
                    v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
                    v.requestLayout();
                }
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        a.setDuration((int) (initialHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }
}
Output :