Anyway to programmatically animate layout weight property of linear layout

前端 未结 5 1755
暗喜
暗喜 2021-02-18 15:12

I have two views in a linear layout, I programmatically change their layout_weight property. Is there a way I could animate this change in weight so when the weight is changed v

相关标签:
5条回答
  • 2021-02-18 15:44

    All of the answers above weren't working for me (they would simply "snap" and not animate), but after I added weight_sum="1" to the parent layout, it started working. Just in case someone else comes up with the same issue.

    0 讨论(0)
  • 2021-02-18 15:47

    Another way is to use old Animation class, as described in https://stackoverflow.com/a/20334557/2914140. In this case you can simultaneously change weights of several Views.

    private static class ExpandAnimation extends Animation {
        private final View[] views;
        private final float startWeight;
        private final float deltaWeight;
    
        ExpandAnimation(View[] views, float startWeight, float endWeight) {
            this.views = views;
            this.startWeight = startWeight;
            this.deltaWeight = endWeight - startWeight;
        }
    
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            float weight = startWeight + (deltaWeight * interpolatedTime);
            for (View view : views) {
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) view.getLayoutParams();
                lp.weight = weight;
                view.setLayoutParams(lp);
            }
            views[0].getParent().requestLayout();
        }
    
        @Override
        public boolean willChangeBounds() {
            return true;
        }
    }
    
    0 讨论(0)
  • 2021-02-18 15:52

    Note: I am not sure that this is the best way, but I tried it and it's working fine

    Simply using ValueAnimator

    ValueAnimator m1 = ValueAnimator.ofFloat(0.2f, 0.5f); //fromWeight, toWeight
    m1.setDuration(400);
    m1.setStartDelay(100); //Optional Delay
    m1.setInterpolator(new LinearInterpolator());
    m1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
                 ((LinearLayout.LayoutParams) viewToAnimate.getLayoutParams()).weight = (float) animation.getAnimatedValue();
                 viewToAnimate.requestLayout();
             }
    
    });
    m1.start();
    

    More About ValueAnimator

    0 讨论(0)
  • 2021-02-18 15:56

    I have been looking at this as well. Eventually I solved it by animating the weightsum property of the parent, which works very nice if you have two views in a LinearLayout.

    see: Animating weightSum property using ObjectAnimator

    In the example below, if you animate the weightSum from 1.0 to 2.0, Screen 2 will animate nicely into view.

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/dual_pane"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal"
        android:weightSum="1.0">
    
    <!-- Screen 1 -->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:background="#ff0000"
        android:layout_weight="1">
    </LinearLayout>
    
    <!-- Screen 2 -->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:background="#ff6600"
        android:layout_weight="1">
    </LinearLayout>
    </LinearLayout>
    
    0 讨论(0)
  • 2021-02-18 16:00

    You can simply use ObjectAnimator.

    ObjectAnimator anim = ObjectAnimator.ofFloat(
                    viewToAnimate,
                    "weight",
                    startValue,
                    endValue);
            anim.setDuration(2500);
            anim.start();
    

    The one problem is that View class has no setWeight() method (which is required by ObjectAnimator). To address this I wrote simple wrapper which helps archive view weight animation.

    public class ViewWeightAnimationWrapper {
        private View view;
    
        public ViewWeightAnimationWrapper(View view) {
            if (view.getLayoutParams() instanceof LinearLayout.LayoutParams) {
                this.view = view;
            } else {
                throw new IllegalArgumentException("The view should have LinearLayout as parent");
            }
        }
    
        public void setWeight(float weight) {
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
            params.weight = weight;
            view.getParent().requestLayout();
        }
    
        public float getWeight() {
            return ((LinearLayout.LayoutParams) view.getLayoutParams()).weight;
        }
    }
    

    Use it in this way:

        ViewWeightAnimationWrapper animationWrapper = new ViewWeightAnimationWrapper(view);
        ObjectAnimator anim = ObjectAnimator.ofFloat(animationWrapper,
                        "weight",
                        animationWrapper.getWeight(),
                        weight);
                anim.setDuration(2500);
                anim.start();
    
    0 讨论(0)
提交回复
热议问题