仿抖音-視頻及直播點(diǎn)贊效果

先上效果圖

視頻點(diǎn)贊.jpg

直播點(diǎn)贊.jpg

需求梳理

抖音APP中呐馆,視頻的點(diǎn)贊和直播中點(diǎn)贊效果是不同的肥缔,先找尋兩者的共同點(diǎn)提取接口:

類(lèi)型 圖片 動(dòng)畫(huà) 初始旋轉(zhuǎn)角度 Y軸偏移量
視頻點(diǎn)贊 單張紅心 組合動(dòng)畫(huà) 隨機(jī)旋轉(zhuǎn)角度 -50
直播點(diǎn)贊 多張圖片隨機(jī) 組合動(dòng)畫(huà) 無(wú) -20

Y軸偏移量是多次調(diào)試的,看各位同學(xué)需求汹来,都可以調(diào)整续膳。

interface ILikeFollowData {

    /**
     * 獲取圖標(biāo)列表
     */
    fun getIconList(): List<Any>

    /**
     * 獲取圖標(biāo)大小
     */
    fun getIconSize(): Int

    /**
     * 獲取旋轉(zhuǎn)角度范圍
     */
    fun getRotationRange(): IntRange

    /**
     * 獲取Y軸偏移量
     */
    fun getYOffset(): Int

    /**
     * 獲取動(dòng)畫(huà)集合
     */
    fun getAnimatorSet(view: View): AnimatorSet
}

實(shí)現(xiàn)

視頻點(diǎn)贊數(shù)據(jù)類(lèi)

class VideoLikeFollowData : ILikeFollowData {

    private val iconList = arrayListOf<Any>(R.drawable.img_like_follow)

    override fun getIconList() = iconList

    override fun getIconSize() = 240

    override fun getRotationRange() = -30..30

    override fun getYOffset() = -50

    override fun getAnimatorSet(view: View): AnimatorSet {
        val set = AnimatorSet()

        //放大
        set.playSequentially(
            AnimatorSet().apply {
                playTogether(
                    ObjectAnimator.ofFloat(view, "scaleX", 1f, 1.4f).apply {
                        duration = 50
                    },
                    ObjectAnimator.ofFloat(view, "scaleY", 1f, 1.4f).apply {
                        duration = 50
                    },
                )
            },
            //縮小
            AnimatorSet().apply {
                playTogether(
                    ObjectAnimator.ofFloat(view, "scaleX", 1.4f, 1f).apply {
                        duration = 200
                    },
                    ObjectAnimator.ofFloat(view, "scaleY", 1.4f, 1f).apply {
                        duration = 200
                    },
                )
            },
            ValueAnimator.ofInt(0, 100).apply {
                duration = 200
            },
            //縮放/透明并位移
            AnimatorSet().apply {
                playTogether(
                    ObjectAnimator.ofFloat(view, "scaleX", 1f, 1.8f).apply {
                        duration = 500
                    },
                    ObjectAnimator.ofFloat(view, "scaleY", 1f, 1.8f).apply {
                        duration = 500
                    },
                    ObjectAnimator.ofFloat(view, "alpha", 1f, 0f).apply {
                        duration = 500
                    },
                    ObjectAnimator.ofFloat(
                        view,
                        "translationY",
                        view.y,
                        view.y - 300f
                    ).apply {
                        duration = 500
                    },
                )
            })

        return set
    }
}

直播點(diǎn)贊數(shù)據(jù)類(lèi)

class LiveLikeFollowData : ILikeFollowData {

    private val iconList = arrayListOf<Any>(
        R.drawable.img_like_follow_1,
        R.drawable.img_like_follow_2,
        R.drawable.img_like_follow_3,
        R.drawable.img_like_follow_4,
        R.drawable.img_like_follow_5,
        R.drawable.img_like_follow_6,
        R.drawable.img_like_follow_7,
    )

    override fun getIconList() = iconList

    override fun getIconSize() = 100

    override fun getRotationRange() = 0..0

    override fun getYOffset() = -20

    override fun getAnimatorSet(view: View): AnimatorSet {
        val set = AnimatorSet()

        //放大
        set.playSequentially(
            AnimatorSet().apply {
                // 同時(shí)播放
                playTogether(
                    ObjectAnimator.ofFloat(view, "scaleX", 1f, 1.1f).apply {
                        duration = 50
                    },
                    ObjectAnimator.ofFloat(view, "scaleY", 1f, 1.1f).apply {
                        duration = 50
                    },
                    ObjectAnimator.ofFloat(view, "rotation", -20f, -6f).apply {
                        duration = 50
                    }
                )
            },
            //縮小
            AnimatorSet().apply {
                playTogether(
                    ObjectAnimator.ofFloat(view, "scaleX", 1.1f, 1f).apply {
                        duration = 200
                    },
                    ObjectAnimator.ofFloat(view, "scaleY", 1.1f, 1f).apply {
                        duration = 200
                    },
                    ObjectAnimator.ofFloat(view, "rotation", -6f, 4f, 0f).apply {
                        duration = 200
                    }
                )
            },
            ValueAnimator.ofInt(0, 100).apply {
                duration = 200
            },
            //縮放/透明并位移
            AnimatorSet().apply {
                playTogether(
                    ObjectAnimator.ofFloat(view, "scaleX", 1f, 1.8f).apply {
                        duration = 500
                    },
                    ObjectAnimator.ofFloat(view, "scaleY", 1f, 1.8f).apply {
                        duration = 500
                    },
                    ObjectAnimator.ofFloat(view, "alpha", 1f, 0f).apply {
                        duration = 500
                    }
                )
            })

        return set
    }
}

上述代碼中的圖片,各位同學(xué)可以讓UI自行設(shè)計(jì)切圖收班,如果需要坟岔,可以在末尾代碼鏈接處下載獲取。

功能model

object LikeFollowModel {

    //短視頻展示數(shù)據(jù)
    val videoLikeFollowData: ILikeFollowData by lazy {
        VideoLikeFollowData()
    }

    //直播展示數(shù)據(jù)
    val liveLikeFollowData: ILikeFollowData by lazy {
        LiveLikeFollowData()
    }
    
    /**
     * 展示點(diǎn)贊效果
     * @param x: 點(diǎn)擊的x坐標(biāo)
     * @param y: 點(diǎn)擊的y坐標(biāo)
     * @param viewGroup: 父布局
     * @param data: 展示數(shù)據(jù)
     */
    fun show(x: Int, y: Int, viewGroup: ViewGroup, data: ILikeFollowData = videoLikeFollowData) {
        //添加愛(ài)心
        val likeView = AppCompatImageView(viewGroup.context)
        //加載圖片,封裝的Glide方法,同學(xué)可自行處理
        loadImage(likeView, data.getIconList().random())

        val size = data.getIconSize()
        val layoutParams = ViewGroup.LayoutParams(size, size)
        likeView.layoutParams = layoutParams
        //設(shè)置愛(ài)心位置
        likeView.x = (x - (size / 2)).toFloat()
        likeView.y = (y - size + data.getYOffset()).toFloat()
        //設(shè)置隨機(jī)旋轉(zhuǎn)角度
        likeView.rotation = (data.getRotationRange().random()).toFloat()
        viewGroup.addView(likeView)

         //獲取動(dòng)畫(huà)集合
        val animatorSet = data.getAnimatorSet(likeView)
        //添加動(dòng)畫(huà)結(jié)束監(jiān)聽(tīng)
        animatorSet.addListener(onEnd = {
            tryCatch({
                //清理動(dòng)畫(huà)
                likeView.clearAnimation()
                //隱藏圖片
                likeView.visibility = View.GONE
                //移除圖片,延遲500毫秒移除,防止動(dòng)畫(huà)還沒(méi)結(jié)束就移除
                HandlerUtils.postRunnable({
                    viewGroup.removeView(likeView)
                }, 500)
            })
        })
        animatorSet.start()
    }
}

以上四個(gè)類(lèi)就是所有的功能代碼摔桦。

實(shí)現(xiàn)思路還是蠻簡(jiǎn)單的:


實(shí)現(xiàn)思路.jpg

獲取點(diǎn)擊事件坐標(biāo)

避免同學(xué)獲取點(diǎn)擊坐標(biāo)有疑問(wèn)社付,這里再補(bǔ)充上相關(guān)代碼:

    /**
     * 設(shè)置點(diǎn)擊監(jiān)聽(tīng)
     * 返回坐標(biāo)
     */
    @SuppressLint("ClickableViewAccessibility")
    private fun setViewOnClickListener(view: View, clickCallBack: (x: Int, y: Int) -> Unit) {
        var x = 0f
        var y = 0f
        view.setOnTouchListener { _, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    x = event.x
                    y = event.y
                }
                MotionEvent.ACTION_UP -> {
                    if (x == event.x && y == event.y) {
                        clickCallBack(event.x.toInt(), event.y.toInt())
                    }
                }
            }
            true
        }
    }

代碼倉(cāng)庫(kù)

倉(cāng)庫(kù)地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市邻耕,隨后出現(xiàn)的幾起案子鸥咖,更是在濱河造成了極大的恐慌,老刑警劉巖兄世,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啼辣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡御滩,警方通過(guò)查閱死者的電腦和手機(jī)鸥拧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)艾恼,“玉大人住涉,你說(shuō)我怎么就攤上這事∧粕埽” “怎么了舆声?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)柳爽。 經(jīng)常有香客問(wèn)我媳握,道長(zhǎng),這世上最難降的妖魔是什么磷脯? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任蛾找,我火速辦了婚禮,結(jié)果婚禮上赵誓,老公的妹妹穿的比我還像新娘打毛。我一直安慰自己柿赊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布幻枉。 她就那樣靜靜地躺著碰声,像睡著了一般。 火紅的嫁衣襯著肌膚如雪熬甫。 梳的紋絲不亂的頭發(fā)上胰挑,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音椿肩,去河邊找鬼瞻颂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛郑象,可吹牛的內(nèi)容都是我干的贡这。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼扣唱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼藕坯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起噪沙,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤炼彪,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后正歼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體辐马,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年局义,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喜爷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萄唇,死狀恐怖檩帐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情另萤,我是刑警寧澤湃密,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站四敞,受9級(jí)特大地震影響泛源,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜忿危,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一达箍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铺厨,春花似錦缎玫、人聲如沸硬纤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)咬摇。三九已至,卻和暖如春煞躬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逸邦。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工恩沛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缕减。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓雷客,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親桥狡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搅裙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容