仿抖音APP視頻切換和點贊效果

android.png

1棉浸、ViewPager2

網上很多仿抖音視頻切換的很多都是使用自定義豎方向的ViewPager或者使用RecyclerView+PagerSnapHelper實現(xiàn)侥猩。
但是這兩種方式其實都有一定的缺陷:

1、但是ViewPager實現(xiàn)镀迂,生命周期有一定問題(ps:FragmentPagerAdapter在新版本中提供了BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT來解決這個問題)圈匆,notifyDataSetChanged支持很不好邻吭。關于生命周期的更新可以參考androidx中的Fragment懶加載方案

2、而使用RecyclerView+PagerSnapHelper實現(xiàn)焕檬,需要自己處理生命周期姆坚。

其實我們可以使用androidx中提供的ViewPage2來實現(xiàn)這個功能。

dependencies {
    implementation "androidx.viewpager2:viewpager2:1.0.0"
}

查看源碼实愚,ViewPager2繼承自ViewGroup兼呵,其中發(fā)現(xiàn)了三個比較重要的成員變量:

private LinearLayoutManager mLayoutManager;
RecyclerView mRecyclerView;
private PagerSnapHelper mPagerSnapHelper;

明眼人一看就知道了兔辅,ViewPager2的核心實現(xiàn)就是RecyclerView+LinearLayoutManager+PagerSnapHelper了,因為LinearLayoutManager本身就支持豎向和橫向兩種布局方式萍程,所以ViewPager2也能很容易地支持這兩種滾動方向了幢妄,而幾乎不需要添加任何多余的代碼。

使用上和老的ViewPager基本沒啥卻別茫负,下面ViewPager2的幾個新東西:

  • 支持RTL布局
  • 支持豎向滾動
  • 完整支持notifyDataSetChanged
  • FragmentStateAdapter替換了原來的 FragmentStatePagerAdapter
  • RecyclerView.Adapter替換了原來的 PagerAdapter
  • registerOnPageChangeCallback替換了原來的 addPageChangeListener
  • public void setUserInputEnabled(boolean enabled)禁止滑動
  • ...

關于更多ViewPager2的資料大家可以自行搜索蕉鸳。

2、視頻播放器

本demo中使用的是GSYVideoPlayer忍法,實際項目中可自行選擇封裝潮尝。demo中沒有對其進行過多的處理,只是為了看效果饿序,實際的抖音中有更多復雜的東西勉失。

3、demo結構

demo結構

看最后實現(xiàn)的效果


視頻切換

點贊原探、視頻控制

4乱凿、無限上滑

借助ViewPager2的監(jiān)聽和adapter的notifyDataSetChanged即可實現(xiàn)

viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
    override fun onPageSelected(position: Int) {
        super.onPageSelected(position)
        if (position==urlList.size-1){
            urlList.add(urlList[0])
            mPagerAdapter.notifyDataSetChanged()
        }
    }
})

5、視頻和作者主頁切換控制

override fun onResume() {
    super.onResume()
    if (mCurrentPosition > 0) {
        videoPlayer?.onVideoResume(false)
    } else {
        videoPlayer?.postDelayed({
            videoPlayer?.startPlayLogic()
        }, 200)
    }
}
override fun onPause() {
    super.onPause()
    likeLayout?.onPause()
    videoPlayer?.onVideoPause()
    mCurrentPosition = videoPlayer?.gsyVideoManager?.currentPosition ?: 0
}

6咽弦、點贊效果

抖音的點贊效果是由右側的桃心點贊和屏幕的點擊構成徒蟆,右側的點擊后為點贊狀態(tài)并有點贊動畫,再次點擊取消點贊型型。

先來看看效果:


點贊

此處我們觀察效果基本和此前用過的一個三方庫比較相似段审,此處就先又此代替,后面有時間再進行完善闹蒜。
該庫為Like Button,使用方式很簡單寺枉,如下:

<com.github.like.LikeButton
    android:id="@+id/likeBtn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true"
    app:icon_size="40dp"
    app:icon_type="heart"
    app:like_drawable="@mipmap/ic_heart_on"
    app:unlike_drawable="@mipmap/ic_heart_off" />

LikeButton具有以下屬性,使用時可自行去查看

<com.github.like.LikeButton
    app:icon_type="Star"
    app:circle_start_color="@color/colorPrimary"
    app:like_drawable="@drawable/thumb_on"
    app:unlike_drawable="@drawable/thumb_off"
    app:dots_primary_color="@color/colorAccent"
    app:dots_secondary_color="@color/colorPrimary"
    app:circle_end_color="@color/colorAccent"
    app:icon_size="25dp"
    app:liked="true"
    app:anim_scale_factor="2"
    app:is_enabled="false"/>

設置LikeButton的監(jiān)聽事件:

likeBtn.setOnLikeListener(object : OnLikeListener {
    override fun liked(p0: LikeButton?) {
        toast("已點贊~~")
    }

    override fun unLiked(p0: LikeButton?) {
        toast("取消點贊~~")
    }

})

我們可以看一下點贊按鈕的點贊效果


點贊

7、屏幕點贊

分析抖音的屏幕點贊由幾個部分組合而成(紅心可自繪绷落,也可以直接使用圖片)

  • 1姥闪、剛開始顯示的時候,有個由大到小縮放動畫
  • 2砌烁、透明度變化
  • 3甘畅、向上平移
  • 4、由小到大的縮放
  • 5往弓、剛開始顯示的時候有個小小的偏移疏唾,避免每個紅心在同一個位置

8、實現(xiàn)過程

獲取紅心

private var icon: Drawable = resources.getDrawable(R.mipmap.ic_heart)

監(jiān)聽Touch事件函似,并在按下位置添加View

override fun onTouchEvent(event: MotionEvent?): Boolean {
    if (event?.action == MotionEvent.ACTION_DOWN) {     //按下時在Layout中生成紅心
        val x = event.x
        val y = event.y
        addHeartView(x, y)
        onLikeListener()
    }
    return super.onTouchEvent(event)
}

為紅心添加一個隨機的偏移(此處為-10~10)

img.scaleType = ImageView.ScaleType.MATRIX
val matrix = Matrix()
matrix.postRotate(getRandomRotate())       //設置紅心的微量偏移

設置一開始的縮放動畫

private fun getShowAnimSet(view: ImageView): AnimatorSet {
    // 縮放動畫
    val scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1.2f, 1f)
    val scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1.2f, 1f)
    val animSet = AnimatorSet()
    animSet.playTogether(scaleX, scaleY)
    animSet.duration = 100
    return animSet
}

設置慢慢消失時的動畫

private fun getHideAnimSet(view: ImageView): AnimatorSet {
    // 1.alpha動畫
    val alpha = ObjectAnimator.ofFloat(view, "alpha", 1f, 0.1f)
    // 2.縮放動畫
    val scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 2f)
    val scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 2f)
    // 3.translation動畫
    val translation = ObjectAnimator.ofFloat(view, "translationY", 0f, -150f)
    val animSet = AnimatorSet()
    animSet.playTogether(alpha, scaleX, scaleY, translation)
    animSet.duration = 500
    return animSet
}

設置動畫關系槐脏,并且在動畫結束后Remove該紅心

val animSet = getShowAnimSet(img)
val hideSet = getHideAnimSet(img)
animSet.start()
animSet.addListener(object : AnimatorListenerAdapter() {
    override fun onAnimationEnd(animation: Animator?) {
        super.onAnimationEnd(animation)
        hideSet.start()
    }
})
hideSet.addListener(object : AnimatorListenerAdapter() {
    override fun onAnimationEnd(animation: Animator?) {
        super.onAnimationEnd(animation)
        removeView(img)     //動畫結束移除紅心
    }
})

區(qū)分單擊和多次點擊,單擊的時候控制視頻的暫停和播放撇寞,多次點擊的時候實現(xiàn)點贊功能

override fun onTouchEvent(event: MotionEvent?): Boolean {
    if (event?.action == MotionEvent.ACTION_DOWN) {     //按下時在Layout中生成紅心
        val x = event.x
        val y = event.y
        mClickCount++
        mHandler.removeCallbacksAndMessages(null)
        if (mClickCount >= 2) {
            addHeartView(x, y)
            onLikeListener()
            mHandler.sendEmptyMessageDelayed(1, 500)
        } else {
            mHandler.sendEmptyMessageDelayed(0, 500)
        }

    }
    return true
}

private fun pauseClick() {
    if (mClickCount == 1) {
        onPauseListener()
    }
    mClickCount = 0
}

fun onPause() {
    mClickCount = 0
    mHandler.removeCallbacksAndMessages(null)
}

完整代碼

只是為了做實驗顿天,代碼寫的比較亂
https://github.com/leiyun1993/DouYinLike

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末堂氯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子牌废,更是在濱河造成了極大的恐慌咽白,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸟缕,死亡現(xiàn)場離奇詭異晶框,居然都是意外死亡,警方通過查閱死者的電腦和手機懂从,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門授段,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人番甩,你說我怎么就攤上這事侵贵。” “怎么了缘薛?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵窍育,是天一觀的道長。 經常有香客問我宴胧,道長蔫骂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任牺汤,我火速辦了婚禮,結果婚禮上浩嫌,老公的妹妹穿的比我還像新娘檐迟。我一直安慰自己,他們只是感情好码耐,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布追迟。 她就那樣靜靜地躺著,像睡著了一般骚腥。 火紅的嫁衣襯著肌膚如雪敦间。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天束铭,我揣著相機與錄音廓块,去河邊找鬼。 笑死契沫,一個胖子當著我的面吹牛带猴,可吹牛的內容都是我干的。 我是一名探鬼主播懈万,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼拴清,長吁一口氣:“原來是場噩夢啊……” “哼靶病!你這毒婦竟也來了?” 一聲冷哼從身側響起口予,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤娄周,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后沪停,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體煤辨,經...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年牙甫,在試婚紗的時候發(fā)現(xiàn)自己被綠了掷酗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡窟哺,死狀恐怖泻轰,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情且轨,我是刑警寧澤浮声,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站旋奢,受9級特大地震影響泳挥,放射性物質發(fā)生泄漏。R本人自食惡果不足惜至朗,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一屉符、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锹引,春花似錦矗钟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至腾啥,卻和暖如春东涡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背倘待。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工疮跑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凸舵。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓祸挪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贞间。 傳聞我的和親對象是個殘疾皇子贿条,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內容