Android使用kotlin实现滑动居中效果

Android使用kotlin实现滑动居中效果

1.自定义CenterLayoutManager

import android.content.Context
import android.util.AttributeSet
import android.util.DisplayMetrics
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSmoothScroller
import androidx.recyclerview.widget.RecyclerView

/**
 *@author: njb
 *@date:  2023/1/16 23:36
 *@desc:
 */
class CenterLayoutManager :LinearLayoutManager{
    constructor(context: Context?) : super(context) {}
    constructor(
        context: Context?,
        orientation: Int,
        reverseLayout: Boolean
    ) : super(context, orientation, reverseLayout) {
    }

    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes) {
    }

    override fun smoothScrollToPosition(
        recyclerView: RecyclerView,
        state: RecyclerView.State,
        position: Int
    ) {
        val smoothScroller: RecyclerView.SmoothScroller = CenterSmoothScroller(recyclerView.context)
        smoothScroller.targetPosition = position
        startSmoothScroll(smoothScroller)
    }

    private class CenterSmoothScroller internal constructor(context: Context?) :
        LinearSmoothScroller(context) {
        override fun calculateDtToFit(
            viewStart: Int,
            viewEnd: Int,
            boxStart: Int,
            boxEnd: Int,
            snapPreference: Int
        ): Int {
            return boxStart + (boxEnd - boxStart) / 2 - (viewStart + (viewEnd - viewStart) / 2)
        }

        override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float {
            return 100f / displayMetrics.densityDpi
        }
    }
}

2.视频详情适配器:

package com.example.centemanagerdemo.adapter

import android.text.TextUtils
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.centemanagerdemo.R
import com.example.centemanagerdemo.bean.VideoDetailBean
import com.example.centemanagerdemo.utils.TimeUtils

/**
 *@author: njb
 *@date:  2023/1/16 23:36
 *@desc:
 */
class FullVideoDetailAdapter(data:MutableList<VideoDetailBean>):BaseQuickAdapter<VideoDetailBean,BaseViewHolder>(
    R.layout.item_full_video_column,data){
    override fun convert(helper: BaseViewHolder, item: VideoDetailBean) {
        item.let {
            val clFullVideo: ConstraintLayout = helper.getView(R.id.cl_full_video)
            val ivStart: ImageView = helper.getView(R.id.iv_full_play)
            val tvTime: TextView = helper.getView(R.id.tv_full_time)
            val tvContent: TextView = helper.getView(R.id.tv_full_content)
            if (!TextUtils.isEmpty(item.point.toString())) {
                tvTime.setText(TimeUtils.formatVideoTime(item.point))
            }
            tvContent.text = item.title
            addChildClickViewIds(R.id.cl_full_video,R.id.iv_full_play)
            if (item.isSelected) {
                ivStart.setImageResource(R.mipmap.icon_video_playing)
                tvTime.setTextColor(context.getColor(R.color.color_ffc10a))
                tvContent.setTextColor(context.getColor(R.color.color_ffc10a))
                clFullVideo.setBackgroundResource(R.drawable.shape_video_column_selected_bg)
            } else {
                ivStart.setImageResource(R.mipmap.icon_video_play)
                tvTime.setTextColor(context.getColor(R.color.color_white))
                tvContent.setTextColor(context.getColor(R.color.color_white))
                clFullVideo.setBackgroundResource(R.drawable.shape_full_video_bg)
            }
        }
    }
}

3.视频详情实体类:

import java.io.Serializable

/**
 *@author: njb
 *@date:  2023/2/6 16:41
 *@desc:
 */
data class VideoDetailBean(
    var id:Int = 0,
    var title:String = "",
    var point:Int = 0,
    var url:String = "",
    var isSelected:Boolean=false
):Serializable

4.自定义SpacesItemDecoration:

package com.example.centemanagerdemo.decoration;

import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.View;

import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

/**
 * 作者: njb
 * 时间: 2021/11/18 0008-上午 10:39
 * 描述:
 * 来源:
 */


public class SpacesItemDecoration extends RecyclerView.ItemDecoration  {


    private SpacesItemDecorationEntrust mEntrust;
    private int mColor;
    private int leftRight;
    private int topBottom;


    public SpacesItemDecoration(int leftRight, int topBottom) {
        this.leftRight = leftRight;
        this.topBottom = topBottom;
    }

    public SpacesItemDecoration(int leftRight, int topBottom, int mColor) {
        this(leftRight, topBottom);
        this.mColor = mColor;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mEntrust == null) {
            mEntrust = getEntrust(parent.getLayoutManager());
        }
        mEntrust.onDraw(c, parent, state);
        super.onDraw(c, parent, state);
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (mEntrust == null) {
            mEntrust = getEntrust(parent.getLayoutManager());
        }
        mEntrust.getItemOffsets(outRect, view, parent, state);
    }

    private SpacesItemDecorationEntrust getEntrust(RecyclerView.LayoutManager manager) {
        SpacesItemDecorationEntrust entrust = null;
        //要注意这边的GridLayoutManager是继承LinearLayoutManager,所以要先判断GridLayoutManager
        if (manager instanceof GridLayoutManager) {
            entrust = new GridEntrust(leftRight, topBottom, mColor);
        } else if (manager instanceof StaggeredGridLayoutManager) {
            entrust = new StaggeredGridEntrust(leftRight, topBottom, mColor);
        } else {//其他的都当做Linear来进行计算
            entrust = new LinearEntrust(leftRight, topBottom, mColor);
        }
        return entrust;
    }
}

5.MainActiivty代码:

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import com.example.centemanagerdemo.adapter.FullVideoDetailAdapter
import com.example.centemanagerdemo.bean.VideoDetailBean
import com.example.centemanagerdemo.decoration.SpacesItemDecoration
import com.example.centemanagerdemo.manager.CenterLayoutManager
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    private var centerAdapter: FullVideoDetailAdapter? = null
    private var dataList: MutableList<VideoDetailBean>? = null
    private var centerLayoutManager: CenterLayoutManager? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initAdapter()
    }

    private fun initAdapter() {
        dataList = mutableListOf()
        for (i in 0..20) {
            val detailModel = VideoDetailBean()
            detailModel.title = ("S1 与 Vision+ S1 App 的连接S1")
            detailModel.point = (90)
            dataList?.add(detailModel)
        }
        centerAdapter = FullVideoDetailAdapter(dataList!!)
        centerLayoutManager = CenterLayoutManager(this)
        rv_video.layoutManager = centerLayoutManager
        rv_video.addItemDecoration(SpacesItemDecoration(0, 20))
        rv_video.adapter = centerAdapter

        centerAdapter?.setOnItemChildClickListener { adapter, view, position ->
            val list: MutableList<VideoDetailBean> = adapter.data as MutableList<VideoDetailBean>
            for (videoDetailModel in list) {
                videoDetailModel.isSelected = false
            }
            list[position].isSelected = true
            centerAdapter?.notifyDataSetChanged()
            if (view.id == R.id.iv_full_play || view.id == R.id.cl_full_video) {
                if (dataList != null && dataList?.size!! > 3) {
                    centerLayoutManager!!.smoothScrollToPosition(
                        rv_video,
                        RecyclerView.State(),
                        position
                    )
                }
            }
        }
    }
}

6.布局文件代码:

activity_main和item_full_video_cloumn

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_video"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        tools:listitem="@layout/item_full_video_column"/>

</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/cl_full_video"
    android:paddingStart="20dp"
    android:paddingEnd="20dp"
    android:paddingTop="12dp"
    android:paddingBottom="12dp"
    android:focusable="true"
    android:background="@drawable/shape_full_video_bg"
    tools:ignore="ResourceName,MissingConstraints">

    <ImageView
        android:id="@+id/iv_full_play"
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:src="@mipmap/icon_video_play"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_full_time"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="11dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:textColor="@color/color_white"
        android:textSize="12sp"
        app:layout_constraintLeft_toRightOf="@+id/iv_full_play"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:text="01:19" />

    <TextView
        android:id="@+id/tv_full_content"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:ellipsize="end"
        android:gravity="center|left"
        android:textColor="@color/color_white"
        android:textSize="12sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/iv_full_play"
        android:text="S1 与 Vision+ S1 App 的连接S1 与 Vision+ S1 App 的连接S1 与 Vision+ S1 App 的连接S1 与 Vision+ S1 App 的连接S1 与 Vision+ S1 App 的连接S1 与 Vision+ S1 App 的连接"
        tools:ignore="RtlHardcoded" />
</androidx.constraintlayout.widget.ConstraintLayout>

7.实现的效果如下:

在这里插入图片描述

8.源码如下:

https://gitee.com/jackning_admin/center-manager-demo-c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值