在老机器人上显示卡翻转animation

我们都知道如何使用new api创建"card filp"animation。 但是我怎样才能on apis < 3.0做到这一点?

更新:

只要有像android-FlipView这样的好用且易于使用的库,我认为你真的不需要经历如此艰难的方式……

Solutions Collecting From Web of "在老机器人上显示卡翻转animation"

find了答案。 如果要在ALL ANDROID VERSIONS上执行翻转animation,请使用:

活动布局文件:

       

当布局文件翻转两个视图组时,您可以在视图组中放置任何其他视图组,它应该可以工作。 现在让我们看一下处理调用翻转animation代码的活动内部的方法:

 public void onCardClick(View view) { flipCard(); } private void flipCard() { View rootLayout = findViewById(R.id.main_activity_root); View cardFace = findViewById(R.id.main_activity_card_face); View cardBack = findViewById(R.id.main_activity_card_back); FlipAnimation flipAnimation = new FlipAnimation(cardFace, cardBack); if (cardFace.getVisibility() == View.GONE) { flipAnimation.reverse(); } rootLayout.startAnimation(flipAnimation); } 

最后是FlipAnimation类:

 public class FlipAnimation extends Animation { private Camera camera; private View fromView; private View toView; private float centerX; private float centerY; private boolean forward = true; /** * Creates a 3D flip animation between two views. * * @param fromView First view in the transition. * @param toView Second view in the transition. */ public FlipAnimation(View fromView, View toView) { this.fromView = fromView; this.toView = toView; setDuration(700); setFillAfter(false); setInterpolator(new AccelerateDecelerateInterpolator()); } public void reverse() { forward = false; View switchView = toView; toView = fromView; fromView = switchView; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); centerX = width/2; centerY = height/2; camera = new Camera(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { // Angle around the y-axis of the rotation at the given time // calculated both in radians and degrees. final double radians = Math.PI * interpolatedTime; float degrees = (float) (180.0 * radians / Math.PI); // Once we reach the midpoint in the animation, we need to hide the // source view and show the destination view. We also need to change // the angle by 180 degrees so that the destination does not come in // flipped around if (interpolatedTime >= 0.5f) { degrees -= 180.f; fromView.setVisibility(View.GONE); toView.setVisibility(View.VISIBLE); } if (forward) degrees = -degrees; //determines direction of rotation when flip begins final Matrix matrix = t.getMatrix(); camera.save(); camera.rotateY(degrees); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); } 

这是原始post的链接: 在旧的android上显示卡片翻转animation

来自@FMMobileFelipeMenezes的更新

如果您想要平滑的缩放animation,请将此部分代码更改为(applyTransformation):

 final Matrix matrix = t.getMatrix(); camera.save(); camera.translate(0, 0, Math.abs(degrees)*2); camera.getMatrix(matrix); camera.rotateY(degrees); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); 

来自@Hesam的更新有一个很好的教程,我建议阅读它。 虽然它不如基于片段的Android教程那么好,但是如果你想为布局和视图分配animation以及将它放在旧的API上,那么值得阅读和使用。

使用Android的缩放animation来模拟3D翻转

@LenaBru改进了github上的项目

我在下面使用了Flextra代码,如果你想要平滑的缩放animation,请将这部分代码更改为(applyTransformation):

  final Matrix matrix = t.getMatrix(); camera.save(); camera.translate(0, 0, Math.abs(degrees)*2); camera.getMatrix(matrix); camera.rotateY(degrees); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); 

我整天玩这个,终于实现了最终的目标 – 像两个视图的旋转animation一样流畅的卡片翻转!

我在这里放了demo项目

 public class FlipAnimation extends Animation { private Camera camera; private View fromView; private View toView; private float centerX; private float centerY; private boolean forward = true; /** * Creates a 3D flip animation between two views. * * @param fromView * First view in the transition. * @param toView * Second view in the transition. */ public FlipAnimation(View fromView, View toView) { this.fromView = fromView; this.toView = toView; setDuration(1500); setFillAfter(false); // setInterpolator(new AccelerateDecelerateInterpolator()); setInterpolator(new LinearInterpolator()); } public void reverse() { if (forward) { View switchView = toView; toView = fromView; fromView = switchView; } forward = false; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); centerX = width / 2; centerY = height / 2; camera = new Camera(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { // Angle around the y-axis of the rotation at the given time // calculated both in radians and degrees. final double radians = Math.PI * interpolatedTime; float degrees = (float) (180.0 * radians / Math.PI); //scale down the views a bit, so that they would look nice when the rotation begins if (interpolatedTime < = 0.05f) { fromView.setScaleX(1 - interpolatedTime); fromView.setScaleY(1 - interpolatedTime); toView.setScaleX(1 - interpolatedTime); toView.setScaleY(1 - interpolatedTime); } // Once we reach the midpoint in the animation, we need to hide the // source view and show the destination view. We also need to change // the angle by 180 degrees so that the destination does not come in //It is very important to call "toView.bringToFront()" and not play with the // visibility of the views, because if you apply this animation more than once, //the subsequent calls may fail if (interpolatedTime >= 0.5f) { degrees -= 180.f; toView.bringToFront(); //these two lines force a layout redraw ((View)toView.getParent()).requestLayout(); ((View)toView.getParent()).invalidate(); } //scale the views back to their original size (Assuming original size was 1) if (interpolatedTime >= 0.95f) { fromView.setScaleX(interpolatedTime); fromView.setScaleY(interpolatedTime); toView.setScaleX(interpolatedTime); toView.setScaleY(interpolatedTime); } if (forward) degrees = -degrees; // determines direction of rotation when flip // begins final Matrix matrix = t.getMatrix(); camera.save(); camera.translate(0, 0, Math.abs(degrees) * 2); camera.getMatrix(matrix); camera.rotateY(degrees); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); } } 

并称之为这样

 import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.FragmentActivity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Toast; public class MainActivity extends FragmentActivity { private boolean showingBack; private FragmentLeft left = new FragmentLeft(); private FragmentRight right = new FragmentRight(); private Context context; private Handler handler; private FlipAnimation flipAnimation; private FlipAnimation backFlip; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this; handler = new Handler(getMainLooper()); getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, right, "fragmentRight").commit(); getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, left, "fragmentLeft").commit(); findViewById(R.id.flip).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { flipAnimation = new FlipAnimation(left.getView(), right.getView()); backFlip = new FlipAnimation(left.getView(), right.getView()); handler.removeCallbacks(rotate); handler.postDelayed(rotate, 100); } }); } private Runnable rotate = new Runnable() { @Override public void run() { //put a variable showingBack, do not rely on view properties to flip if (!showingBack) { //very important to flip both views, so that when the //left view goes to back and right view goes to front, //the right view finishes the rotation left.getView().startAnimation(flipAnimation); right.getView().startAnimation(flipAnimation); Toast.makeText(context, "flip", Toast.LENGTH_LONG).show(); showingBack = true; } else { showingBack = false; backFlip.reverse(); Toast.makeText(context, "backflip", Toast.LENGTH_LONG).show(); //very important to flip both views, so that when the //right view goes to back and right view goes to front, //the left view finishes the rotation left.getView().startAnimation(backFlip); right.getView().startAnimation(backFlip); } } }; } 

这些是碎片

 import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class FragmentRight extends Fragment { @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_right, container,false); } } import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class FragmentLeft extends Fragment { @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_left, container,false); } } 

最后是观点本身

activity_main.xml中

       

fragment_left.xml

 < ?xml version="1.0" encoding="utf-8"?>    

fragment_right.xml

 < ?xml version="1.0" encoding="utf-8"?>    

请注意从Flextra和@FMMobileFelipeMenezes答案中获取的一些代码

有一个很好的教程,我建议阅读它。 虽然它不如基于片段的Android教程那么好,但是如果你想为布局和视图分配animation以及将它放在旧的API上,那么值得阅读和使用。

使用Android的缩放animation来模拟3D翻转