为了实现您想要的效果,在您的动画师中,您需要完成以下两个步骤:
- 使用非默认的枢轴(位于视图中间)旋转视图
- 在旋转时平移视图
在这两种情况下,您需要知道您的视图大小,因此我建议创建自定义布局组件用作片段的根,公开一组可使用不同的
objectanimator
在xml中进行动画处理的属性。
该组件应如下所示:
public class FlippableLayout extends FrameLayout {
private FlipEvaluator flipRightInEvaluator;
private FlipEvaluator flipRightOutEvaluator;
private FlipEvaluator flipLeftInEvaluator;
private FlipEvaluator flipLeftOutEvaluator;
public FlippableLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FlippableLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
setCameraDistance(getCameraDistance() * 10);
flipRightInEvaluator = new FlipEvaluator(
1f, .5f,
-1f, 0f,
-180, 0,
0f, 1f);
flipRightOutEvaluator = new FlipEvaluator(
0f, .5f,
0f, 1f,
0, 180,
1f, 0f);
flipLeftInEvaluator = new FlipEvaluator(
.0f, .5f,
1f, 0f,
180, 0,
0f, 1f);
flipLeftOutEvaluator = new FlipEvaluator(
1f, .5f,
0f, -1f,
0, -180,
1f, 0f);
}
public void setFlipRightIn(float value) {
evaluateUsing(flipRightInEvaluator, value);
}
public void setFlipRightOut(float value) {
evaluateUsing(flipRightOutEvaluator, value);
}
public void setFlipLeftIn(float value) {
evaluateUsing(flipLeftInEvaluator, value);
}
public void setFlipLeftOut(float value) {
evaluateUsing(flipLeftOutEvaluator, value);
}
private void evaluateUsing(FlipEvaluator evaluator, float value) {
float cappedValue = Math.min(1f, Math.max(0f, value));
setPivotX(getWidth() * evaluator.getPivotX());
setPivotY(getHeight() * evaluator.getPivotY());
setAlpha(evaluator.getAlpha(cappedValue));
setTranslationX(getWidth() * evaluator.getTranslationX(cappedValue));
setRotationY(evaluator.getRotationY(cappedValue));
}
private static class FlipEvaluator {
private final float pivotX;
private final float pivotY;
private final float startTranslationX;
private final float endTranslationY;
private final float startRotationY;
private final float endRotationY;
private final float startAlpha;
private final float endAlpha;
private FlipEvaluator(float pivotX, float pivotY,
float startTranslationX, float endTranslationY,
float startRotationY, float endRotationY,
float startAlpha, float endAlpha) {
this.pivotX = pivotX;
this.pivotY = pivotY;
this.startTranslationX = startTranslationX;
this.endTranslationY = endTranslationY;
this.startRotationY = startRotationY;
this.endRotationY = endRotationY;
this.startAlpha = startAlpha;
this.endAlpha = endAlpha;
}
public float getPivotX() {
return pivotX;
}
public float getPivotY() {
return pivotY;
}
public float getTranslationX(float t) {
return startTranslationX + (endTranslationY - startTranslationX) * t;
}
public float getRotationY(float t) {
return startRotationY + (endRotationY - startRotationY) * t;
}
public float getAlpha(float t) {
return t < .5f ? startAlpha : endAlpha;
}
}
}
您的动画文件将会看起来像这样:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="0"
android:valueTo="1"
android:propertyName="flipLeftIn"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="1000" />
当然,你可以将flipLeftIn
替换为flipLeftOut
、flipRightIn
或flipRightOut
,以便将动画应用到不同的属性上。
在你的Activity
中,你可以像往常一样在片段事务中设置自定义动画,指定之前定义的XML文件:
....
getFragmentManager()
.beginTransaction()
.setCustomAnimations(
R.animator.card_flip_right_in, R.animator.card_flip_right_out,
R.animator.card_flip_left_in, R.animator.card_flip_left_out)
....
另一种方法是完全在XML中处理,但是使用XML定义的维度值设置枢轴/平移不如上面显示的解决方案具有可扩展性。
编辑
要减少相机距离,您可以在API>12上轻松使用View.setCameraDistance()。我更新了包括此更改的代码片段。