Offenbaren für alle!



    Hallo, Chabrowsk-Bürger !
    Ich werde Ihnen erzählen, wie ich die Circual Reveal-Animation von Lollipop implementiert und den Schwellenwert auf Lebkuchen gesenkt habe.

    Lollipop führte die nativen Klassen HardwareCanvas, RenderNodeAnimator für flüssigere Animationen und Renderings sowie Ripple- und Reveal-Animationen ein. Jetzt werden viele Elemente auf Eisenebene gezeichnet und animiert.



    Native Animation



    	public static Animator createCircularReveal(View view,
                int centerX,  int centerY, float startRadius, float endRadius) {
            return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
        }
    


    Wie in der Dokumentation beschrieben, ist RevealAnimator ein animiertes Zuschneiden eines Kreises. Es stammt wiederum vom RenderNodeAnimator ab und ruft die native Methode auf.

        private static native long nCreateRevealAnimator(
                int x, int y, float startRadius, float endRadius);
    


    Es wird bereits ein Kreis abgeschnitten, durch:

    RevealAnimator::RevealAnimator(int centerX, int centerY,
            float startValue, float finalValue)
            : BaseRenderNodeAnimator(finalValue)
            , mCenterX(centerX)
            , mCenterY(centerY) {
        setStartValue(startValue);
    }
    float RevealAnimator::getValue(RenderNode* target) const {
        return target->properties().getRevealClip().getRadius();
    }
    // здесь и происходит обрезка
    void RevealAnimator::setValue(RenderNode* target, float value) {
        target->animatorProperties().mutableRevealClip().set(true,
                mCenterX, mCenterY, value);
    }
    


    Lösung



    Meine Lösung ist relativ einfach: Ich habe meine benutzerdefinierten Layouts (Rahmen | Linear, Original, fast unberührt) erstellt und nur die Methode geändert, mit der Kinder gezeichnet werden

    
        @Override
        protected boolean drawChild(@NonNull Canvas canvas, @NonNull View child, long drawingTime) {
            if(!mClipOutlines && child != mTarget)
                return super.drawChild(canvas, child, drawingTime);
            final int state = canvas.save();
            mRevealPath.reset();
            mRevealPath.addCircle(mCenterX, mCenterY, mRadius, Path.Direction.CW);
            canvas.clipPath(mRevealPath);
            boolean isInvalidated = super.drawChild(canvas, child, drawingTime);
            canvas.restoreToCount(state);
            return isInvalidated;
        }
    


    Ich bitte die Leinwand, während der Animation einen bestimmten Bereich zuzuschneiden. Die Animation wird über ObjectAnimator implementiert (danke an Jake Wharton, Nineoldsandroid).



    Der Artikel stellte sich als etwas zerknittert heraus, wenn Sie Fragen haben, schreiben Sie in die Kommentare, ich werde den Artikel ergänzen :)

    Vielen Dank für Ihre Aufmerksamkeit!
    Github

    Jetzt auch beliebt: