Android 新活动的循环过渡
依照Android 新活动的循环过渡,android,animation,material-design,Android,Animation,Material Design,依照 ViewAnimationUtils.createCircularReveal()方法使您能够 设置剪切圆的动画以显示或隐藏视图 要使用此效果显示以前不可见的视图,请执行以下操作: // previously invisible view View myView = findViewById(R.id.my_view); // get the center for the clipping circle int cx = (myView.getLeft() + myView.getRig
ViewAnimationUtils.createCircularReveal()
方法使您能够
设置剪切圆的动画以显示或隐藏视图
要使用此效果显示以前不可见的视图,请执行以下操作:
// 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 action按钮循环显示。在寻找半天没有结果的解决方案后,我想出了一个自己的实现。我正在使用具有匹配根布局的透明活动。 根布局是一个视图,可以使用
createCircularReveal()
显示该视图
我的代码如下所示:
style.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>
<activity
android:name=".ui.CircularRevealActivity"
android:theme="@style/Theme.Transparent"
android:launchMode="singleTask"
/>
将circularRevealActivity()
放入OnGlobalLayoutListener
中非常重要,因为需要为动画绘制视图
circularrevelactivity()
看起来像伊莎恩的提议:
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\u not\u move
的定义。但是,如果您的设计没有为活动指定默认转换,那么在没有该行的情况下它也应该可以工作。让我知道
R.anim.请勿移动:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="0"
android:toYDelta="0"
android:duration="@android:integer/config_mediumAnimTime"
/>
</set>
要反转循环视图
动画,请交换startRadius
和endRadius
参数。您还需要设置一个AnimatorListener
,在onAnimationEnd()
回调方法中可以调用finishAfterTransition()
。这适用于当您按下向上导航
或单击后退按钮
时,我认为您可以使用活动选项compat.makeClipRevealAnimation
[,int,int,int,int,int)](,int,int,int,int,int))您必须绘制圆形视图,然后您应该为其创建动画 创建圆视图:
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;
}
}
创建动画类以设置新角度:
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" />
如果要反转“离开时循环分隔缝”活动,请使用以下对onBackPressed()的修改
不。不再积极寻找了。谢谢你这么详细的回答。它对你有用吗?这周我要试一试。工作对我来说很有魅力。我只是觉得这个通告应该是可能的,不需要将两个活动合并为一个。。。如果有问题,请告诉我。效果很好。我更改了cx和cy值以更改原点R.anim.do_not_move?的定义是什么?@StefanMedack您应该添加
getViewTreeObserver().RemoveGlobalOnlyOutliner(此)代码>在onGlobalLayout()
中。这样可以避免多次调用导致双重显示。在这里工作。仅在APi 23+上工作,否则默认为标准动画。如何使用此“上一步”按钮返回到以前的活动?这不是用户要求的,但无论如何这帮助了我。您应该详细说明如何实现反向动画。
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" />
Circle circle = (Circle) findViewById(R.id.circle);
CircleAngleAnimation animation = new CircleAngleAnimation(circle, 240);
animation.setDuration(1000);
circle.startAnimation(animation);
@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();
}
}