Як дадаць міготную мяжу для CardView

Нядаўна мы атрымалі заданне ад нашых карыстальнікаў UX дадаць "мігцельную анімацыю межаў" у нашу CardViews, калі вы націскаеце на іх. Мяжа павінна неўзабаве набыць іншы колер, а потым вярнуцца да зыходнага стану.

Што нам варта ўзнавіць на Android

На сённяшні дзень анімацыя ў Android па-ранейшаму для мяне па-ранейшаму чорная скрынка. Мая каманда ацаніла квіток даволі высока, таму што ўсе мы ведалі, што гэта неяк будзе працаваць з анімацыяй, але ніхто сапраўды не ўяўляў, як пачаць. Як і кожны распіральнік, і першае, што я зрабіў, калі забраў білет, гугнуў па падобных праблемах, але ажыўленне міргаючай мяжы, здавалася, была праблемай нікога іншага ...

Шмат адказаў на StackOverflow ўстанаўлівалі ўласны фон на View, а потым ажыўлялі змены фона, які можна атрымаць. Аднак я баяўся, што мне прыйдзецца ўручную паклапаціцца пра эфект Ripple, і яшчэ горш, CardView будзе выглядаць агідна. Пасля яшчэ некалькіх адказаў мне нагадалі, што новы MaterialCardView мае ўласцівасць strokeColor. Такім чынам, анімацыя StroColor ад нейкага значэння да іншага можа спрацаваць.

Android мае ўбудаваны для аніміравання змены колеру ўласцівасцей прагляду, для гэтага можна проста выкарыстоўваць ObjectAnimator.ofArgb ():

ObjectAnimator.ofArgb (cardView, "strokeColor", Color.RED). Прымяніць {duration = 1000 start ()}

Кажучы, што мы хочам ажывіць уласцівасць strokeColor нашай карты праглядаць значэнне Color.RED на працягу адной секунды. Вы можаце перадаць некалькі значэнняў колеру, бо гэта займае вараг. Перадача аднаго анімуе ад бягучага значэння да дадзенага значэння. Праходжанне двух будзе ажыўляць з першага ў другі аргумент, а праходжанне яшчэ больш аніміруе ўсіх.

Аднак, калі мы пакладзем вышэй код у слухач клікаў нашага cardView, мы бачым простае паводзіны:

Першая анімацыя, якую мы пачынаем, нічога не робіць, а другая імгненна колеру або чырвоны бардзюр. Мне некаторы час было цікава, чаму колер не мяняецца, потым я дадаў слухач абнаўленняў, які выдае кожнае новае значэнне анімацыі:

addUpdateListener {val colorInt = cardView.strokeColor println (Color.valueOf (colorInt))}

якія адбіткі:

I / System.out: колер (1.0, 1.0, 1.0, 1.0, sRGB IEC61966-2.1) I / System.out: колер (1.0, 0.99607843, 0.99607843, 1.0, sRGB IEC61966-2.1) I / System.out: колер ( 1.0, 0.99607843, 0.99607843, 1.0, sRGB IEC61966-2.1) [...] I / System.out: колер (1.0, 0.0, 0.0, 1.0, sRGB IEC61966-2.1)

Такім чынам, колер на самай справе змяняецца ад белага да чырвонага (чытайце яго як "чырвоны, зялёны, сіні, альфа"), але гэта проста не абнаўленне гледжання! Змена нашага слухача абнаўленняў на

addUpdateListener {cardView.invalidate ()}

дае нам:

Ха! Цяпер павольна мяняецца на чырвоны. Першы крок зроблены

Паколькі мы хочам мець мігценную аблямоўку, зараз нам трэба вярнуць колер абрысу да яго першапачатковага значэння. На шчасце, у гэтых аніматараў ужо ёсць функцыя reverse (), таму мы можам проста паставіць:

doOnEnd {reverse ()}

Кажучы ў канцы анімацыі, перавярніце анімацыю. Аднак пасля таго, як будзе зроблена зваротная анімацыя, слухач будзе спрацаваць яшчэ раз, і адмяніць зваротны ход, пасля чаго ён будзе спрацаваць яшчэ раз, і адменіць адваротны зваротны ход .. ну вы разумееце гэта зараз бясконцая анімацыя.

Што мы можам зрабіць, гэта не выкарыстоўваць функцыю пашырэння, дадаць уласнага слухача і выдаліць яго зноў, так што ён не можа быць зноў запушчаны:

addListener (object: Animator.AnimatorListener {override fun onAnimationRepeat (анімацыя: Animator?) {} адмяніць задавальненне onAnimationEnd (анімацыя: Animator?) {removeListener (this) reverse ()} override fun onAnimationCancel (анімацыя: Animator?) {} адмяніць забаву onAnimationStart (анімацыя: Аніматар?) {}})

Гэта больш не гуляе бясконца, але пасля рэверсіі ён зноў прайгравае пачатковую анімацыю. Я не разумеў, чаму гэта адбываецца - калі вы ведаеце, вы можаце пакінуць каментар.

У гэты момант я проста здабыў усё да метаду і пачаў іншую анімацыю пасля таго, як скончылася першая:

прыватная анімацыя весела (зваротная: Boolean = false) {val colorTo = калі (адваротны!) Color.RED else Color.TRANSPARENT ObjectAnimator.ofArgb (cardView, "strokeColor", colorTo). Прымяненне {duration = 300
        addUpdateListener {cardView.invalidate ()} if (! адваротнае) {doOnEnd {antete (reverse = true)}}
        пачаць ()}}

што выглядае так:

Важна: каб убачыць любы колер абводкі, вы павінны надаць CardView тактовую шырыню не менш за 1 дп. Я таксама раю ўсталяваць strokeColor першапачаткова на Color.TRANSPARENT, інакш у вас можа з'явіцца непажаданая мяжа.

Спадзяюся, гэты артыкул дапамог вам дасягнуць чагосьці падобнага і зэканоміў вам нейкі гуглы час, які я ўжо выдаткаваў