天天看點

RecyclerView嵌套(含滑動沖突解決,在子控件中解決沖突)

背景

有時需要在縱向滑動清單中嵌套橫向滑動清單.

效果圖:

RecyclerView嵌套(含滑動沖突解決,在子控件中解決沖突)

解決方案

通過縱向RecyclerView嵌套橫向RecyclerView.

大緻實作方式:

  1. 主界面中包含一個縱向RecyclerView
<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
      
  1. 縱向RecyclerView的adapter
  • VerticalRvAdapter.kt
class VerticalRvAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private var mDataList = mutableListOf<List<String>>()
    private lateinit var mContext: Context
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val data = mDataList[position]
        val horizontalRvAdapter = HorizontalRvAdapter()
        holder.itemView.horizontalRecyclerView.adapter = horizontalRvAdapter
        horizontalRvAdapter.setData(data)
    }

    fun setData(dataList: List<List<String>>) {
        mDataList.clear()
        mDataList.addAll(dataList)
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int = mDataList.size

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        mContext = parent.context
        val view = LayoutInflater.from(mContext).inflate(R.layout.item_vertical_rv, parent, false)
        view.horizontalRecyclerView.layoutManager = LinearLayoutManager(mContext, RecyclerView.HORIZONTAL, false)

        return ViewHolder(view)
    }

    class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView!!)

}
      
  • 縱向RecyclerView每個item對應的布局item_vertical_rv.xml(包含一個橫向RecyclerView ):
<com.cxyzy.demo.HorizontalRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/horizontalRecyclerView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center" />
      
  1. 橫向RecyclerView(HorizontalRecyclerView.kt):

    作用: 解決滑動沖突,具體多大角度進行縱向滑動,多大角度進行橫向滑動,可以通過修改​

    ​if (abs(moveX - mDownX) > abs(moveY - mDownY))​

    ​實作.(此處為了代碼簡潔,為直接計算出角度,而是采用寬和高的比較來達到同樣效果)
class HorizontalRecyclerView(context: Context, attrs: AttributeSet) : RecyclerView(context, attrs) {

    private var mDownX: Int = 0
    private var mDownY: Int = 0

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                mDownX = ev.x.toInt()
                mDownY = ev.y.toInt()
            }
            MotionEvent.ACTION_MOVE -> {
                val moveX = ev.x.toInt()
                val moveY = ev.y.toInt()
                if (abs(moveX - mDownX) > abs(moveY - mDownY)) {
                    parent.requestDisallowInterceptTouchEvent(true)
                }
                mDownX = moveX
                mDownY = moveY
            }
        }
        return super.dispatchTouchEvent(ev)
    }
}