Reveal для всех!

62667f1d00eb4ba08d9eda3d93503cc0.jpgЗдравствуйте, Хабровчане! Я расскажу как я реализовал Circual Reveal анимацию из Lollipop, опустив порог до Gingerbread.

В Lollipop появились нативные классы HardwareCanvas, RenderNodeAnimator для более плавной анимации и отрисовки, на нем построена Ripple и Reveal анимация. Теперь многие элементы рисуются и анимируются на уровне железа.

Родная анимация public static Animator createCircularReveal (View view, int centerX, int centerY, float startRadius, float endRadius) { return new RevealAnimator (view, centerX, centerY, startRadius, endRadius); } Как описанно в документации, RevealAnimator — это анимированная обрезка круга. Он в свою очередь произошел от RenderNodeAnimator и вызывает нативный метод.

private static native long nCreateRevealAnimator ( int x, int y, float startRadius, float endRadius); Там уже и идет обрезка круга, через:

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); } Решение Мое решение относительно простое: я создал свои кастомные Layout’ы (Frame | Linear, оригинальные, почти нетронутые), изменив всего лишь метод, где рисуются дети

@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; }

Я лишь прошу canvas обрезать определненную область во время анимации. Анимация реализуется через ObjectAnimator (thanks to Jake Wharton, nineoldsandroid).

[embedded content]

Статья получилась немного скомканной, если есть вопросы пишите в комментарии, дополню статью :)

Спасибо за внимание! Github

© Habrahabr.ru