【Android】RecycleView 将指定item滚动置顶(kotlin)

一、RecyclerView本身提供的定位方法说明

 // 滑动到适配器指定位置(position:item的index)
 smoothScrollToPosition(position) 

// 使指定的item平滑滚动到屏幕中
// 说明:
// 情况1:指定item在可见范围外时,则滑动到可见范围
// 情况2:指定item在可见范围内时,则不会滑动
 recycleview.smoothScrollToPosition();

二、实现思路

item有三种情况:

情况1:在可见范围之前
item在第一个可见item之前,直接用smoothScrollToPosition,则当该item移动到可见范围时,它就在RecyclerView顶部

情况2:在可见范围内
tem在可见范围内(即在第一个可见item之后,最后一个可见item之前),这时scrollToPosition失效,需要手动计算该item的view距离顶部的距离,用scrollBy自行移动到置顶位置

情况3:在可见范围之后
item在最后一个可见item之后,有两种处理方式:
方式一:(不推荐,如item内容过长会有问题)
用smoothScrollToPosition滑动到可见范围 (此时该item在最后一个位置),再获取该item的view,计算到顶部距离,再监听RecyclerView的滑动,对其进行二次滑动到顶部

//标记是否需要二次滑动
var shouldMove: Boolean = false

// 监听RecyclerView的滑动,对需要进行二次滑动的item进行滑动
mRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
        super.onScrollStateChanged(recyclerView, newState)
        if (shouldMove && RecyclerView.SCROLL_STATE_IDLE == newState) {
            shouldMove = false
            smoothMoveToPosition(mRecyclerView, mPosition)
        }
    }
})

// smoothMoveToPosition函数内第三种情况代码替换为
recyclerView.smoothScrollToPosition(position)
mPosition = position
shouldMove = true

方式二:(推荐)
用smoothScrollToPosition滑动到可见范围,RecyclerView在用smoothScrollToPosition函数时,是创建了一个LinearSmoothScroller,其中有个 SNAP_TO_START参数 能将 子view与父view左对齐或顶部对齐,根据 LayoutManager 是 horizontal 还是 vertical 决定的,因此重写 LinearSmoothScroller,设置该参数即可实现置顶,之后在需要使用的地方获取 RecyclerView 的 LayoutManager ,调用 startSmoothScroll 即可。

三、完整代码

// 需要置顶的item的index
var mPosition: Int = 0
//标记 当前可见item与顶部的距离是否为0:false则点击上一题时显示当前item
var shouldMove: Boolean = true

// 监听RecyclerView的滑动,当前可见item是否置顶
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
	override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
    	super.onScrollStateChanged(recyclerView, newState)
        if (RecyclerView.SCROLL_STATE_IDLE == newState) {
        	mPosition = recyclerView.getChildLayoutPosition(recyclerView.getChildAt(0))
        	if (recyclerView.childCount>0) {
            	// 计算当前可见item到顶部的距离
                val top = recyclerView.getChildAt(0).top
                // 手动滑动到顶部
                shouldMove = top >= 0
             }
         }
     }
})
                
// 让指定item置顶
fun smoothMoveToPosition(recyclerView: RecyclerView, position: Int) {
	// 获取RecyclerView的第一个可见位置
	val firstItem = recyclerView.getChildLayoutPosition(recyclerView.getChildAt(0))
	// 获取RecyclerView的最后一个可见位置
	val lastItem = recyclerView.getChildLayoutPosition(recyclerView.getChildAt(recyclerView.childCount - 1))
	
	if (position < firstItem) {
		// 在可见范围之前,就smoothScrollToPosition可以直接跳转
        recyclerView.smoothScrollToPosition(position)
    } else if (position <= lastItem) {
        // 在可见范围内
    	val pos = position - firstItem
        if (pos >= 0 && pos < recyclerView.childCount) {
        	// 计算指定item的view到顶部的距离
        	val top = recyclerView.getChildAt(pos).top
        	// 手动滑动到顶部
        	recyclerView.smoothScrollBy(0, top)
    	}
    } else {
        // 在可见范围之后
        mPosition = position
        
        // 用smoothScrollToPosition滑动到可见范围
        // RecyclerView在用smoothScrollToPosition函数时,是创建了一个LinearSmoothScroller有个SNAP_TO_START参数
        // SNAP_TO_START:将子view与父view左对齐或顶部对齐,根据LayoutManager是horizontal还是vertical决定,
        // 因此重写LinearSmoothScroller,设置该参数即可实现置顶
        class TopSmoothScroller(context: Context) : LinearSmoothScroller(context) {
        	override fun getHorizontalSnapPreference(): Int {
              	return SNAP_TO_START
            }

            override fun getVerticalSnapPreference(): Int {
                return SNAP_TO_START
            }
        }
        
        val mTopScroller = TopSmoothScroller(requireContext())// requireContext()用于获取与片段相关联的Context对象
        mTopScroller.targetPosition = position
        recyclerView.layoutManager?.startSmoothScroll(mTopScroller)
     }
}

// 点击显示上一个item
preQue.addPreventDoubleClickListener {
	if (mPosition > 0 && shouldMove) {
    	mPosition -= 1
        smoothMoveToPosition(recyclerView, mPosition)
    }else{
        if (recyclerView.childCount>0) {
        	// 计算当前可见item到顶部的距离
            val top = recyclerView.getChildAt(0).top
            // 手动滑动到顶部
            recyclerView.smoothScrollBy(0, top)
            shouldMove = true
         }
     }
}
// 点击显示下一个item
nextQue.addPreventDoubleClickListener {
	if (mPosition < exp.expTopic.size) {
    	mPosition += 1
        smoothMoveToPosition(recyclerView, mPosition)
    }
}

四、参考链接

java版本

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是Kotlin实现的BRVAH和RecyclerView实现无限循环滚动和可点击item的代码: 1. 首先在build.gradle添加BRVAH依赖: ``` implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4' ``` 2. 在布局文件添加RecyclerView: ``` <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 3. 在Activity或Fragment初始化RecyclerView: ``` val recyclerView = findViewById<RecyclerView>(R.id.recyclerView) val layoutManager = LinearLayoutManager(this) layoutManager.orientation = LinearLayoutManager.HORIZONTAL // 设置为横向滚动 recyclerView.layoutManager = layoutManager ``` 4. 创建Adapter并继承BaseQuickAdapter: ``` class MyAdapter(data: List<String>?) : BaseQuickAdapter<String, BaseViewHolder>(R.layout.item_layout, data) { override fun convert(holder: BaseViewHolder, item: String) { // 设置item的显示内容 holder.setText(R.id.tvItemName, item) } } ``` 5. 创建数据源并初始化Adapter: ``` val dataList = listOf("item1", "item2", "item3", "item4", "item5") val myAdapter = MyAdapter(dataList) recyclerView.adapter = myAdapter ``` 6. 实现无限循环滚动: ``` recyclerView.post { val layoutManager = recyclerView.layoutManager as LinearLayoutManager val firstItem = layoutManager.findFirstVisibleItemPosition() val lastItem = layoutManager.findLastVisibleItemPosition() val itemCount = layoutManager.itemCount // 如果当前第一个可见item是第0个item,则将RecyclerView滚动到最后一个item的位置 if (firstItem == 0) { recyclerView.scrollToPosition(itemCount - 1) } // 如果当前最后一个可见item是最后一个item,则将RecyclerView滚动到第一个item的位置 else if (lastItem == itemCount - 1) { recyclerView.scrollToPosition(0) } } ``` 7. 实现可点击item: ``` myAdapter.setOnItemClickListener { adapter, view, position -> // 处理item的点击事件 } ``` 以上就是BRVAH和RecyclerView实现无限循环滚动和可点击itemKotlin代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值