我正在创建一个食品菜单布局,菜单有类别与项目。最上面是饮料、寿司等类别名称的列表,这是一个水平滚动的回收视图,底部是分类项目,例如饮料下面有cocacola芬达等,这是一个垂直滚动的回收视图。我试图同步这两个回收视图与一个行为,在其中当你滚动垂直,它滚动水平,反之亦然。
我创建这个类是为了实现这个特性。
import android.graphics.Typeface import android.os.Handler import android.os.Looper import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearSmoothScroller import androidx.recyclerview.widget.RecyclerView class TwoRecyclerViews( private val recyclerViewHorizontal: RecyclerView, private val recyclerViewVertical: RecyclerView, private var indices: List<Int>, private var isSmoothScroll: Boolean = false, private var attached = false private var horizontalRecyclerState = RecyclerView.SCROLL_STATE_IDLE private var verticalRecyclerState = RecyclerView.SCROLL_STATE_IDLE private val smoothScrollerVertical: RecyclerView.SmoothScroller = object : LinearSmoothScroller(recyclerViewVertical.context) { override fun getVerticalSnapPreference(): Int { return SNAP_TO_START fun attach() { recyclerViewHorizontal.adapter ?: throw RuntimeException("Cannot attach with no Adapter provided to RecyclerView") recyclerViewVertical.adapter ?: throw RuntimeException("Cannot attach with no Adapter provided to RecyclerView") updateFirstPosition() notifyIndicesChanged() attached = true private fun detach() { recyclerViewVertical.clearOnScrollListeners() recyclerViewHorizontal.clearOnScrollListeners() fun reAttach() { detach() attach() private fun updateFirstPosition() { Handler(Looper.getMainLooper()).postDelayed({ val view = recyclerViewHorizontal.findViewHolderForLayoutPosition(0)?.itemView val textView = view?.findViewById<TextView>(R.id.horizontalCategoryName) val imageView = view?.findViewById<ImageView>(R.id.categorySelectionIndicator) imageView?.visibility = View.VISIBLE textView?.setTypeface(null, Typeface.BOLD) textView?.setTextColor(recyclerViewVertical.context.getColor(R.color.primary_1)) }, 100) fun isAttached() = attached private fun notifyIndicesChanged() { recyclerViewHorizontal.addOnScrollListener(onHorizontalScrollListener) recyclerViewVertical.addOnScrollListener(onVerticalScrollListener) private val onHorizontalScrollListener = object : RecyclerView.OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { horizontalRecyclerState = newState override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) val linearLayoutManager: LinearLayoutManager = recyclerView.layoutManager as LinearLayoutManager? ?: throw RuntimeException("No LinearLayoutManager attached to the RecyclerView.") var itemPosition = linearLayoutManager.findFirstCompletelyVisibleItemPosition() if (itemPosition == -1) { itemPosition = linearLayoutManager.findFirstVisibleItemPosition() if (horizontalRecyclerState == RecyclerView.SCROLL_STATE_DRAGGING || horizontalRecyclerState == RecyclerView.SCROLL_STATE_SETTLING for (position in indices.indices) { val view = recyclerView.findViewHolderForLayoutPosition(indices[position])?.itemView val textView = view?.findViewById<TextView>(R.id.horizontalCategoryName) val imageView = view?.findViewById<ImageView>(R.id.categorySelectionIndicator) if (itemPosition == indices[position]) { if (isSmoothScroll) { smoothScrollerVertical.targetPosition = indices[position] recyclerViewVertical.layoutManager?.startSmoothScroll(smoothScrollerVertical) } else { (recyclerViewVertical.layoutManager as LinearLayoutManager?)?.scrollToPositionWithOffset( indices[position], 16.dpToPx() imageView?.visibility = View.VISIBLE textView?.setTypeface(null, Typeface.BOLD) textView?.setTextColor(recyclerView.context.getColor(R.color.primary_1)) } else { imageView?.visibility = View.GONE textView?.setTypeface(null, Typeface.NORMAL) textView?.setTextColor(recyclerView.context.getColor(R.color.secondary_5)) private val onVerticalScrollListener = object : RecyclerView.OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { verticalRecyclerState = newState override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) val linearLayoutManager: LinearLayoutManager = recyclerView.layoutManager as LinearLayoutManager? ?: throw RuntimeException("No LinearLayoutManager attached to the RecyclerView.") var itemPosition = linearLayoutManager.findFirstCompletelyVisibleItemPosition() if (itemPosition == -1) { itemPosition = linearLayoutManager.findFirstVisibleItemPosition() if (verticalRecyclerState == RecyclerView.SCROLL_STATE_DRAGGING || verticalRecyclerState == RecyclerView.SCROLL_STATE_SETTLING for (position in indices.indices) { val view = recyclerViewHorizontal.findViewHolderForAdapterPosition(indices[position])?.itemView val textView = view?.findViewById<TextView>(R.id.horizontalCategoryName) val imageView = view?.findViewById<ImageView>(R.id.categorySelectionIndicator) if (itemPosition == indices[position]) { (recyclerViewHorizontal.layoutManager as LinearLayoutManager?)?.scrollToPositionWithOffset( indices[position], 16.dpToPx() imageView?.visibility = View.VISIBLE textView?.setTypeface(null, Typeface.BOLD) textView?.setTextColor(recyclerViewVertical.context.getColor(R.color.primary_1)) } else { imageView?.visibility = View.GONE textView?.setTypeface(null, Typeface.NORMAL) textView?.setTextColor(recyclerViewVertical.context.getColor(R.color.secondary_5))