Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListView expand animation for items only works after second click

I have a CardView with the following views:

- RelativeLayout (view_1)
    - TextView
    - TextView

- RelativeLayout (view_2)
    - ImageView
    - ImageView

When i open my ListView view_2 is set to Visible.GONE so you cant see it. Now i used the ExpandAnimation from this blog. Here you have the code:

/**
 *
 */
public class ExpandAnimation extends Animation {
    /**
     *
     */
    private AnimationCallback callback = null;
    /**
     *
     */
    private View viewToAnimate = null;
    /**
     *
     */
    private RelativeLayout.LayoutParams viewToAnimateLayoutParams = null;
    /**
     *
     */
    private int marginStart = 0;
    /**
     *
     */
    private int marginEnd = 0;
    /**
     *
     */
    private boolean isVisibleAfter = false;
    /**
     *
     */
    private boolean isEndedAlready = false;

    /**
     *
     * @param callback
     * @param view
     * @param duration
     */
    public ExpandAnimation(AnimationCallback callback, View view, int duration) {
        this.setDuration(duration);

        this.callback = callback;

        this.viewToAnimate = view;
        this.viewToAnimateLayoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();

        this.isVisibleAfter = (view.getVisibility() == View.VISIBLE);

        this.marginStart = this.viewToAnimateLayoutParams.bottomMargin;
        this.marginEnd = (this.marginStart == 0 ? (0 - view.getHeight()) : 0);

        view.setVisibility(View.VISIBLE);
    }

    /**
     *
     * @param interpolatedTime
     * @param transformation
     */
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation transformation) {
        super.applyTransformation(interpolatedTime, transformation);

        if (interpolatedTime < 1.0f) {
            this.viewToAnimateLayoutParams.bottomMargin = this.marginStart + (int) ((this.marginEnd - this.marginStart) * interpolatedTime);
            this.viewToAnimate.requestLayout();
        } else if (!this.isEndedAlready) {
            this.viewToAnimateLayoutParams.bottomMargin = this.marginEnd;
            this.viewToAnimate.requestLayout();

            if (this.isVisibleAfter) {
                this.viewToAnimate.setVisibility(View.GONE);
            }

            this.isEndedAlready = true;

            this.callback.onAnimationCompleted(-1);
        }
    }
}

I use it inside my AdapterView:

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, AnimationCallback {
    private TextView textViewValue = null;
    private TextView textViewTime = null;
    private RelativeLayout relativeLayoutExpand = null;
    private ImageView imageViewMood = null;
    private ImageView imageViewMeal = null;

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

        this.textViewValue = (TextView) itemView.findViewById(R.id.textview_value);
        this.textViewTime = (TextView) itemView.findViewById(R.id.textview_time);
        this.relativeLayoutExpand = (RelativeLayout) itemView.findViewById(R.id.list_row_expand);
        this.imageViewMood = (ImageView) itemView.findViewById(R.id.imageview_mood);
        this.imageViewMeal = (ImageView) itemView.findViewById(R.id.imageview_meal);

        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        this.animate(this.relativeLayoutExpand);
    }

    public void animate(final View view) {
        ExpandAnimation expand = new ExpandAnimation(this, view, 500);

        view.startAnimation(expand);
    }

    public void onAnimationCompleted(int position) {
    }
}

I only have one problem now: When i expand an item inside my list the first time it appears instantly without animation and after it the closing and opening works smoothly with animation.

Does someone know why the first opening happens without animation but every click after that is triggering the correct animation?

I also need the animation for the first click.

EDIT

Is it because initially my views visibility is GONE and so the height is unknown? If yes: How could i solve this?

EDIT 2

No, my XML layout file does not set the view to GONE:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_marginBottom="10dp">

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

        <RelativeLayout
            android:id="@+id/datatransfer_measure_list_row_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingEnd="10dp"
            android:paddingStart="10dp"
            android:paddingTop="10dp">

            <TextView
                android:id="@+id/datatransfer_measure_list_row_textview_value"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentStart="true"
                android:lines="1"
                android:maxLines="1"
                android:singleLine="true"
                android:text="@string/text_value"
                android:textColor="@color/textcolorprimary"
                android:textSize="30sp" />

            <TextView
                android:id="@+id/datatransfer_measure_list_row_textview_time"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/datatransfer_measure_list_row_textview_value"
                android:layout_gravity="center"
                android:layout_marginBottom="10dp"
                android:gravity="start"
                android:lines="1"
                android:maxLines="1"
                android:singleLine="true"
                android:textColor="@color/textcolorprimary"
                android:textSize="14sp" />

            <ImageView
                android:id="@+id/datatransfer_measure_list_row_imageview_expand"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_alignParentTop="true"
                android:contentDescription="@string/text_description"
                android:scaleType="fitCenter"
                android:src="@drawable/ic_expand_more_black_24dp" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/datatransfer_measure_list_row_expand"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/datatransfer_measure_list_row_data"
            android:background="@color/primaryColor"
            android:paddingBottom="10dp"
            android:paddingEnd="10dp"
            android:paddingStart="10dp"
            android:paddingTop="10dp">

            <RelativeLayout
                android:id="@+id/datatransfer_measure_list_row_mood"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_alignParentStart="true"
                    android:layout_centerVertical="true"
                    android:lines="1"
                    android:maxLines="1"
                    android:singleLine="true"
                    android:text="@string/text_mood"
                    android:textColor="@color/textcolorsecundary"
                    android:textSize="30sp" />

                <ImageView
                    android:id="@+id/datatransfer_measure_list_row_imageview_mood"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentEnd="true"
                    android:contentDescription="@string/text_description"
                    android:scaleType="fitCenter" />
            </RelativeLayout>

            <ImageView
                android:id="@+id/datatransfer_measure_list_row_imageview_meal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/datatransfer_measure_list_row_mood"
                android:layout_centerInParent="true"
                android:contentDescription="@string/text_description" />

        </RelativeLayout>

    </RelativeLayout>

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

I set the View.GONE in my ListAdapter:

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

    viewHolder.textViewTime.setText(time);
    viewHolder.textViewValue.setText(value + " " + unitValue);
    viewHolder.relativeLayoutExpand.setVisibility(View.GONE); // <-- HERE

    ...
}

Edit 3

Maybe it is important to know that the container of my cardviews is a recyclerview:

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

    <TextView
        android:id="@+id/datatransfer_measure_list_textview_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:background="@color/primaryColorDark"
        android:gravity="center"
        android:padding="10dp"
        android:textColor="@color/white"
        android:textSize="18dp" />

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/datatransfer_measure_list_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/datatransfer_measure_list_textview_name">

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/datatransfer_measure_list_swipe_refresh_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/datatransfer_measure_list_row_parent"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clipToPadding="false"
                android:padding="10dp"
                android:textColor="@color/textcolorprimary" />
        </android.support.v4.widget.SwipeRefreshLayout>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/datatransfer_measure_list_floating_action_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:layout_marginEnd="16dp"
            android:clickable="true"
            android:src="@drawable/ic_search_white_24dp"
            app:backgroundTint="@color/primaryColorDark"
            app:borderWidth="0dp"
            app:elevation="6dp"
            app:layout_anchor="@id/datatransfer_measure_list_row_parent"
            app:layout_anchorGravity="bottom|right|end"
            app:layout_behavior="de.hof.ime_dc.idia_move.views.buttons.ScrollFABBehaviour"
            app:rippleColor="@color/accentColor" />

    </android.support.design.widget.CoordinatorLayout>
</RelativeLayout>

I really need a solution for that. It is disturbing many of needed functionality.

Edit 4

I added some Log-Outputs:

=============================== EXPAND =========================================

08-02 12:27:22.471   V/ExpandAnimation﹕ View is visible: 8 (GONE)
08-02 12:27:22.471   V/ExpandAnimation﹕ marginStart: 0
08-02 12:27:22.471   V/ExpandAnimation﹕ marginEnd: 0
08-02 12:27:22.472   V/ExpandAnimation﹕ View is visible: 0 (VISIBLE)

============================== COLLAPSE ========================================

08-02 12:27:51.015   V/ExpandAnimation﹕ View is visible: 0 (VISIBLE)
08-02 12:27:51.015   V/ExpandAnimation﹕ marginStart: 0
08-02 12:27:51.015   V/ExpandAnimation﹕ marginEnd: -156
08-02 12:27:51.015   V/ExpandAnimation﹕ View is visible: 8 (GONE)

=============================== EXPAND =========================================

08-02 12:27:56.007   V/ExpandAnimation﹕ View is visible: 8 (GONE)
08-02 12:27:56.007   V/ExpandAnimation﹕ marginStart: -156
08-02 12:27:56.007   V/ExpandAnimation﹕ marginEnd: 0
08-02 12:27:56.008   V/ExpandAnimation﹕ View is visible: 0 (VISIBLE)

============================== COLLAPSE ========================================

08-02 12:27:51.015   V/ExpandAnimation﹕ View is visible: 0 (VISIBLE)
08-02 12:27:51.015   V/ExpandAnimation﹕ marginStart: 0
08-02 12:27:51.015   V/ExpandAnimation﹕ marginEnd: -156
08-02 12:27:51.015   V/ExpandAnimation﹕ View is visible: 8 (GONE)

=============================== EXPAND =========================================

08-02 12:27:56.007   V/ExpandAnimation﹕ View is visible: 8 (GONE)
08-02 12:27:56.007   V/ExpandAnimation﹕ marginStart: -156
08-02 12:27:56.007   V/ExpandAnimation﹕ marginEnd: 0
08-02 12:27:56.008   V/ExpandAnimation﹕ View is visible: 0 (VISIBLE)

As you can see the first marginStart of the expand is 0 but it has to be -156.

like image 657
Mulgard Avatar asked Jul 27 '15 08:07

Mulgard


1 Answers

You did not show your XML but I assume you got android:visibility="gone" there. If so, you should remove it from layout file (so it is visible by default). if it should be gone, call setVisibility(View.GONE) on it after inflation. That way you will get the same result but view would also be able to get its dimensions.

like image 115
Marcin Orlowski Avatar answered Sep 21 '22 23:09

Marcin Orlowski