您好,登錄后才能下訂單哦!
今天小編給大家分享一下Android怎么實現(xiàn)點贊動畫效果的相關(guān)知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
對接下來功能實現(xiàn)的探索。
仔細觀察點贊交互,看出大概以下幾個步驟:
1:點贊控件需要自定義,對其觸摸事件進行處理。
2:點贊動畫的實現(xiàn)。
3:要有一個存放動畫的容器。
點贊控件是區(qū)分長按和點擊處理的,另外我們發(fā)現(xiàn)在手指按下以后包括手指的移動直到手指的抬起都在執(zhí)行動畫。因為點贊的點擊區(qū)域可能包括點贊次數(shù),所以這里就自定義了點贊控件,并處理onTouchEvent(event: MotionEvent)
事件,區(qū)分長按和單擊是使用了點擊到手指抬起的間隔時間區(qū)分的,偽代碼如下:
override fun onTouchEvent(event: MotionEvent): Boolean { var onTouch: Boolean when (event.action) { MotionEvent.ACTION_DOWN -> { isRefreshing = false isDowning = true //點擊 lastDownTime = System.currentTimeMillis() postDelayed(autoPollTask, CLICK_INTERVAL_TIME) onTouch = true } MotionEvent.ACTION_UP -> { isDowning = false //抬起 if (System.currentTimeMillis() - lastDownTime < CLICK_INTERVAL_TIME) { //小于間隔時間按照單擊處理 onFingerDowningListener?.onDown(this) } else { //大于等于間隔時間按照長按抬起手指處理 onFingerDowningListener?.onUp() } removeCallbacks(autoPollTask) onTouch = true } MotionEvent.ACTION_CANCEL ->{ isDowning = false removeCallbacks(autoPollTask) onTouch = false } else -> onTouch = false } return onTouch }
長按時使用Runnable的postDelayed(Runnable action, long delayMillis)
方法來進行不斷的執(zhí)行動畫,偽代碼:
private inner class AutoPollTask : Runnable { override fun run() { onFingerDowningListener?.onLongPress(this@LikeView) if(!canLongPress){ removeCallbacks(autoPollTask) }else{ postDelayed(autoPollTask, CLICK_INTERVAL_TIME) } } }
點贊效果元素分為:點贊表情圖標(biāo)、點贊次數(shù)數(shù)字以及點贊文案
這里參考了SuperLike的做法,對圖片進行了緩存處理,代碼如下:
object BitmapProviderFactory { fun getProvider(context: Context): BitmapProvider.Provider { return BitmapProvider.Builder(context) .setDrawableArray( intArrayOf( R.mipmap.emoji_1, R.mipmap.emoji_2, R.mipmap.emoji_3, R.mipmap.emoji_4, R.mipmap.emoji_5, R.mipmap.emoji_6, R.mipmap.emoji_7, R.mipmap.emoji_8, R.mipmap.emoji_9, R.mipmap.emoji_10, R.mipmap.emoji_11, R.mipmap.emoji_12, R.mipmap.emoji_13, R.mipmap.emoji_14 ) ) .setNumberDrawableArray( intArrayOf( R.mipmap.multi_digg_num_0, R.mipmap.multi_digg_num_1, R.mipmap.multi_digg_num_2, R.mipmap.multi_digg_num_3, R.mipmap.multi_digg_num_4, R.mipmap.multi_digg_num_5, R.mipmap.multi_digg_num_6, R.mipmap.multi_digg_num_7, R.mipmap.multi_digg_num_8, R.mipmap.multi_digg_num_9 ) ) .setLevelDrawableArray( intArrayOf( R.mipmap.multi_digg_word_level_1, R.mipmap.multi_digg_word_level_2, R.mipmap.multi_digg_word_level_3 ) ) .build() } }
object BitmapProvider { class Default( private val context: Context, cacheSize: Int, @DrawableRes private val drawableArray: IntArray, @DrawableRes private val numberDrawableArray: IntArray?, @DrawableRes private val levelDrawableArray: IntArray?, private val levelStringArray: Array<String>?, private val textSize: Float ) : Provider { private val bitmapLruCache: LruCache<Int, Bitmap> = LruCache(cacheSize) private val NUMBER_PREFIX = 0x70000000 private val LEVEL_PREFIX = -0x80000000 /** * 獲取數(shù)字圖片 * @param number * @return */ override fun getNumberBitmap(number: Int): Bitmap? { var bitmap: Bitmap? if (numberDrawableArray != null && numberDrawableArray.isNotEmpty()) { val index = number % numberDrawableArray.size bitmap = bitmapLruCache[NUMBER_PREFIX or numberDrawableArray[index]] if (bitmap == null) { bitmap = BitmapFactory.decodeResource(context.resources, numberDrawableArray[index]) bitmapLruCache.put(NUMBER_PREFIX or numberDrawableArray[index], bitmap) } } else { bitmap = bitmapLruCache[NUMBER_PREFIX or number] if (bitmap == null) { bitmap = createBitmapByText(textSize, number.toString()) bitmapLruCache.put(NUMBER_PREFIX or number, bitmap) } } return bitmap } /** * 獲取等級文案圖片 * @param level * @return */ override fun getLevelBitmap(level: Int): Bitmap? { var bitmap: Bitmap? if (levelDrawableArray != null && levelDrawableArray.isNotEmpty()) { val index = level.coerceAtMost(levelDrawableArray.size) bitmap = bitmapLruCache[LEVEL_PREFIX or levelDrawableArray[index]] if (bitmap == null) { bitmap = BitmapFactory.decodeResource(context.resources, levelDrawableArray[index]) bitmapLruCache.put(LEVEL_PREFIX or levelDrawableArray[index], bitmap) } } else { bitmap = bitmapLruCache[LEVEL_PREFIX or level] if (bitmap == null && !levelStringArray.isNullOrEmpty()) { val index = level.coerceAtMost(levelStringArray.size) bitmap = createBitmapByText(textSize, levelStringArray[index]) bitmapLruCache.put(LEVEL_PREFIX or level, bitmap) } } return bitmap } /** * 獲取隨機表情圖片 * @return */ override val randomBitmap: Bitmap get() { val index = (Math.random() * drawableArray.size).toInt() var bitmap = bitmapLruCache[drawableArray[index]] if (bitmap == null) { bitmap = BitmapFactory.decodeResource(context.resources, drawableArray[index]) bitmapLruCache.put(drawableArray[index], bitmap) } return bitmap } private fun createBitmapByText(textSize: Float, text: String): Bitmap { val textPaint = TextPaint() textPaint.color = Color.BLACK textPaint.textSize = textSize val bitmap = Bitmap.createBitmap( textPaint.measureText(text).toInt(), textSize.toInt(), Bitmap.Config.ARGB_4444 ) val canvas = Canvas(bitmap) canvas.drawColor(Color.TRANSPARENT) canvas.drawText(text, 0f, textSize, textPaint) return bitmap } } class Builder(var context: Context) { private var cacheSize = 0 @DrawableRes private var drawableArray: IntArray? = null @DrawableRes private var numberDrawableArray: IntArray? = null @DrawableRes private var levelDrawableArray: IntArray? = null private var levelStringArray: Array<String>? = null private var textSize = 0f fun setCacheSize(cacheSize: Int): Builder { this.cacheSize = cacheSize return this } /** * 設(shè)置表情圖片 * @param drawableArray * @return */ fun setDrawableArray(@DrawableRes drawableArray: IntArray?): Builder { this.drawableArray = drawableArray return this } /** * 設(shè)置數(shù)字圖片 * @param numberDrawableArray * @return */ fun setNumberDrawableArray(@DrawableRes numberDrawableArray: IntArray): Builder { this.numberDrawableArray = numberDrawableArray return this } /** * 設(shè)置等級文案圖片 * @param levelDrawableArray * @return */ fun setLevelDrawableArray(@DrawableRes levelDrawableArray: IntArray?): Builder { this.levelDrawableArray = levelDrawableArray return this } fun setLevelStringArray(levelStringArray: Array<String>?): Builder { this.levelStringArray = levelStringArray return this } fun setTextSize(textSize: Float): Builder { this.textSize = textSize return this } fun build(): Provider { if (cacheSize == 0) { cacheSize = 32 } if (drawableArray == null || drawableArray?.isEmpty() == true) { drawableArray = intArrayOf(R.mipmap.emoji_1) } if (levelDrawableArray == null && levelStringArray.isNullOrEmpty()) { levelStringArray = arrayOf("次贊!", "太棒了!!", "超贊同!!!") } return Default( context, cacheSize, drawableArray!!, numberDrawableArray, levelDrawableArray, levelStringArray, textSize ) } } interface Provider { /** * 獲取隨機表情圖片 */ val randomBitmap: Bitmap /** * 獲取數(shù)字圖片 * [number] 點擊次數(shù) */ fun getNumberBitmap(number: Int): Bitmap? /** * 獲取等級文案圖片 * [level] 等級 */ fun getLevelBitmap(level: Int): Bitmap? } }
這里的實現(xiàn)參考了toutiaothumb,表情圖標(biāo)的動畫大致分為:上升動畫的同時執(zhí)行圖標(biāo)大小變化動畫和圖標(biāo)透明度變化,在上升動畫完成時進行下降動畫。代碼如下:
class EmojiAnimationView @JvmOverloads constructor( context: Context, private val provider: BitmapProvider.Provider?, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { private var mThumbImage: Bitmap? = null private var mBitmapPaint: Paint? = null private var mAnimatorListener: AnimatorListener? = null /** * 表情圖標(biāo)的寬度 */ private var emojiWith = 0 /** * 表情圖標(biāo)的高度 */ private var emojiHeight = 0 private fun init() { //初始化圖片,取出隨機圖標(biāo) mThumbImage = provider?.randomBitmap } init { //初始化paint mBitmapPaint = Paint() mBitmapPaint?.isAntiAlias = true } /** * 設(shè)置動畫 */ private fun showAnimation() { val imageWidth = mThumbImage?.width ?:0 val imageHeight = mThumbImage?.height ?:0 val topX = -1080 + (1400 * Math.random()).toFloat() val topY = -300 + (-700 * Math.random()).toFloat() //上升動畫 val translateAnimationX = ObjectAnimator.ofFloat(this, "translationX", 0f, topX) translateAnimationX.duration = DURATION.toLong() translateAnimationX.interpolator = LinearInterpolator() val translateAnimationY = ObjectAnimator.ofFloat(this, "translationY", 0f, topY) translateAnimationY.duration = DURATION.toLong() translateAnimationY.interpolator = DecelerateInterpolator() //表情圖片的大小變化 val translateAnimationRightLength = ObjectAnimator.ofInt( this, "emojiWith", 0,imageWidth,imageWidth,imageWidth,imageWidth, imageWidth, imageWidth, imageWidth, imageWidth, imageWidth ) translateAnimationRightLength.duration = DURATION.toLong() val translateAnimationBottomLength = ObjectAnimator.ofInt( this, "emojiHeight", 0,imageHeight,imageHeight,imageHeight,imageHeight,imageHeight, imageHeight, imageHeight, imageHeight, imageHeight ) translateAnimationBottomLength.duration = DURATION.toLong() translateAnimationRightLength.addUpdateListener { invalidate() } //透明度變化 val alphaAnimation = ObjectAnimator.ofFloat( this, "alpha", 0.8f, 1.0f, 1.0f, 1.0f, 0.9f, 0.8f, 0.8f, 0.7f, 0.6f, 0f ) alphaAnimation.duration = DURATION.toLong() //動畫集合 val animatorSet = AnimatorSet() animatorSet.play(translateAnimationX).with(translateAnimationY) .with(translateAnimationRightLength).with(translateAnimationBottomLength) .with(alphaAnimation) //下降動畫 val translateAnimationXDown = ObjectAnimator.ofFloat(this, "translationX", topX, topX * 1.2f) translateAnimationXDown.duration = (DURATION / 5).toLong() translateAnimationXDown.interpolator = LinearInterpolator() val translateAnimationYDown = ObjectAnimator.ofFloat(this, "translationY", topY, topY * 0.8f) translateAnimationYDown.duration = (DURATION / 5).toLong() translateAnimationYDown.interpolator = AccelerateInterpolator() //設(shè)置動畫播放順序 val animatorSetDown = AnimatorSet() animatorSet.start() animatorSet.addListener(object : Animator.AnimatorListener { override fun onAnimationStart(animation: Animator) {} override fun onAnimationEnd(animation: Animator) { animatorSetDown.play(translateAnimationXDown).with(translateAnimationYDown) animatorSetDown.start() } override fun onAnimationCancel(animation: Animator) {} override fun onAnimationRepeat(animation: Animator) {} }) animatorSetDown.addListener(object : Animator.AnimatorListener { override fun onAnimationStart(animation: Animator) {} override fun onAnimationEnd(animation: Animator) { //動畫完成后通知移除動畫view mAnimatorListener?.onAnimationEmojiEnd() } override fun onAnimationCancel(animation: Animator) {} override fun onAnimationRepeat(animation: Animator) {} }) } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) drawEmojiImage(canvas) } /** * 繪制表情圖片 */ private fun drawEmojiImage(canvas: Canvas) { mThumbImage?.let{ val dst = Rect() dst.left = 0 dst.top = 0 dst.right = emojiWith dst.bottom = emojiHeight canvas.drawBitmap(it, null, dst, mBitmapPaint) } } /** * 這些get\set方法用于表情圖標(biāo)的大小動畫 * 不能刪除 */ fun getEmojiWith(): Int { return emojiWith } fun setEmojiWith(emojiWith: Int) { this.emojiWith = emojiWith } fun getEmojiHeight(): Int { return emojiHeight } fun setEmojiHeight(emojiHeight: Int) { this.emojiHeight = emojiHeight } fun setEmojiAnimation() { showAnimation() } fun setAnimatorListener(animatorListener: AnimatorListener?) { mAnimatorListener = animatorListener } interface AnimatorListener { /** * 動畫結(jié)束 */ fun onAnimationEmojiEnd() } fun setEmoji() { init() } companion object { //動畫時長 const val DURATION = 500 } }
這里的點贊次數(shù)處理了從1到999,并在不同的點贊次數(shù)區(qū)間顯示不同的點贊文案。代碼如下:
class NumberLevelView @JvmOverloads constructor( context: Context, private val provider: BitmapProvider.Provider?, private val x: Int, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { private var textPaint: Paint = Paint() /** * 點擊次數(shù) */ private var mNumber = 0 /** * 等級文案圖片 */ private var bitmapTalk: Bitmap? = null /** * 等級 */ private var level = 0 /** * 數(shù)字圖片寬度 */ private var numberImageWidth = 0 /** * 數(shù)字圖片的總寬度 */ private var offsetX = 0 /** * x 初始位置 */ private var initialValue = 0 /** * 默認數(shù)字和等級文案圖片間距 */ private var spacing = 0 init { textPaint.isAntiAlias = true initialValue = x - PublicMethod.dp2px(context, 120f) numberImageWidth = provider?.getNumberBitmap(1)?.width ?: 0 spacing = PublicMethod.dp2px(context, 10f) } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) val levelBitmap = provider?.getLevelBitmap(level) ?: return //等級圖片的寬度 val levelBitmapWidth = levelBitmap.width val dst = Rect() when (mNumber) { in 0..9 -> { initialValue = x - levelBitmapWidth dst.left = initialValue dst.right = initialValue + levelBitmapWidth } in 10..99 -> { initialValue = x - PublicMethod.dp2px(context, 100f) dst.left = initialValue + numberImageWidth + spacing dst.right = initialValue+ numberImageWidth + spacing+ levelBitmapWidth } else -> { initialValue = x - PublicMethod.dp2px(context, 120f) dst.left = initialValue + 2*numberImageWidth + spacing dst.right = initialValue+ 2*numberImageWidth + spacing + levelBitmapWidth } } dst.top = 0 dst.bottom = levelBitmap.height //繪制等級文案圖標(biāo) canvas.drawBitmap(levelBitmap, null, dst, textPaint) while (mNumber > 0) { val number = mNumber % 10 val bitmap = provider.getNumberBitmap(number)?:continue offsetX += bitmap.width //這里是數(shù)字 val rect = Rect() rect.top = 0 when { mNumber/ 10 < 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 //繪制數(shù)字 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 } } //根據(jù)等級取出等級文案圖標(biāo) bitmapTalk = provider?.getLevelBitmap(level) invalidate() } }
我們需要自定義一個view來存放動畫,以及提供開始動畫以及回收動畫view等工作。代碼如下:
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 /** * 有無表情動畫 暫時無用 */ private var hasEruptionAnimation = false /** * 有無等級文字 暫時無用 */ private var hasTextAnimation = false /** * 是否可以長按,暫時無用 目前用時間來管理 */ private var canLongPress = false /** * 最大和最小角度暫時無用 */ 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() } /** * 點擊表情動畫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() } } } /** * 開啟動畫 */ fun launch(x: Int, y: Int) { if (System.currentTimeMillis() - lastClickTime >= SPACING_TIME) { pointX = x pointY = y //單次點擊 addEmojiView(context, x, y-50) lastClickTime = System.currentTimeMillis() currentNumber = 1 if (mNumberLevelView != null) { removeView(mNumberLevelView) mNumberLevelView = null } } else { //連續(xù)點擊 if (pointX != x || pointY != y){ return } lastClickTime = System.currentTimeMillis() Log.i(TAG, "當(dāng)前動畫化正在執(zhí)行") addEmojiView(context, x, y) //添加數(shù)字連擊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" /** * 表情動畫單次彈出個數(shù),以后如果有不同需求可以改為配置 */ 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) } }
注意:動畫完成之后一定要清除view。
點贊控件的手勢回調(diào),偽代碼如下:
holder.likeView.setOnFingerDowningListener(object : OnFingerDowningListener { /** * 長按回調(diào) */ override fun onLongPress(v: View) { if (!bean.hasLike) { //未點贊 if (!fistLongPress) { //這里同步點贊接口等數(shù)據(jù)交互 bean.likeNumber++ bean.hasLike = true setLikeStatus(holder, bean) } //顯示動畫 onLikeAnimationListener?.doLikeAnimation(v) } else { if (System.currentTimeMillis() - lastClickTime <= throttleTime && lastClickTime != 0L) { //處理點擊過后為點贊狀態(tài)的情況 onLikeAnimationListener?.doLikeAnimation(v) lastClickTime = System.currentTimeMillis() } else { //處理長按為點贊狀態(tài)后的情況 onLikeAnimationListener?.doLikeAnimation(v) } } fistLongPress = true } /** * 長按抬起手指回調(diào)處理 */ override fun onUp() { fistLongPress = false } /** * 單擊事件回調(diào) */ override fun onDown(v: View) { if (System.currentTimeMillis() - lastClickTime > throttleTime || lastClickTime == 0L) { if (!bean.hasLike) { //未點贊情況下,點贊接口和數(shù)據(jù)交互處理 bean.hasLike = true bean.likeNumber++ setLikeStatus(holder, bean) throttleTime = 1000 onLikeAnimationListener?.doLikeAnimation(v) } else { //點贊狀態(tài)下,取消點贊接口和數(shù)據(jù)交互處理 bean.hasLike = false bean.likeNumber-- setLikeStatus(holder, bean) throttleTime = 30 } } else if (lastClickTime != 0L && bean.hasLike) { //在時間范圍內(nèi),連續(xù)點擊點贊,顯示動畫 onLikeAnimationListener?.doLikeAnimation(v) } lastClickTime = System.currentTimeMillis() } })
在顯示動畫頁面初始化工作時初始化動畫資源:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_list) likeAnimationLayout?.provider = BitmapProviderFactory.getProvider(this) }
在顯示動畫的回調(diào)中啟動動畫:
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) }
因為流列表中使用了SmartRefreshLayout下拉刷新控件,如果在列表前幾條內(nèi)容進行點贊動畫當(dāng)手指移動時觸摸事件會被SmartRefreshLayout攔截去執(zhí)行下拉刷新,那么手指抬起時點贊控件得不到響應(yīng)會一直進行動畫操作,目前想到的解決方案是點贊控件在手指按下時查看父布局有無SmartRefreshLayout,如果有通過反射先禁掉下拉刷新功能,手指抬起或者取消進行重置操作。代碼如下:
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 //點擊 lastDownTime = System.currentTimeMillis() findSmartRefreshLayout(false) if (isRefreshing) { //如果有下拉控件并且正在刷新直接不響應(yīng) return false } postDelayed(autoPollTask, CLICK_INTERVAL_TIME) onTouch = true } MotionEvent.ACTION_UP -> { isDowning = false //抬起 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 } /** * 如果父布局有SmartRefreshLayout 控件,設(shè)置控件是否可用 */ 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){ //如果有下拉控件并且正在刷新直接結(jié)束 break } if (!enable && firstClick){ try { firstClick = false val field: Field = parent.javaClass.getDeclaredField("mEnableRefresh") field.isAccessible = true //通過反射獲取是否可以先下拉刷新的初始值 enableRefresh = field.getBoolean(parent) }catch (e: Exception) { e.printStackTrace() } } if (enableRefresh){ //如果初始值不可以下拉刷新不要設(shè)置下拉刷新狀態(tài) parent.setEnableRefresh(enable) } parent.setEnableLoadMore(enable) break } else { parent = parent.parent } } }
以上就是“Android怎么實現(xiàn)點贊動畫效果”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。