圆形显示新活动的过渡

按照https://developer.android.com/training/material/animations.html

ViewAnimationUtils.createCircularReveal()方法使您可以animation剪辑圈来显示或隐藏视图。

使用这个效果来揭示以前不可见的视图:

 // previously invisible view View myView = findViewById(R.id.my_view); // get the center for the clipping circle int cx = (myView.getLeft() + myView.getRight()) / 2; int cy = (myView.getTop() + myView.getBottom()) / 2; // get the final radius for the clipping circle int finalRadius = Math.max(myView.getWidth(), myView.getHeight()); // create the animator for this view (the start radius is zero) Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius); // make the view visible and start the animation myView.setVisibility(View.VISIBLE); anim.start(); 

这是为了揭示一个观点。 我如何使用这个来循环显示整个活动,没有任何共享元素?

具体来说,我想我的searchActivity从工具栏中的search操作button循环显示。

找了半天没有结果的解决scheme后,我想出了一个自己的实现。 我正在使用具有匹配根目录布局的透明活动。 根布局是可以用createCircularReveal()显示的视图。

我的代码如下所示:

styles.xml中的主题定义

 <style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowIsTranslucent">true</item> <item name="android:statusBarColor">@android:color/transparent</item> <item name="android:windowBackground">@android:color/transparent</item> </style> 

AndroidManifest.xml中的活动定义

 <activity android:name=".ui.CircularRevealActivity" android:theme="@style/Theme.Transparent" android:launchMode="singleTask" /> 

然后我为我的活动声明了一个布局(我select了DrawerLayout,这样我就可以有一个NavDrawer了,每个布局都应该在这里工作)。

 <android.support.v4.widget.DrawerLayout android:id="@+id/drawer_layout" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <FrameLayout android:id="@+id/root_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/honey_melon" > <!-- Insert your actual layout here --> </FrameLayout> </android.support.v4.widget.DrawerLayout> 

重要的是带有root_layout的FrameLayout。 这个观点将在活动中揭示。

最后我实现了CircularRevealActivity并覆盖onCreate()

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); overridePendingTransition(R.anim.do_not_move, R.anim.do_not_move); setContentView(R.layout.activity_reveal_circular); if (savedInstanceState == null) { rootLayout.setVisibility(View.INVISIBLE); ViewTreeObserver viewTreeObserver = rootLayout.getViewTreeObserver(); if (viewTreeObserver.isAlive()) { viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { circularRevealActivity(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); } else { rootLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this); } } }); } } } 

circularRevealActivity()放入OnGlobalLayoutListener非常重要,因为需要为该animation绘制视图。

circularRevealActivity()看起来像Ishaan的build议:

 private void circularRevealActivity() { int cx = rootLayout.getWidth() / 2; int cy = rootLayout.getHeight() / 2; float finalRadius = Math.max(rootLayout.getWidth(), rootLayout.getHeight()); // create the animator for this view (the start radius is zero) Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootLayout, cx, cy, 0, finalRadius); circularReveal.setDuration(1000); // make the view visible and start the animation rootLayout.setVisibility(View.VISIBLE); circularReveal.start(); } 

编辑1

添加了R.anim.do_not_move的定义。 但是,如果您的devise没有指定活动的默认转换,它也应该没有这一行。 让我知道

R.anim.do_not_move:

 <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromYDelta="0" android:toYDelta="0" android:duration="@android:integer/config_mediumAnimTime" /> </set> 

要反转CircularRevealanimation,请交换startRadiusendRadius参数。 您还需要设置AnimatorListener并在onAnimationEnd()callback方法中调用finishAfterTransition() 。 这是为了当你按下up navigation或点击back button

如果要在离开活动时取消循环显示,请对onBackPressed()使用以下修改。

 @Override public void onBackPressed() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { int cx = rootLayout.getWidth(); int cy = 0; float finalRadius = Math.max(rootLayout.getWidth(), rootLayout.getHeight()); Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootLayout, cx, cy, finalRadius, 0); circularReveal.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { } @Override public void onAnimationEnd(Animator animator) { rootLayout.setVisibility(View.INVISIBLE); finish(); } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); circularReveal.setDuration(400); circularReveal.start(); }else{ super.onBackPressed(); } } 

我想你可以使用ActivityOptionsCompat.makeClipRevealAnimation

[ https://developer.android.com/reference/android/support/v4/app/ActivityOptionsCompat.html#makeClipRevealAnimation(android.view.View,int,int,int,int)%5D(https://developer.android / android / support / v4 / app / ActivityOptionsCompat.html#makeClipRevealAnimation(android.view.View ,int,int,int,int)

你必须绘制圆形视图,之后你应该创build一个animation。

创build圆视图:

 public class Circle extends View { private static final int START_ANGLE_POINT = 90; private final Paint paint; private final RectF rect; private float angle; public Circle(Context context, AttributeSet attrs) { super(context, attrs); final int strokeWidth = 40; paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(strokeWidth); //Circle color paint.setColor(Color.RED); //size 200x200 example rect = new RectF(strokeWidth, strokeWidth, 200 + strokeWidth, 200 + strokeWidth); //Initial Angle (optional, it can be zero) angle = 120; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint); } public float getAngle() { return angle; } public void setAngle(float angle) { this.angle = angle; } } 

创buildanimation类来设置新的angular度:

 public class CircleAngleAnimation extends Animation { private Circle circle; private float oldAngle; private float newAngle; public CircleAngleAnimation(Circle circle, int newAngle) { this.oldAngle = circle.getAngle(); this.newAngle = newAngle; this.circle = circle; } @Override protected void applyTransformation(float interpolatedTime, Transformation transformation) { float angle = oldAngle + ((newAngle - oldAngle) * interpolatedTime); circle.setAngle(angle); circle.requestLayout(); } } 

将圆圈放入您的布局中:

 <com.package.Circle android:id="@+id/circle" android:layout_width="300dp" android:layout_height="300dp" /> 

最后开始animation:

 Circle circle = (Circle) findViewById(R.id.circle); CircleAngleAnimation animation = new CircleAngleAnimation(circle, 240); animation.setDuration(1000); circle.startAnimation(animation);