使用ValueAnimator在LinearLayout权重上同时运行动画

Ken*_*and 4 android android-animation android-linearlayout

我已经尝试了很多不同的方法,但没有一种方法可行.我愿意接受建议.

我正在制作一个自定义的"按钮".它不是类型,Button但会表现为多状态按钮.每个按钮有3个不同颜色的字形,代表不同的状态(蓝色,白色和橙色).无论哪个字形处于主要状态都比其他字形大得多,如下所示:

在此输入图像描述 在此输入图像描述 在此输入图像描述

目前,每个"按钮"是一个带有3个ImageView的LinearLayout,每个ImageView由一个权重为0.2 + 0.6 + 0.2 = 1.0的PathShape绘制.那部分工作正常.0.6是主要的状态权重.

我在屏幕上有一个简单的按钮来触发动画.动画将当前的主要从0.6重量减少到0.2重量,新的主要从0.2减少到0.6.一个缩小,另一个增长.

问题:动画不会同时运行,即使我明确告诉他们同时运行.第一个从0.6缩小到0.2,然后稍微暂停,然后第二个从0.2增加到0.6.

Button button = (Button)this.findViewById(R.id.shift);
button.setOnClickListener(new View.OnClickListener() {

    public Animator makeWeightAnimator(final View v, float startingWeight, float endingWeight) {
        long duration = 2000;

        ValueAnimator va = ValueAnimator.ofFloat(startingWeight, endingWeight);
        va.setDuration(duration);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                Float value = (Float) animation.getAnimatedValue();
                LinearLayout.LayoutParams paramsanim = (LinearLayout.LayoutParams)v.getLayoutParams();
                paramsanim.weight = value.floatValue();
                v.requestLayout();
            }
        });

        return va;
    }

    @Override
    public void onClick(View v) {

        float newBlueWeight = 0.2f;
        float newWhiteWeight = 0.2f;
        float newOrangeWeight = 0.2f;

        if (state == 0) {
            // Make blue larger
            newBlueWeight = 0.6f;
        } else if (state == 1) {
            // Make white larger
            newWhiteWeight = 0.6f;
        } else {
            // Make orange larger
            newOrangeWeight = 0.6f;
        }
        // Total will be 0.2 + 0.6 + 0.2 = 1.0

        List<Animator> animators = new LinkedList<Animator>();

        LinearLayout.LayoutParams blueParams = (LinearLayout.LayoutParams)blueImage.getLayoutParams();
        Log.d("TA", String.format("blue %f -> %f", blueParams.weight, newBlueWeight));
        if (Math.abs(blueParams.weight - newBlueWeight) > 0.001) {
            // new weight is different from existing weight
            Animator va = makeWeightAnimator(blueImage, blueParams.weight, newBlueWeight);
            animators.add(va);
        }

        LinearLayout.LayoutParams whiteParams = (LinearLayout.LayoutParams)whiteImage.getLayoutParams();
        Log.d("TA", String.format("white %f -> %f", whiteParams.weight, newWhiteWeight));
        if (Math.abs(whiteParams.weight - newWhiteWeight) > 0.001) {
            // new weight is different from existing weight
            Animator va = makeWeightAnimator(whiteImage, whiteParams.weight, newWhiteWeight);
            animators.add(va);
        }

        LinearLayout.LayoutParams orangeParams = (LinearLayout.LayoutParams)orangeImage.getLayoutParams();
        Log.d("TA", String.format("orange %f -> %f", orangeParams.weight, newOrangeWeight));
        if (Math.abs(orangeParams.weight - newOrangeWeight) > 0.001) {
            // new weight is different from existing weight
            Animator va = makeWeightAnimator(orangeImage, orangeParams.weight, newOrangeWeight);
            animators.add(va);
        }

        if (animators.size() > 0) {
            AnimatorSet s = new AnimatorSet();
            s.playTogether(animators);
            s.start();
        }

        state++;

        if (state > 2) {
            state = 0;
        }

    }
});
Run Code Online (Sandbox Code Playgroud)

这是我制作的视频,显示了顺序运行而不是并行运行的动画:

http://inadaydevelopment.com/stackoverflow/AndroidLinearLayoutAnimation.html

我甚至尝试将所有更改组合到一个动画师中,而不是尝试让多个动画师并行运行,但动画仍然按顺序发生.我觉得我在失去理智:

public Animator makeSimultaneousAnimator(final ViewGroup parentViewGroup, final View growingView, final View shrinkingView, final View otherView, float startingWeight, float endingWeight) {
    long duration = 2000;

    ValueAnimator va = ValueAnimator.ofFloat(startingWeight, endingWeight);
    va.setDuration(duration);
    va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            Float value = (Float) animation.getAnimatedValue();
            float growingWeight = value.floatValue();

            LinearLayout.LayoutParams growingParams = (LinearLayout.LayoutParams)growingView.getLayoutParams();
            LinearLayout.LayoutParams shrinkingParams = (LinearLayout.LayoutParams)shrinkingView.getLayoutParams();
            LinearLayout.LayoutParams otherParams = (LinearLayout.LayoutParams)otherView.getLayoutParams();

            float otherWeight = otherParams.weight;
            float shrinkingWeight = 1.0f - growingWeight - otherWeight;

            growingParams.weight = growingWeight;
            shrinkingParams.weight = shrinkingWeight;

            parentViewGroup.requestLayout();
            //growingView.requestLayout();
            //shrinkingView.requestLayout();
        }
    });

    return va;
}
Run Code Online (Sandbox Code Playgroud)

Sim*_*mas 6

我会保留对大的参考ImageView,以便轻松地遵循它.然后每次触发事件时,减少大事件并增加另一个事件.

我已经做了一个例子,每个ImageView内部都有一个点击监听器LinearLayout.

最重要的是中间的ImageView,它的重量是预先设定的,0.6而其他人则拥有它0.2.

码:

private static final float FROM_WEIGHT = 0.2f;
private static final float TO_WEIGHT = 0.6f;
private static final int DURATION = 500;

private View v1, v2, v3, big;
private View.OnClickListener clickListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (v == big) {
            return;
        } else if (v1 == big) {
            animate(v1, TO_WEIGHT, FROM_WEIGHT);
        } else if (v2 == big) {
            animate(v2, TO_WEIGHT, FROM_WEIGHT);
        } else if (v3 == big) {
            animate(v3, TO_WEIGHT, FROM_WEIGHT);
        }
        big = v;
        animate(v, FROM_WEIGHT, TO_WEIGHT);
    }
};

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

    v1 = findViewById(R.id.tv1);
    big = v2 = findViewById(R.id.tv2);
    v3 = findViewById(R.id.tv3);
    v1.setOnClickListener(clickListener);
    v2.setOnClickListener(clickListener);
    v3.setOnClickListener(clickListener);
}

private void animate(final View v, float from, float to) {
    ValueAnimator va = ValueAnimator.ofFloat(from, to);
    va.setDuration(DURATION);
    va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            float growingWeight = (Float) animation.getAnimatedValue();
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) v.getLayoutParams();
            params.weight = growingWeight;
            v.setLayoutParams(params);
        }
    });
    va.start();
}
Run Code Online (Sandbox Code Playgroud)

布局:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:background="#00FFFF"
        android:layout_weight="0.2"
        android:id="@+id/tv1"
        android:layout_width="100dp"
        android:layout_height="0dp"/>

    <ImageView
        android:background="#FFFF00"
        android:layout_weight="0.6"
        android:id="@+id/tv2"
        android:layout_width="100dp"
        android:layout_height="0dp"/>

    <ImageView
        android:background="#FF00FF"
        android:layout_weight="0.2"
        android:id="@+id/tv3"
        android:layout_width="100dp"
        android:layout_height="0dp"/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

影响:

效果的例子