...

вторник, 18 ноября 2014 г.

Reveal для всех!


Здравствуйте, Хабровчане !

Я расскажу как я реализовал 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).



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


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

Github


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий