Циркуляр показывает переход для новой активности
Согласно https://developer.android.com/training/material/animations.html
Метод 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();
Это предназначено, чтобы показать представление. Как я могу использовать это для кругового раскрытия всей деятельности без каких-либо общих элементов?
В частности, мне бы хотелось, чтобы моя функция поиска была открыта кругом из кнопки поиска на панели инструментов.
Ответы
Ответ 1
После поиска решения в течение полудня без результата, я придумал собственную реализацию. Я использую прозрачную активность с подходящим корневым макетом.
Корневая компоновка представляет собой представление, которое затем может быть обнаружено с помощью 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"
/>
то я объявил макет для своей деятельности (я выбрал 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>
Важным является FrameLayout с идентификатором root_layout
. Это представление будет раскрыто в этой деятельности.
Наконец, я реализовал 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
, потому что для анимации нужно рисовать.
circularRevealActivity()
выглядит как предложение Ишана:
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
. Тем не менее, он должен работать и без этой строки, если в вашем проекте не указаны переходы по умолчанию для действий. Дайте мне знать
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>
Ответ 2
Чтобы отменить анимацию CircularReveal
, замените аргументы startRadius
и endRadius
. Также вам нужно настроить AnimatorListener
, а в методе обратного вызова onAnimationEnd()
вы можете вызвать finishAfterTransition()
. Это происходит, когда вы нажимаете кнопку up navigation
или нажимаете back button
.
Ответ 3
Я думаю, вы можете использовать ActivityOptionsCompat.makeClipRevealAnimation
.
[https://developer.android.com/reference/android/support/v4/app/ActivityOptionsCompat.html#makeClipRevealAnimation(android.view.View, int, int, int, int)] (https://developer.android.com/reference/android/support/v4/app/ActivityOptionsCompat.html#makeClipRevealAnimation(android.view.View, int, int, int, int))
Ответ 4
Если вы хотите отменить круговое раскрытие при уходе, используйте следующую модификацию для 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();
}
}
Ответ 5
ou нужно нарисовать круг, и после этого вы должны создать анимацию.
Создание представления окружности:
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" />
И наконец, начиная анимацию:
Circle circle = (Circle) findViewById(R.id.circle);
CircleAngleAnimation animation = new CircleAngleAnimation(circle, 240);
animation.setDuration(1000);
circle.startAnimation(animation);