Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the like Animation effect with Android

2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

Today, the editor will share with you the relevant knowledge points about how Android realizes the animation effect of giving likes. The content is detailed and the logic is clear. I believe most people still know too much about this, so share this article for your reference. I hope you can get something after reading this article. Let's take a look at it.

I. Preface

The exploration of the implementation of the following functions.

II. Demand split

Take a closer look at the like interaction and see the following steps:

1: the like control needs to be customized to handle its touch event.

2: the realization of like animation.

3: have a container for animations.

Third, implementation plan 1. Touch event handling of like control

The like control distinguishes between long press and click processing, and we find that the animation is performed after the finger is pressed, including the movement of the finger until the finger is lifted. Since the click area of like may include the number of likes, we customize the like control and handle the onTouchEvent (event: MotionEvent) event. The difference between long click and click is based on the interval between click and finger lift. The pseudo code is as follows:

Override fun onTouchEvent (event: MotionEvent): Boolean {var onTouch: Boolean when (event.action) {MotionEvent.ACTION_DOWN-> {isRefreshing = false isDowning = true / / Click lastDownTime = System.currentTimeMillis () postDelayed (autoPollTask CLICK_INTERVAL_TIME) onTouch = true} MotionEvent.ACTION_UP-> {isDowning = false / / lift if (System.currentTimeMillis ()-lastDownTime

< CLICK_INTERVAL_TIME) { //小于间隔时间按照单击处理 onFingerDowningListener?.onDown(this) } else { //大于等于间隔时间按照长按抬起手指处理 onFingerDowningListener?.onUp() } removeCallbacks(autoPollTask) onTouch = true } MotionEvent.ACTION_CANCEL ->

< 1 ->

{rect.left = initialValue-bitmap.width rect.right = initialValue} mNumber/ 10 in 1.. 9-> {rect.left = initialValue rect.right = initialValue + bitmap.width} else-> { Rect.left = initialValue + bitmap.width rect.right = initialValue + 2* bitmap.width}} rect.bottom = bitmap.height / / draw digital canvas.drawBitmap (bitmap Null, rect TextPaint) mNumber / = 10}} fun setNumber (number: Int) {this.mNumber = number if (mNumber > 999) {mNumber = 999} level = when (mNumber) {in 1.. 20-> {0} in 21.. 80-> { 1} else-> {2}} / / take out the grade copy icon bitmapTalk = provider?.getLevelBitmap (level) invalidate ()} 3, A container for like animation

We need to customize a view to store the animation and provide work such as starting the animation and recycling the animation view. The code is as follows:

Class LikeAnimationLayout @ JvmOverloads constructor (context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0): FrameLayout (context, attrs) DefStyleAttr) {private var lastClickTime: Long = 0 private var currentNumber = 1 private var mNumberLevelView: NumberLevelView? = null / * whether there is facial expression or animation is temporarily useless * / private var hasEruptionAnimation = false / * whether hierarchical text is temporarily useless * / private var hasTextAnimation = false / * * can you press it for a long time? Temporarily useless currently using time to manage * / private var canLongPress = false / * maximum and minimum angles are temporarily useless * / private var maxAngle = 0 private var minAngle = 0 private var pointX = 0 private var pointY = 0 var provider: BitmapProvider.Provider? = null get () {if (field = = null) {field = BitmapProvider. Builder (context) .build ()} return field} private fun init (context: Context Attrs: AttributeSet?, defStyleAttr: Int) {val typedArray = context.obtainStyledAttributes (attrs, R.styleable.LikeAnimationLayout, defStyleAttr, 0) maxAngle = typedArray.getInteger (R.styleable.LikeAnimationLayout_max_angle, MAX_ANGLE) minAngle = typedArray.getInteger (R.styleable.LikeAnimationLayout_min_angle MIN_ANGLE) hasEruptionAnimation = typedArray.getBoolean (R.styleable.LikeAnimationLayout_show_emoji, true) hasTextAnimation = typedArray.getBoolean (R.styleable.LikeAnimationLayout_show_text, true) typedArray.recycle ()} / * Click emoticon view * / private fun addEmojiView (context: Context?, x: Int Y: Int) {for (I in 0.. ERUPTION_ELEMENT_AMOUNT) {val layoutParams = RelativeLayout.LayoutParams (ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) layoutParams.setMargins (x, y, 0,0) val articleThumb = context?.let {EmojiAnimationView (it) Provider)} articleThumb?.let {it.setEmoji () this.addView (it,-1 LayoutParams) it.setAnimatorListener (object: EmojiAnimationView.AnimatorListener {override fun onAnimationEmojiEnd () {removeView (it) val handler = Handler () handler.postDelayed ({if (mNumberLevelView! = null & & System.currentTimeMillis ()-lastClickTime > = SPACING _ TIME) {removeView (mNumberLevelView) mNumberLevelView = null}} SPACING_TIME)}}) it.setEmojiAnimation ()}} / * enable animation * / fun launch (x: Int Y: Int) {if (System.currentTimeMillis ()-lastClickTime > = SPACING_TIME) {pointX = x pointY = y / / single click addEmojiView (context, x YMQ 50) lastClickTime = System.currentTimeMillis () currentNumber = 1 if (mNumberLevelView! = null) {removeView (mNumberLevelView) mNumberLevelView = null}} else {/ / Click if (pointX! = x | | pointY! = y) {return} LastClickTime = System.currentTimeMillis () Log.i (TAG "current animation in progress") addEmojiView (context, x, y) / / add digital chain click view val layoutParams = RelativeLayout.LayoutParams (ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) layoutParams.setMargins (0, y-PublicMethod.dp2px (context, 60f), 0 0) if (mNumberLevelView = = null) {mNumberLevelView = NumberLevelView (context,provider,x) addView (mNumberLevelView, layoutParams)} currentNumber++ mNumberLevelView?.setNumber (currentNumber)}} companion object {private const val TAG = "LikeAnimationLayout" / * number of single pop-ups in facial animation If you have different requirements in the future, you can configure * / private const val ERUPTION_ELEMENT_AMOUNT = 8 private const val MAX_ANGLE = 180 private const val MIN_ANGLE = 70 private const val SPACING_TIME = 400L} init {init (context, attrs, defStyleAttr)}}

Note: be sure to clear view after the animation is complete.

4. Start the animation

The gesture callback of the like control. The pseudo code is as follows:

Holder.likeView.setOnFingerDowningListener (object: OnFingerDowningListener {/ * long-press callback * / override fun onLongPress (v: View) {if (! bean.hasLike) {/ / unliked if (! fistLongPress) {/ / synchronous like API and other data interaction bean.likeNumber++ bean here .hasLike = true setLikeStatus (holder Bean)} / / display animation onLikeAnimationListener?.doLikeAnimation (v)} else {if (System.currentTimeMillis ()-lastClickTime throttleTime | | lastClickTime = = 0L) {if (! bean.hasLike) {/ / without likes Like API and data interactive processing bean.hasLike = true bean.likeNumber++ setLikeStatus (holder, bean) throttleTime = 1000 onLikeAnimationListener?.doLikeAnimation (v)} else {/ / like status Cancel the like API and data interactive processing bean.hasLike = false bean.likeNumber-- setLikeStatus (holder, bean) throttleTime = 30}} else if (lastClickTime! = 0L & & bean.hasLike) {/ / within the time range, click to like continuously Show animation onLikeAnimationListener?.doLikeAnimation (v)} lastClickTime = System.currentTimeMillis ()}})

Initialize animation resources when displaying the animation page initialization work:

Override fun onCreate (savedInstanceState: Bundle?) {super.onCreate (savedInstanceState) setContentView (R.layout.activity_list) likeAnimationLayout?.provider = BitmapProviderFactory.getProvider (this)}

Start the animation in a callback that displays the animation:

Override fun doLikeAnimation (v: View) {val itemPosition = IntArray (2) val superLikePosition = IntArray (2) v.getLocationOnScreen (itemPosition) likeAnimationLayout?.getLocationOnScreen (superLikePosition) val x = itemPosition [0] + v.width / 2 val y = itemPosition [1]-superLikePosition [1] + v.height / 2 likeAnimationLayout?.launch (x, y)} IV. Problems encountered

Because the SmartRefreshLayout drop-down refresh control is used in the flow list, if you animate the like in the first few items of the list, when the finger moves, the touch event will be blocked by SmartRefreshLayout to perform the drop-down refresh, then the like control will always be animated when the finger is raised. The solution you can think of now is to check whether the parent layout has SmartRefreshLayout when the finger is pressed, and to disable the drop-down refresh function through reflection. Lift the finger or cancel the reset operation. The code is as follows:

Override fun dispatchTouchEvent (event: MotionEvent?): Boolean {parent?.requestDisallowInterceptTouchEvent (true) return super.dispatchTouchEvent (event)} override fun onTouchEvent (event: MotionEvent): Boolean {var onTouch: Boolean when (event.action) {MotionEvent.ACTION_DOWN-> {isRefreshing = false isDowning = true / / Click lastDownTime = System.currentTimeMillis () findSmartRefreshLayout (false) If (isRefreshing) {/ / if there is a drop-down control and is refreshing, it does not respond directly to return false} postDelayed (autoPollTask) CLICK_INTERVAL_TIME) onTouch = true} MotionEvent.ACTION_UP-> {isDowning = false / / lift if (System.currentTimeMillis ()-lastDownTime

< CLICK_INTERVAL_TIME) { //小于间隔时间按照单击处理 onFingerDowningListener?.onDown(this) } else { //大于等于间隔时间按照长按抬起手指处理 onFingerDowningListener?.onUp() } findSmartRefreshLayout(true) removeCallbacks(autoPollTask) onTouch = true } MotionEvent.ACTION_CANCEL ->

{isDowning = false findSmartRefreshLayout (true) removeCallbacks (autoPollTask) onTouch = false} else-> onTouch = false} return onTouch} / * if the parent layout has SmartRefreshLayout controls Sets whether the control is available * / private fun findSmartRefreshLayout (enable: Boolean) {var parent = parent while (parent! = null & & parent! is ContentFrameLayout) {if (parent is SmartRefreshLayout) {isRefreshing = parent.state = = RefreshState.Refreshing if (isRefreshing) {/ / if there is a drop-down control and is refreshing to end break directly } if (! enable & & firstClick) {try {firstClick = falseval field: Field = parent.javaClass.getDeclaredField ("mEnableRefresh") field.isAccessible = true / / get the initial value enableRefresh = field.getBoolean (parent) of whether the refresh can be pulled down first by reflection. } catch (e: Exception) {e.printStackTrace ()}} if (enableRefresh) {/ / if the initial value cannot be refreshed below, do not set the drop-down refresh status parent.setEnableRefresh (enable)} parent.setEnableLoadMore (enable) break} else {parent = parent.parent}} 5. Realize the effect

These are all the contents of the article "how to achieve like Animation in Android". Thank you for reading! I believe you will gain a lot after reading this article. The editor will update different knowledge for you every day. If you want to learn more knowledge, please pay attention to the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report