21

我在线性布局中有两个视图,我以编程方式更改了它们的 layout_weight 属性。有没有一种方法可以为这种重量变化设置动画,所以当重量改变时,视图会滑向新的尺寸?

4

5 回答 5

34

您可以简单地使用 ObjectAnimator。

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

一个问题是 View 类没有 setWeight() 方法(ObjectAnimator 需要它)。为了解决这个问题,我编写了简单的包装器来帮助归档视图权重动画。

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;
    }
}

以这种方式使用它:

    ViewWeightAnimationWrapper animationWrapper = new ViewWeightAnimationWrapper(view);
    ObjectAnimator anim = ObjectAnimator.ofFloat(animationWrapper,
                    "weight",
                    animationWrapper.getWeight(),
                    weight);
            anim.setDuration(2500);
            anim.start();
于 2015-12-04T13:59:18.833 回答
4

我也一直在看这个。最终我通过动画父的 weightsum 属性解决了这个问题,如果你在 LinearLayout 中有两个视图,它会非常有用。

请参阅: 使用 ObjectAnimator 为 weightSum 属性设置动画

在下面的示例中,如果您将 weightSum 从 1.0 设置为 2.0,Screen 2 将很好地显示在视图中。

<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>
于 2012-07-25T16:28:38.450 回答
4

注意:我不确定这是最好的方法,但我试过了,效果很好

只需使用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();

更多关于ValueAnimator

于 2017-10-27T17:36:44.267 回答
0

上面的所有答案都对我不起作用(它们只会“捕捉”而不是动画),但是在我将 weight_sum="1" 添加到父布局之后,它开始起作用了。以防万一其他人提出同样的问题。

于 2018-11-02T11:11:30.917 回答
0

另一种方法是使用旧Animation类,如https://stackoverflow.com/a/20334557/2914140中所述。在这种情况下,您可以同时更改多个视图的权重。

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;
    }
}
于 2017-10-03T18:50:26.860 回答