【发布时间】:2015-04-05 02:36:41
【问题描述】:
我已经尝试了很多不同的方法,但都没有奏效。我愿意接受建议。
我正在制作一个自定义“按钮”。它不是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;
}
}
});
这是我制作的视频,展示了按顺序而不是并行运行的动画:
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;
}
【问题讨论】:
-
考虑不为任何
LayoutParams设置动画,因为它们会在每个缓慢的动画帧上触发重新布局操作(比仿射变换慢得多,例如scaleX和scaleY,因为它们'重新使用硬件加速)。相反,您可以使用scale实现相同的效果。据我记得,自从引入动画显示列表后,scale属性甚至不会触发 onDraw 方法。 -
您能否提供一个代码示例来说明您的意思?我有时需要重绘 3 个子视图的内容,因为它们是带有贝塞尔 Path ShapeDrawables 的 ImageView。
-
重绘还是可以的,但是重新布局一般不行。它很可能会在功能强大的设备(如 Nexus 4)上顺利运行,但在“速度较慢”的设备上会出现明显的丢帧现象。取决于您的视图层次结构的复杂程度/嵌套程度。我的意思是使用动画框架制作动画:
view.animate().scaleX(someValue).scaleY(someValue)。我不会为您的问题提供确切的代码,但使用 scale 肯定可以达到相同的结果。所以,这只是一个建议,而不是一个答案。
标签: android android-linearlayout android-animation