Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animation not smooth

I have made a app in which on button click i have slided a linear layout.The code to slide the linear layout is working fine but the problem is that it lags when sliding.Also the height which i have set to slide the layout doesnt look proper on all screen sizes(Specially on Nexus 5).Please do help me out

XMl

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


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

        <ImageView
            android:id="@+id/iv_upload_add"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:src="@drawable/add" />


        <LinearLayout
            android:id="@+id/ll_upload_options"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="@drawable/choosefile_bg"
            android:gravity="center"
            android:orientation="vertical">

            <pocketdocs.indiehustlers.com.pocketdocsv2.Utils.TextViewGeneral
                android:id="@+id/tv_upload_gallery"
                style="@style/text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:padding="5dp"
                android:text="GALLERY"
                android:textSize="20sp"
                android:visibility="visible" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="1dp"
                android:layout_marginLeft="30dp"
                android:layout_marginRight="30dp"

                android:background="@drawable/line" />

            <pocketdocs.indiehustlers.com.pocketdocsv2.Utils.TextViewGeneral
                android:id="@+id/tv_upload_camera"
                style="@style/text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="bottom"
                android:padding="5dp"
                android:text="CAMERA"
                android:textSize="20sp"
                android:visibility="visible" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="1dp"
                android:layout_marginLeft="30dp"
                android:layout_marginRight="30dp"

                android:background="@drawable/line" />

            <pocketdocs.indiehustlers.com.pocketdocsv2.Utils.TextViewGeneral
                android:id="@+id/tv_upload_file"
                style="@style/text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="bottom"
                android:padding="5dp"
                android:text="FILE"
                android:textSize="20sp"
                android:visibility="visible" />


        </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_gravity="center"
        android:layout_marginLeft="@dimen/all_left_mar"
        android:layout_marginRight="@dimen/all_right_mar"
        android:layout_weight="2"
        android:gravity="center"
        android:orientation="vertical">

        <pocketdocs.indiehustlers.com.pocketdocsv2.Utils.EditTextFont
            style="@style/edit_text"
            android:drawableBottom="@drawable/line_black"
            android:hint="File Title"
            android:textColor="#000"
            android:textColorHint="#000" />

        <AutoCompleteTextView
            style="@style/edit_text"
            android:layout_marginTop="10dp"
            android:completionThreshold="1"
            android:drawableBottom="@drawable/line_black"
            android:hint="Type"
            android:textColor="#000"
            android:textColorHint="#000" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">

            <Switch
                android:id="@+id/switch1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:checked="false"
                android:textOff="No"
                android:textOn="Yes" />

            <pocketdocs.indiehustlers.com.pocketdocsv2.Utils.TextViewGeneral
                style="@style/text_view"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:text="@string/Protect"
                android:textColor="#000" />

        </LinearLayout>

        <pocketdocs.indiehustlers.com.pocketdocsv2.Utils.EditTextFont
            style="@style/edit_text"
            android:layout_marginTop="10dp"
            android:drawableBottom="@drawable/line_black"
            android:hint="Password"
            android:inputType="numberPassword"
            android:textColor="#000"
            android:textColorHint="#000" />


    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginLeft="@dimen/all_left_mar"
        android:layout_marginRight="@dimen/all_right_mar"
        android:layout_weight="1">

        <pocketdocs.indiehustlers.com.pocketdocsv2.Utils.ButtonFont
            style="@style/button"
            android:text="UPLOAD" />
    </LinearLayout>

</LinearLayout>

Code

if (llUploadOptions.getMeasuredHeight() != 0) {

//                    tvGallery.setVisibility(View.GONE);
//                    tvCamera.setVisibility(View.GONE);
//                    tvFile.setVisibility(View.GONE);

                    ValueAnimator anim = ValueAnimator.ofInt(llUploadOptions.getMeasuredHeight(),200);
                    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
                            int val = (Integer) valueAnimator.getAnimatedValue();
                            ViewGroup.LayoutParams layoutParams = llUploadOptions.getLayoutParams();
                            layoutParams.height = val;
                            llUploadOptions.setLayoutParams(layoutParams);
                        }
                    });
                    anim.setDuration(700);
                    anim.start();
                } else {
                    ValueAnimator anim = ValueAnimator.ofInt(llUploadOptions.getMeasuredHeight(),250);
                    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
                            int val = (Integer) valueAnimator.getAnimatedValue();
                            ViewGroup.LayoutParams layoutParams = llUploadOptions.getLayoutParams();
                            layoutParams.height = val;
                            llUploadOptions.setLayoutParams(layoutParams);
                        }
                    });
                    anim.setDuration(700);
                    anim.start();

                }
like image 991
Anuj Avatar asked Dec 18 '14 08:12

Anuj


2 Answers

The problem is, that you are trying to animate the height of your Layout. That means, that with every animation step you call setLayoutParams() which forces your whole layout (incl. children) to be relayouted by going through the complete view hierarchy and this leads to laggy animation. Layouting things is an expensive operation!

There are some "workarounds" (I'm not sure what you want to do):

  1. Since Android 4.0 you simply can use animate layout changes in your xml if you simply want to show / hide a element with animations in your layout
  2. For more complex things you may consider to use Transitions framework introduced in Kitkat (Api 19) https://www.youtube.com/watch?v=S3H7nJ4QaD8. Backports: https://github.com/guerwan/TransitionsBackport or https://github.com/andkulikov/transitions-everywhere
  3. "Fake" the animation by animating views by hand with translation, alpha etc. and set the LayoutParameters only once after the animation has been finished
  4. I can't remember how the api is called, but you can subclass from ViewGroup and use it as your root layout. You have to intercept layout changes while animating the height somehow to get a smooth animation (this is how animateLayoutChanges = true works). However thats an advanced topic an I would recommend to go one of the other ways
like image 71
sockeqwe Avatar answered Oct 20 '22 11:10

sockeqwe


you are using Animators (not Animations), which might be laggy, especially with moving widgets. try TranslateAnimation

TranslateAnimation animation = new TranslateAnimation(0.0f, 200.0f,
        0.0f, 0.0f);          
//  these are delta's, check doc for this constructor
//  TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
animation.setDuration(700);     

llUploadOptions.startAnimation(animation);

if you want to leave your animated view with final coordinates use

animation.setFillAfter(true);

but it might not be clickable or other issues might occur. for these you might use

animation.setAnimationListener(new AnimationListener() {
                public void onAnimationStart(Animation anim)
                {
                };
                public void onAnimationRepeat(Animation anim)
                {
                };
                public void onAnimationEnd(Animation anim)
                {
                    //set fixed position in here, using LayoutParams or setTop/setRight etc. methods of View (API 11)
                };
            });

edit:

so instead of ValueAnimator you might do smth like this

int desiredHeightInPx = getResources().getDimensionPixelSize(R.dimen.expandedHeight);
//note those are pixels, not dp. you might set this as =200 or =250 like you have

ScaleAnimation animation = new ScaleAnimation(0, 0, 0, desiredHeightInPx/llUploadOptions.getMeasuredHeight(), Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f);
animation.setDuration(1000); //ms
llUploadOptions.startAnimation(animation);

next steps as above, fillAfter or set AnimationListener and inside onAnimationEnd set final LayoutParams.

be aware that ScaleAnimation is scaling, it might be more appropiate to use RelativeLayout instead of Linear (which rescales its childers)

like image 42
snachmsm Avatar answered Oct 20 '22 11:10

snachmsm