Gemäß https://developer.android.com/training/material/animations.html
Mit dieser
ViewAnimationUtils.createCircularReveal()
Methode können Sie einen Schnittkreis animieren, um eine Ansicht anzuzeigen oder auszublenden.So zeigen Sie mit diesem Effekt eine zuvor unsichtbare Ansicht an:
// 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();
Dies soll eine Ansicht offenbaren. Wie kann ich damit eine gesamte Aktivität ohne gemeinsame Elemente zirkulär anzeigen?
Insbesondere möchte ich, dass meine searchActivity über die Schaltfläche für Suchaktionen in der Symbolleiste zirkulär angezeigt wird.
android
animation
material-design
Ishaan Garg
quelle
quelle
Antworten:
Nachdem ich einen halben Tag lang ohne Ergebnis nach einer Lösung gesucht hatte, kam ich auf eine eigene Implementierung. Ich verwende eine transparente Aktivität mit einem passenden Root-Layout. Das Root-Layout ist eine Ansicht, mit der dann angezeigt werden kann
createCircularReveal()
.Mein Code sieht folgendermaßen aus:
Themendefinition in 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>
Aktivitätsdefinition in AndroidManifest.xml
<activity android:name=".ui.CircularRevealActivity" android:theme="@style/Theme.Transparent" android:launchMode="singleTask" />
Dann habe ich ein Layout für meine Aktivität deklariert (ich habe DrawerLayout ausgewählt, damit ich einen NavDrawer haben kann. Jedes Layout sollte hier funktionieren.)
<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>
Wichtig ist das FrameLayout mit der ID
root_layout
. Diese Ansicht wird in der Aktivität offenbart.Schließlich habe ich implementiert
CircularRevealActivity
und überschriebenonCreate()
:@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); } } }); } } }
Es war wichtig,
circularRevealActivity()
in eine zu setzenOnGlobalLayoutListener
, da die Ansicht für die Animation gezeichnet werden muss.circularRevealActivity()
sieht aus wie Ishaans Vorschlag: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(); }
Bearbeiten 1
Die Definition für
R.anim.do_not_move
wurde hinzugefügt. Es sollte jedoch auch ohne diese Zeile funktionieren, wenn in Ihrem Entwurf keine Standardübergänge für Aktivitäten angegeben sind. Gib mir BescheidR.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>
quelle
getViewTreeObserver().removeGlobalOnLayoutListener(this);
inonGlobalLayout()
. Dadurch wird vermieden, mehr als einmal anzurufen, was zu einer doppelten Enthüllung führte. Funktioniert hier.Wenn Sie die kreisförmige Enthüllung beim Verlassen der Aktivität umkehren möchten, verwenden Sie die folgende Änderung für 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(); } }
quelle
Um die
CircularReveal
Animation umzukehren, tauschen Sie die ArgumentestartRadius
und ausendRadius
. Außerdem müssen Sie ein einrichtenAnimatorListener
und in deronAnimationEnd()
Rückrufmethode können Sie aufrufenfinishAfterTransition()
. Dies ist der Fall, wenn Sie dieup navigation
Taste drücken oder auf die Schaltfläche klickenback button
.quelle
Ich denke du kannst es benutzen
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))
quelle
Sie müssen die Kreisansicht zeichnen, und danach sollten Sie eine Animation dazu erstellen.
Erstellen der Kreisansicht:
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; } }
Erstellen der Animationsklasse zum Festlegen des neuen Winkels:
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(); } }
Fügen Sie einen Kreis in Ihr Layout ein:
<com.package.Circle android:id="@+id/circle" android:layout_width="300dp" android:layout_height="300dp" />
Und zum Schluss die Animation starten:
Circle circle = (Circle) findViewById(R.id.circle); CircleAngleAnimation animation = new CircleAngleAnimation(circle, 240); animation.setDuration(1000); circle.startAnimation(animation);
quelle