您好,登錄后才能下訂單哦!
今天小編給大家分享一下Android怎么實現點贊動畫效果的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
對接下來功能實現的探索。
仔細觀察點贊交互,看出大概以下幾個步驟:
1:點贊控件需要自定義,對其觸摸事件進行處理。
2:點贊動畫的實現。
3:要有一個存放動畫的容器。
點贊控件是區分長按和點擊處理的,另外我們發現在手指按下以后包括手指的移動直到手指的抬起都在執行動畫。因為點贊的點擊區域可能包括點贊次數,所以這里就自定義了點贊控件,并處理onTouchEvent(event: MotionEvent)
事件,區分長按和單擊是使用了點擊到手指抬起的間隔時間區分的,偽代碼如下:
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)
方法來進行不斷的執行動畫,偽代碼:
private inner class AutoPollTask : Runnable { override fun run() { onFingerDowningListener?.onLongPress(this@LikeView) if(!canLongPress){ removeCallbacks(autoPollTask) }else{ postDelayed(autoPollTask, CLICK_INTERVAL_TIME) } } }
點贊效果元素分為:點贊表情圖標、點贊次數數字以及點贊文案
這里參考了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 /** * 獲取數字圖片 * @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 } /** * 設置表情圖片 * @param drawableArray * @return */ fun setDrawableArray(@DrawableRes drawableArray: IntArray?): Builder { this.drawableArray = drawableArray return this } /** * 設置數字圖片 * @param numberDrawableArray * @return */ fun setNumberDrawableArray(@DrawableRes numberDrawableArray: IntArray): Builder { this.numberDrawableArray = numberDrawableArray return this } /** * 設置等級文案圖片 * @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 /** * 獲取數字圖片 * [number] 點擊次數 */ fun getNumberBitmap(number: Int): Bitmap? /** * 獲取等級文案圖片 * [level] 等級 */ fun getLevelBitmap(level: Int): Bitmap? } }
這里的實現參考了toutiaothumb,表情圖標的動畫大致分為:上升動畫的同時執行圖標大小變化動畫和圖標透明度變化,在上升動畫完成時進行下降動畫。代碼如下:
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 /** * 表情圖標的寬度 */ private var emojiWith = 0 /** * 表情圖標的高度 */ private var emojiHeight = 0 private fun init() { //初始化圖片,取出隨機圖標 mThumbImage = provider?.randomBitmap } init { //初始化paint mBitmapPaint = Paint() mBitmapPaint?.isAntiAlias = true } /** * 設置動畫 */ 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() //設置動畫播放順序 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方法用于表情圖標的大小動畫 * 不能刪除 */ 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 { /** * 動畫結束 */ fun onAnimationEmojiEnd() } fun setEmoji() { init() } companion object { //動畫時長 const val DURATION = 500 } }
這里的點贊次數處理了從1到999,并在不同的點贊次數區間顯示不同的點贊文案。代碼如下:
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() /** * 點擊次數 */ private var mNumber = 0 /** * 等級文案圖片 */ private var bitmapTalk: Bitmap? = null /** * 等級 */ private var level = 0 /** * 數字圖片寬度 */ private var numberImageWidth = 0 /** * 數字圖片的總寬度 */ private var offsetX = 0 /** * x 初始位置 */ private var initialValue = 0 /** * 默認數字和等級文案圖片間距 */ 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 //繪制等級文案圖標 canvas.drawBitmap(levelBitmap, null, dst, textPaint) while (mNumber > 0) { val number = mNumber % 10 val bitmap = provider.getNumberBitmap(number)?:continue offsetX += bitmap.width //這里是數字 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 //繪制數字 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 } } //根據等級取出等級文案圖標 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 { //連續點擊 if (pointX != x || pointY != y){ return } lastClickTime = System.currentTimeMillis() Log.i(TAG, "當前動畫化正在執行") addEmojiView(context, x, y) //添加數字連擊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" /** * 表情動畫單次彈出個數,以后如果有不同需求可以改為配置 */ 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。
點贊控件的手勢回調,偽代碼如下:
holder.likeView.setOnFingerDowningListener(object : OnFingerDowningListener { /** * 長按回調 */ override fun onLongPress(v: View) { if (!bean.hasLike) { //未點贊 if (!fistLongPress) { //這里同步點贊接口等數據交互 bean.likeNumber++ bean.hasLike = true setLikeStatus(holder, bean) } //顯示動畫 onLikeAnimationListener?.doLikeAnimation(v) } else { if (System.currentTimeMillis() - lastClickTime <= throttleTime && lastClickTime != 0L) { //處理點擊過后為點贊狀態的情況 onLikeAnimationListener?.doLikeAnimation(v) lastClickTime = System.currentTimeMillis() } else { //處理長按為點贊狀態后的情況 onLikeAnimationListener?.doLikeAnimation(v) } } fistLongPress = true } /** * 長按抬起手指回調處理 */ override fun onUp() { fistLongPress = false } /** * 單擊事件回調 */ override fun onDown(v: View) { if (System.currentTimeMillis() - lastClickTime > throttleTime || lastClickTime == 0L) { if (!bean.hasLike) { //未點贊情況下,點贊接口和數據交互處理 bean.hasLike = true bean.likeNumber++ setLikeStatus(holder, bean) throttleTime = 1000 onLikeAnimationListener?.doLikeAnimation(v) } else { //點贊狀態下,取消點贊接口和數據交互處理 bean.hasLike = false bean.likeNumber-- setLikeStatus(holder, bean) throttleTime = 30 } } else if (lastClickTime != 0L && bean.hasLike) { //在時間范圍內,連續點擊點贊,顯示動畫 onLikeAnimationListener?.doLikeAnimation(v) } lastClickTime = System.currentTimeMillis() } })
在顯示動畫頁面初始化工作時初始化動畫資源:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_list) likeAnimationLayout?.provider = BitmapProviderFactory.getProvider(this) }
在顯示動畫的回調中啟動動畫:
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下拉刷新控件,如果在列表前幾條內容進行點贊動畫當手指移動時觸摸事件會被SmartRefreshLayout攔截去執行下拉刷新,那么手指抬起時點贊控件得不到響應會一直進行動畫操作,目前想到的解決方案是點贊控件在手指按下時查看父布局有無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) { //如果有下拉控件并且正在刷新直接不響應 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 控件,設置控件是否可用 */ 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){ //如果有下拉控件并且正在刷新直接結束 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){ //如果初始值不可以下拉刷新不要設置下拉刷新狀態 parent.setEnableRefresh(enable) } parent.setEnableLoadMore(enable) break } else { parent = parent.parent } } }
以上就是“Android怎么實現點贊動畫效果”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。