使用场景
- 有时我们可能会有一个列表,不要求一下子全部显示,让其自行进行进行上下滚动显示。
解决方案
- 对于列表我们会想到ListView或者RecyclerView,但是要使其自动的无线滚动的话,因为是对布局的内容进行滑动,所以我们可以考虑使用ScrollTo()/ScrollBy()以及动画。在这里我们可以考虑使ScrollBy()来实现布局内容的滑动。
解决步骤
- 1.解决列表滑动问题
- 1.自定义RecyclerView,实现Runable接口。
- 2.通过PostDelayed()发送延迟消息。
- 3.在run方法中,通过scrollBy()对RecyclerView进行滑动处理,并再次发送延迟消息
- 4.在onDetachedFromWindow()中移除延迟消息,停止其滑动。
- 2.解决列表无线滚动
- 对于无线滚动,我们只需要让列表的个数尽可能无线就可以了,所以我们只需要让列表的getItemCount()返回数值尽可能大就行
- 3.解决用户触摸事件
- 对于用户触摸有两种解决方式
1.不处理用户事件,即用户触摸对滑动无影响,继续滚动。
2.用户触摸后停止滚动,等用户松开后继续滚动。
具体实现
- 1.自定义RecyclerView,在onAttachedToWindow()中通过PostDealyed()发送延迟消息来开始滚动(在View被添加到界面时触发该方法),在onDetachedFromWindow()中通过removeCallbacks()来停止滚动(在View从界面移除时触发)。
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.util.AttributeSet
import android.view.MotionEvent
/**
* Author:mj
* Time: 2018/10/9 16:27
* 描述:
* Version:
*/
class AutoVerticalRollRecyclerView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr), Runnable {
/**是否正在滑动*/
private var mIsRolling = false
/**
* View被添加到界面时触发
*/
override fun onAttachedToWindow() {
super.onAttachedToWindow()
startRoll()
}
/**
* View从界面移除时触发
*/
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
stopRoll()
}
/**
* 开始滑动
*/
private fun startRoll() {
//已经滑动时/没有设置适配器时直接返回
if (mIsRolling && adapter == null) return
mIsRolling = true
postDelayed(this,30)
}
/**
* 停止滑动
*/
private fun stopRoll() {
if(!mIsRolling) return
mIsRolling=false
removeCallbacks(this)
}
override fun run() {
if(this!=null&&this.mIsRolling){
scrollBy(0,2)
postDelayed(this,30)
}
}
/**
* 事件触摸:
* 1.若让滑动不受用户触摸影响,直接返回false,表示不处理事件
* 2.若需要在用户触摸时停止,用户离开时开始,只需要根据情况触摸事件进行处理即可
*/
override fun onTouchEvent(e: MotionEvent?): Boolean {
//1.若让滑动不受用户触摸影响,直接返回false,表示不处理事件
return false
//2.若需要在用户触摸时停止,用户离开时开始,只需要根据情况触摸事件进行处理即可
// when(e?.action){
// MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE -> stopRoll()
// MotionEvent.ACTION_UP,MotionEvent.ACTION_CANCEL,MotionEvent.ACTION_OUTSIDE -> startRoll()
// }
// return super.onTouchEvent(e)
}
}
- 2.自定义Adapter,在getItemCount()方法中返回最大值
class SimpleAdapter(list: MutableList<String>, mContext: Context) : RecyclerView.Adapter<SimpleAdapterViewHolder>() {
/**数据源*/
private var list: MutableList<String> = list
/**上下文*/
private var mContext: Context = mContext
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): SimpleAdapterViewHolder {
val view=LayoutInflater.from(mContext).inflate(R.layout.item_layout,p0,false)
return SimpleAdapterViewHolder(view)
}
/**
* 为了实现无线循环,需要将数据的源的个数设置为比较大的值
*/
override fun getItemCount(): Int {
return Int.MAX_VALUE
}
override fun onBindViewHolder(p0: SimpleAdapterViewHolder, p1: Int) {
p0.mTvData?.text=list!![p1%list!!.size]
}
}
- 自定义ViewHolder
class SimpleAdapterViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var mTvData: TextView? = null
init {
mTvData = itemView.findViewById(R.id.tvData)
}
}
- item布局:item_layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/tvData"
android:layout_width="match_parent"
android:layout_height="30dp"
android:text="数据"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:textSize="15sp"
android:gravity="center"/>
</android.support.constraint.ConstraintLayout>
- 主布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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=".ui.MainActivity">
<com.view.widget.AutoVerticalRollRecyclerView
android:id="@+id/mRecyclerView"
android:layout_width="match_parent"
android:layout_height="130dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
- 具体代码调用
var list= mutableListOf<String>()
for (i in 0 until 10){
list.add("数据$i")
}
mRecyclerView.layoutManager=LinearLayoutManager(this)
mRecyclerView.adapter=SimpleAdapter(list,this)
- 效果图