Rundschreiben enthüllen Übergang für neue Aktivität

73

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.

Ishaan Garg
quelle
Nee. Ich suche nicht mehr aktiv danach.
Ishaan Garg

Antworten:

88

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 CircularRevealActivityund überschrieben 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);
                    } 
                }
            });
        }
    }
}

Es war wichtig, circularRevealActivity()in eine zu setzen OnGlobalLayoutListener, 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_movewurde 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 Bescheid

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>
Stefan Medack
quelle
Vielen Dank für diese ausführliche Antwort. Funktioniert es für dich? Ich werde es diese Woche versuchen.
Ishaan Garg
Arbeiten wie ein Zauber für mich. Ich hatte gerade das Gefühl, dass diese kreisförmige Enthüllung möglich sein sollte, ohne zwei Aktivitäten zu einer zusammenzuführen ... Wenn es Probleme gibt, lassen Sie es mich wissen.
Stefan Medack
1
funktioniert super. Ich habe den cx- und cy-Wert geändert, um den Ursprungspunkt zu ändern
ch3tanz
Was ist die Definition von R.anim.do_not_move?
Jaka Dirnbek
1
@StefanMedack Sie shoud hinzufügen getViewTreeObserver().removeGlobalOnLayoutListener(this);in onGlobalLayout(). Dadurch wird vermieden, mehr als einmal anzurufen, was zu einer doppelten Enthüllung führte. Funktioniert hier.
WindRider
9

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();
    }
}
Jayasoo
quelle
8

Um die CircularRevealAnimation umzukehren, tauschen Sie die Argumente startRadiusund aus endRadius. Außerdem müssen Sie ein einrichten AnimatorListenerund in der onAnimationEnd()Rückrufmethode können Sie aufrufen finishAfterTransition(). Dies ist der Fall, wenn Sie die up navigationTaste drücken oder auf die Schaltfläche klicken back button.

toobsco42
quelle
Sie sollten im Detail sagen, wie Sie eine umgekehrte Animation erzielen.
Pei
7

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))

TeeTracker
quelle
1
Funktioniert nur mit APi 23+, ansonsten wird standardmäßig die Standardanimation verwendet
Bob Bobbington,
1
Wie auch immer, um die Schaltfläche "Zurück" zu verwenden, um zur vorherigen Aktivität zurückzukehren?
JavierSegoviaCordoba
2

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);
Mahesh Kumthekar
quelle
Dies ist nicht wat Benutzer gefragt, aber trotzdem hat mir das sehr geholfen
AMAN SINGH