Search code examples
javaandroidandroid-layoutexpand

Expand and collapse Relativelayout by button click


I have this RelativeLayout which expand and collapse on button click it works fine on one button. I want to reuse same method on more two RelativeLayout in same layout and expand using other two buttons.

This code is running fine. just want more layout to do same action.

Layout: enter image description here

This is my code:

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

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

        <RelativeLayout

            android:layout_width="fill_parent"
            android:layout_height="64dp"
            android:background="#FFF"
            android:orientation="vertical">

            <TextView

                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Title"
                android:textSize="20sp" />

            <Button
                android:id="@+id/viewmore"
                android:layout_width="80dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="280dp"
                android:background="@null"
                android:text="viewmore" />


        </RelativeLayout>


        <RelativeLayout

            android:visibility="gone"
            android:id="@+id/expandable"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:animateLayoutChanges="true"
            android:background="@color/colorAccent"
            android:orientation="vertical">


            <TextView

                android:layout_width="match_parent"
                android:layout_height="133dp"
                android:text="Text messaging, or texting, is the act of composing and sending electronic messages, typically consisting of alphabetic and numeric characters"
                android:textSize="20sp" />


        </RelativeLayout>


        <RelativeLayout


            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/textView4"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Title 2"
                android:textSize="20sp" />

            <Button
                android:id="@+id/viewmore1"
                android:layout_width="80dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="280dp"
                android:background="@null"
                android:text="viewmore" />


        </RelativeLayout>

        <RelativeLayout
            android:visibility="gone"
            android:animateLayoutChanges="true"
            android:id="@+id/expandable1"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:layout_marginTop="30dp"
            android:background="@color/colorPrimary">

            <TextView

                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Text messaging, or texting, is the act of composing and sending electronic messages, typically consisting of alphabetic and numeric characters"
                android:textSize="20sp" />


        </RelativeLayout>

        <RelativeLayout

            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView

                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Title 3"
                android:textSize="20sp" />

            <Button
                android:id="@+id/viewmore2"
                android:layout_width="80dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="280dp"
                android:background="@null"
                android:text="viewmore" />


        </RelativeLayout>

        <RelativeLayout
            android:visibility="gone"
            android:animateLayoutChanges="true"
            android:id="@+id/expandable2"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:layout_marginTop="30dp"
            android:background="@color/colorPrimary">

            <TextView

                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Text messaging, or texting, is the act of composing and sending electronic messages, typically consisting of alphabetic and numeric characters"
                android:textSize="20sp" />


        </RelativeLayout>


    </LinearLayout>
</ScrollView>

Source Code:

RelativeLayout relativeLayout, relativeLayout1, relativeLayout2;
    Button viewmore, viewmore1, viewmore2;
    ValueAnimator mAnimator;

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


        relativeLayout = (RelativeLayout) findViewById(R.id.expandable);
        relativeLayout1 = (RelativeLayout) findViewById(R.id.expandable1);
        relativeLayout2 = (RelativeLayout) findViewById(R.id.expandable2);


        viewmore = (Button) findViewById(R.id.viewmore);
        viewmore1 = (Button) findViewById(R.id.viewmore1);
        viewmore2 = (Button) findViewById(R.id.viewmore2);

        viewmore.setOnClickListener(this);
        viewmore1.setOnClickListener(this);
        viewmore2.setOnClickListener(this);


        relativeLayout.getViewTreeObserver().addOnPreDrawListener(
                new ViewTreeObserver.OnPreDrawListener() {

                    @Override
                    public boolean onPreDraw() {
                        relativeLayout.getViewTreeObserver().removeOnPreDrawListener(this);
                        relativeLayout.setVisibility(View.GONE);

                        final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
                        final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
                        relativeLayout.measure(widthSpec, heightSpec);

                        mAnimator = slideAnimator(0, relativeLayout.getMeasuredHeight());
                        return true;
                    }
                });


    }


    private void expand() {

        relativeLayout.setVisibility(View.VISIBLE);
        mAnimator.start();
    }

    private void collapse() {
        int finalHeight = relativeLayout.getHeight();

        ValueAnimator mAnimator = slideAnimator(finalHeight, 0);

        mAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationEnd(Animator animator) {
                //Height=0, but it set visibility to GONE
                relativeLayout.setVisibility(View.GONE);
            }

            @Override
            public void onAnimationStart(Animator animator) {
            }

            @Override
            public void onAnimationCancel(Animator animator) {
            }

            @Override
            public void onAnimationRepeat(Animator animator) {
            }
        });
        mAnimator.start();
    }


    private ValueAnimator slideAnimator(int start, int end) {

        ValueAnimator animator = ValueAnimator.ofInt(start, end);


        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                //Update Height
                int value = (Integer) valueAnimator.getAnimatedValue();

                ViewGroup.LayoutParams layoutParams = relativeLayout.getLayoutParams();
                layoutParams.height = value;
                relativeLayout.setLayoutParams(layoutParams);
            }
        });
        return animator;
    }


    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.viewmore:

                if (relativeLayout.getVisibility() == View.GONE) {
                    expand();
                } else {
                    collapse();
                }

                break;


            case R.id.viewmore1:


                break;

            case R.id.viewmore2:


                break;


        }
    }

Solution

  • To continue with your approach, you will have to make the code apply to all three sections that you have laid out. To do this, you will need to change several of your methods to accept a RelativeLayout as an argument.

    First, in your onClick listener, fill in the case blocks so each block calls expand() with the targeted RelativeLayout and maximum height. Call collapse() with the targeted RelativeLayout. You will then need to modify expand() and collapse() to handle the new arguments:

    You will notice in the following code that I have changed how and where the animator is created. The animator will need to work with each RelativeLayout.

    So, onClick() calls expand() which calls slideAnimator(). For each call, the RelativeLayout that is effected is passed as an argument. In this way, you can generalize the code to work with more than one RelativeLayout.

    The pre-draw listener will also need to measure each expandable RelativeLayout.

    Here is it all put together:

    MainActivity.xml

    public class MainActivity extends AppCompatActivity
        implements View.OnClickListener {
    
        RelativeLayout relativeLayout, relativeLayout1, relativeLayout2;
        Button viewmore, viewmore1, viewmore2;
        int height, height1, height2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.viewmore);
    
            relativeLayout = (RelativeLayout) findViewById(R.id.expandable);
            relativeLayout1 = (RelativeLayout) findViewById(R.id.expandable1);
            relativeLayout2 = (RelativeLayout) findViewById(R.id.expandable2);
    
            viewmore = (Button) findViewById(R.id.viewmore);
            viewmore1 = (Button) findViewById(R.id.viewmore1);
            viewmore2 = (Button) findViewById(R.id.viewmore2);
    
            viewmore.setOnClickListener(this);
            viewmore1.setOnClickListener(this);
            viewmore2.setOnClickListener(this);
    
    
            relativeLayout.getViewTreeObserver().addOnPreDrawListener(
                new ViewTreeObserver.OnPreDrawListener() {
    
                    @Override
                    public boolean onPreDraw() {
                        relativeLayout.getViewTreeObserver().removeOnPreDrawListener(this);
                        relativeLayout.setVisibility(View.GONE);
                        relativeLayout1.setVisibility(View.GONE);
                        relativeLayout2.setVisibility(View.GONE);
    
                        final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
                        final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
                        relativeLayout.measure(widthSpec, heightSpec);
                        height = relativeLayout.getMeasuredHeight();
                        relativeLayout1.measure(widthSpec, heightSpec);
                        height1 = relativeLayout.getMeasuredHeight();
                        relativeLayout2.measure(widthSpec, heightSpec);
                        height2 = relativeLayout.getMeasuredHeight();
                        return true;
                    }
                });
        }
    
    
        private void expand(RelativeLayout layout, int layoutHeight) {
            layout.setVisibility(View.VISIBLE);
            ValueAnimator animator = slideAnimator(layout, 0, layoutHeight);
            animator.start();
        }
    
        private void collapse(final RelativeLayout layout) {
            int finalHeight = layout.getHeight();
            ValueAnimator mAnimator = slideAnimator(layout, finalHeight, 0);
    
            mAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationEnd(Animator animator) {
                    //Height=0, but it set visibility to GONE
                    layout.setVisibility(View.GONE);
                }
    
                @Override
                public void onAnimationStart(Animator animator) {
                }
    
                @Override
                public void onAnimationCancel(Animator animator) {
                }
    
                @Override
                public void onAnimationRepeat(Animator animator) {
                }
            });
            mAnimator.start();
        }
    
    
        private ValueAnimator slideAnimator(final RelativeLayout layout, int start, int end) {
            ValueAnimator animator = ValueAnimator.ofInt(start, end);
    
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    //Update Height
                    int value = (Integer) valueAnimator.getAnimatedValue();
    
                    ViewGroup.LayoutParams layoutParams = layout.getLayoutParams();
                    layoutParams.height = value;
                    layout.setLayoutParams(layoutParams);
                }
            });
            return animator;
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.viewmore:
                    if (relativeLayout.getVisibility() == View.GONE) {
                        expand(relativeLayout, height);
                    } else {
                        collapse(relativeLayout);
                    }
                    break;
    
                case R.id.viewmore1:
                    if (relativeLayout1.getVisibility() == View.GONE) {
                        expand(relativeLayout1, height1);
                    } else {
                        collapse(relativeLayout1);
                    }
                    break;
    
                case R.id.viewmore2:
                    if (relativeLayout2.getVisibility() == View.GONE) {
                        expand(relativeLayout2, height2);
                    } else {
                        collapse(relativeLayout2);
                    }
                    break;
            }
        }
    }