请问这是否可以通过xml实现?
以下是答案,但只适用于3.0及以上版本。
1)创建一个名为“animator”的新资源文件夹。
2)创建一个新的.xml文件,我将其称为“flipping”。使用以下xml代码:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="0" android:valueTo="360" android:propertyName="rotationY" >
</objectAnimator>
不,objectAnimator标签不以大写字母“O”开头。
3)使用以下代码启动动画:
ObjectAnimator anim = (ObjectAnimator) AnimatorInflater.loadAnimator(mContext, R.animator.flipping);
anim.setTarget(A View Object reference goes here i.e. ImageView);
anim.setDuration(3000);
anim.start();
我是从这里获取的所有内容。
由于这个问题的答案相当陈旧,这里提供一个更现代的解决方案,依赖于ValueAnimators。 该解决方案实现了真正美观的3D翻转效果,因为它不仅会翻转视图,还会在翻转时对其进行缩放(这是苹果的做法)。
首先,我们设置了ValueAnimator:
mFlipAnimator = ValueAnimator.ofFloat(0f, 1f);
mFlipAnimator.addUpdateListener(new FlipListener(frontView, backView));
相应的更新监听器:
public class FlipListener implements ValueAnimator.AnimatorUpdateListener {
private final View mFrontView;
private final View mBackView;
private boolean mFlipped;
public FlipListener(final View front, final View back) {
this.mFrontView = front;
this.mBackView = back;
this.mBackView.setVisibility(View.GONE);
}
@Override
public void onAnimationUpdate(final ValueAnimator animation) {
final float value = animation.getAnimatedFraction();
final float scaleValue = 0.625f + (1.5f * (value - 0.5f) * (value - 0.5f));
if(value <= 0.5f){
this.mFrontView.setRotationY(180 * value);
this.mFrontView.setScaleX(scaleValue);
this.mFrontView.setScaleY(scaleValue);
if(mFlipped){
setStateFlipped(false);
}
} else {
this.mBackView.setRotationY(-180 * (1f- value));
this.mBackView.setScaleX(scaleValue);
this.mBackView.setScaleY(scaleValue);
if(!mFlipped){
setStateFlipped(true);
}
}
}
private void setStateFlipped(boolean flipped) {
mFlipped = flipped;
this.mFrontView.setVisibility(flipped ? View.GONE : View.VISIBLE);
this.mBackView.setVisibility(flipped ? View.VISIBLE : View.GONE);
}
}
就是这样!
进行此设置后,您可以通过调用以下方法翻转视图:
mFlipAnimator.start();
通过调用反转翻转
mFlipAnimator.reverse();
如果你想检查视图是否翻转,请实现并调用此函数:
private boolean isFlipped() {
return mFlipAnimator.getAnimatedFraction() == 1;
}
您还可以通过实现此方法来检查视图当前是否正在翻转:
您可以通过实现此方法来检查视图当前是否正在翻转:
private boolean isFlipping() {
final float currentValue = mFlipAnimator.getAnimatedFraction();
return (currentValue < 1 && currentValue > 0);
}
你可以组合上述函数来实现一个很好的翻转切换功能,具体取决于它是否已经翻转:private void toggleFlip() {
if(isFlipped()){
mFlipAnimator.reverse();
} else {
mFlipAnimator.start();
}
}
就这样了! 简单易懂。享受吧!
我已经创建了一个简单的程序,可以创建类似于下面这样的视图翻转:
在Activity中,您需要创建此方法,以添加flip_rotation到视图中。
private void applyRotation(View view)
{
final Flip3dAnimation rotation = new Flip3dAnimation(view);
rotation.applyPropertiesInRotation();
view.startAnimation(rotation);
}
import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;
public class Flip3dAnimation extends Animation {
private final float mFromDegrees;
private final float mToDegrees;
private final float mCenterX;
private final float mCenterY;
private Camera mCamera;
public Flip3dAnimation(View view) {
mFromDegrees = 0;
mToDegrees = 720;
mCenterX = view.getWidth() / 2.0f;
mCenterY = view.getHeight() / 2.0f;
}
@Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}
public void applyPropertiesInRotation()
{
this.setDuration(2000);
this.setFillAfter(true);
this.setInterpolator(new AccelerateInterpolator());
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
float degrees = fromDegrees
+ ((mToDegrees - fromDegrees) * interpolatedTime);
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
final Matrix matrix = t.getMatrix();
camera.save();
Log.e("Degree",""+degrees) ;
Log.e("centerX",""+centerX) ;
Log.e("centerY",""+centerY) ;
camera.rotateY(degrees);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
在不使用资源动画的情况下,翻转图像的较好解决方案如下:
ObjectAnimator animation = ObjectAnimator.ofFloat(YOUR_IMAGEVIEW, "rotationY", 0.0f, 360f); // HERE 360 IS THE ANGLE OF ROTATE, YOU CAN USE 90, 180 IN PLACE OF IT, ACCORDING TO YOURS REQUIREMENT
animation.setDuration(500); // HERE 500 IS THE DURATION OF THE ANIMATION, YOU CAN INCREASE OR DECREASE ACCORDING TO YOURS REQUIREMENT
animation.setInterpolator(new AccelerateDecelerateInterpolator());
animation.start();
The simplest way to do it is using ViewPropertyAnimator
mImageView.animate().rotationY(360f);
Using the fluent interface you can build more complex and exciting animation. E.g. you can enable hardware acceleration just call withLayer() method(API 16). More here
If you want to figure out how to create 3d flick animation, please follow here and here
I implemended my own solution only for a research. It includes: cancelation, accelleration, support API >= 15 and is based on Property Animation. The entire animation includes 4 parts, 2 for each side. Every objectAnimator has a listener that defines current animation index and represents an image in the onAnimationStart and current play time value in the onAnimationCancel. It looks like
mQuarterAnim1.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mQuarterCurrentAnimStartIndex = QUARTER_ANIM_INDEX_1;
mImageView.setImageResource(mResIdFrontCard);
}
@Override
public void onAnimationCancel(Animator animation) {
mQuarterCurrentAnimPlayTime = ((ObjectAnimator) animation).getCurrentPlayTime();
}
});
For start set call
mAnimatorSet.play(mQuarterAnim1).before(mQuarterAnim2)
If AnimatorSet was canceled we can calculate delta and run the reverse animation relying on the current index animation and the current play time value.
long degreeDelta = mQuarterCurrentAnimPlayTime * QUARTER_ROTATE / QUARTER_ANIM_DURATION;
if (mQuarterCurrentAnimStartIndex == QUARTER_ANIM_INDEX_1) {
mQuarterAnim4.setFloatValues(degreeDelta, QUARTER_FROM_1);
mQuarterAnim4.setDuration(mQuarterCurrentAnimPlayTime);
mAnimatorSet.play(mQuarterAnim4);
}
您可以在这里找到完整的代码片段。
ObjectAnimator flip = ObjectAnimator.ofFloat(viewToFlip, "rotationY", 0f, 360f); // or rotationX
flip.setDuration(2000); // 2 seconds
flip.start();
在A. Steenbergen的优秀答案中补充一点。当翻转同一个视图(例如更新TextView
)时,我在构造函数中删除了View.Visibility
的更改,以保持过渡更加平滑。
public FlipListener(final View front, final View back) {
this.mFrontView = front;
this.mBackView = back;
}