Android 照猫画虎~ 来实现一下皮皮虾的详情页效果

源码 2024-9-3 02:22:40 75 0 来自 中国
前言

封闭、无聊、刷皮皮、详情页、交互式、有意思、实现下
1、分析功能点



  • 下滑关闭详情页
  • 左滑关闭详情页
  • 右滑切换短视频
2、实现思绪

那么即可左滑又可右滑还不辩说的东西是什么
ViewPager
1.jpeg 好!确定详情页父结构使用Viewpager那么咱们只须要思量下滑手势的题目了
3、实现 (不要在意定名、特殊在意检察项目即可满足好奇心?)

XML
<layout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools">    <merge        android:layout_width="match_parent"        android:layout_height="match_parent"        tools:parentTag=".widget.XBBDetailView">        <!-- 状态栏 -->        <com.kasiengao.ksgframe.common.widget.CView            android:id="@+id/status_bar"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:background="@color/black"            tools:layout_height="24dp" />        <!-- ViewPager -->        <androidx.viewpager.widget.ViewPager            android:id="@+id/detail_vp"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_below="@id/status_bar"            androidverScrollMode="never" />        <!-- Back -->        <androidx.appcompat.widget.AppCompatImageView            android:id="@+id/back"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignTop="@id/detail_vp"            android:layout_marginStart="@dimen/view_space"            android:layout_marginTop="12dp"            android:elevation="5dp"            android:src="@drawable/ic_cover_back" />    </merge></layout>class XBBDetailView(context: Context) : RelativeLayout(context) {    private val mBinding: LayoutXbbDetailBinding by lazy {        DataBindingUtil.inflate(            LayoutInflater.from(context), R.layout.layout_xbb_detail, this, true        )    }}- 列表到详情页的过渡动画

皮皮虾仿皮皮虾 3.gif 看得出来是从列表中的视频容器Y坐标为出发点平移到顶部的一个动画效果


  • 获取列表视频容器在屏幕中的坐标getLocationOnScreen
  • 拿到列表视频容器的Y到减去状态栏高度位置做一个平移动画即可
  • 数据源截取聚集subList从点击列表的position到size做一个截取
// 列表截取val subList = mAdapter.data.subList(position, mAdapter.data.size)/** * 打开详情页 * * @param position      列表位置 * @param data          数据源 * @param listContainer 列表容器 */fun openDetail(position: Int, data: List<VideoBean>, listContainerlayerContainerView{    // 添加到View层级下    this.mActivity.findViewById<ViewGroup>(android.R.id.content)?.let {        if (!it.contains(this)) {            it.addView(this)        }    }    // 列表容器坐标    val location = IntArray(2)    this.mListContainer.getLocationOnScreen(location)    // 动画    ObjectAnimator.ofFloat(        mBinding.detailVp, Y,        location[1].toFloat(), mStatusBarHeight.toFloat()    ).let {        it.interpolator = LinearInterpolator()        it.duration = 150        it.start()    }    // Init    this.post {        this.mBinding.detailVp.setCurrentItem(1, false)    }}
留意:setCurrentItem(1, false)ViewPager初始页肯定要设置为第1页,须要预留第0页作为关闭页
看起来是不是so easy来咱接着往下走
- 右滑切换短视频

这里着实就是简朴的ViewPager右滑切换了
皮皮虾仿皮皮虾


  • 但是须要留意的是右滑切换后同时要同步Recycler的Item位置
  • 否则findViewHolderForLayoutPosition会报空指针,
  • 同步Recycler的Item位置是由于在关闭详情页的也须要做过渡动画
override fun onPageSelected(position: Int) {    ...    // 同步列表Item的位置    scrollToPositionWithOffset(getRealListPosition())}override fun onPageScrollStateChanged(state: Int) {    ...    when (state) {        ViewPager.SCROLL_STATE_IDLE -> {               // 同步列表的容器               mListContainer = getItemPlayContainer(getRealListPosition())            }        }    }}/** * 指定Item滑动到顶部 */fun scrollToPositionWithOffset(position: Int) {    (layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position, 0)}/** * 获取Item中的视频容器View */fun getItemPlayContainer(position: Int): PlayerContainerView {     return (findViewHolderForLayoutPosition(position) as XBBAdapter.ViewHolder).mPlayContainer}- 左滑关闭详情页

皮皮虾仿皮皮虾
在上面咱们说到了预留了第0页作为了关闭页,那么很简朴第0页只须要添加一个空View且透明即可,在滑动结束后关闭详情页即可。
override fun onPageSelected(position: Int) {    // 关闭页    if (position == PAGE_FINISH) {        ...        // 切回至旧容器 (原列表容器)        mSignalPlayer.bindContainer(mListContainer, false)        return    }}override fun onPageScrollStateChanged(state: Int) {    when (state) {        ViewPager.SCROLL_STATE_IDLE -> {            ...            // 关闭页            if (currentItem == PAGE_FINISH) {                // Finish                finishDetail()                return            }        }    }}/** * 关闭详情页 */private fun finishDetail() {    // 从View层级中移除    this.mActivity.findViewById<ViewGroup>(android.R.id.content)        ?.removeView(this@XBBDetailView)    ...}左滑关闭逻辑也就结束了、也好坏常的easy哈?
- 下滑关闭详情页

皮皮虾仿皮皮虾 8.gif
这里就比力关键了须要用到变乱分发
起首在详情页可以看到品评列表可上下滑动,那就须要限制在列表顶部的时间才可以下滑关闭
这里须要在父结构中重写onInterceptTouchEvent去判断滑动偏移量与列表是否在顶部逻辑
/** * 变乱分发 */override fun onInterceptTouchEvent(event: MotionEvent): Boolean {    var intercept = false    when (event.action) {        MotionEvent.ACTION_DOWN -> {            this.mDownX = event.x            this.mDownY = event.y        }        MotionEvent.ACTION_MOVE -> {            if ((event.y - mDownY) > 23) {                if (mItemView.getScrollView().isOnTop) {                    intercept = true                }            }        }    }    return intercept}
然后重写onTouchEvent当变乱被拦截时此处会被实行,然后根据 X Y 坐标去设置更新容器即可
override fun onTouchEvent(event: MotionEvent): Boolean {    if (!mItemView.getScrollView().isOnTop) {        return true    }    when (event.action) {        MotionEvent.ACTION_DOWN -> {            this.mDownX = event.x            this.mDownY = event.y        }        MotionEvent.ACTION_UP -> {            ...        }        MotionEvent.ACTION_MOVE -> {            val moveX = event.x - mDownX            this.mMoveY = (event.y - mDownY)            this.mItemView.getPlayerContainer().x = moveX            this.mItemView.getPlayerContainer().y = mMoveY            ...        }    }    return true}
到这里就结束了效果也实现了。
在这里也只是提供个思绪有更好的办法欢迎品评区一起讨论,那下面就直接堆栈地点了感爱好的朋侪么渴望给个Star支持一下?
KsgFrame
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-27 12:12, Processed in 0.170774 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表