讲道义的松树 · 深入理解SpringBoot 最大连接数及最 ...· 4 月前 · |
爱旅游的丝瓜 · javax.management.Insta ...· 1 年前 · |
耍酷的作业本 · 如何解决python版本升级后,conda不 ...· 1 年前 · |
纯真的红酒 · Delphi写注册表改变App内嵌TWebB ...· 1 年前 · |
我正在创建一个食品菜单布局,菜单有类别与项目。最上面是饮料、寿司等类别名称的列表,这是一个水平滚动的回收视图,底部是分类项目,例如饮料下面有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))
}
这个类对于垂直滚动很好,但是水平滚动是不稳定的。如果您还有一个比我创建的类更好的解决方案,请分享。
要解决TwoRecyclerViews类的问题,可以尝试以下方法:
私人娱乐recyclerViewHorizontal.addOnItemTouchListener(onHorizontalScrollListener) notifyIndicesChanged() { recyclerViewVertical.addOnItemTouchListener(onVerticalScrollListener) }
var itemPosition =itemPosition
//获取linearLayoutManager.findViewByPosition(itemPosition) val currentItem = RecyclerView //中的当前项,使用索引列表在其他RecyclerView val索引= indicesitemPosition中获取相应的索引
//滚动另一个RecyclerView到正确的位置val otherLinearLayoutManager =RecyclerView
实现UI/UX要求的最佳方法是使用带有垂直回收器视图的 TabLayout 。
可以将回收器视图中的列表项目和选项卡布局中的选项卡设置为动态的项目/选项卡数。
当您上下滚动并到达相应的类别时,请使用以下代码更新选项卡布局。属性中的每个类别。
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); // Once for the Activity of Fragment
TabLayout.Tab tab = tabLayout.getTabAt(someIndex); // Some index should be obtain from the dataset
tab.select();
同样,当单击选项卡或滚动选项卡布局时,相应地更新RecyclerVew。
recyclerView.smoothScrollToPosition(itemCount)
希望这会有帮助,干杯!
看起来,水平滚动的问题是它只滚动到垂直
RecyclerView
中的第一项,而不是滚动到在水平
RecyclerView
中滚动到的类别的相应项。要解决这个问题,可以使用
LinearLayoutManager.scrollToPositionWithOffset()
方法滚动到垂直RecyclerView中的对应项。
下面是如何更新onHorizontalScrollListener以使用此方法的示例:
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
if (indices.size > itemPosition) {
val index = indices[itemPosition]
if (isSmoothScroll) {
smoothScrollerVertical.targetPosition = index
recyclerViewVertical.layoutManager?.startSmoothScroll(smoothScrollerVertical)
} else {
// Use the LinearLayoutManager.scrollToPositionWithOffset() method to scroll to the corresponding item in the vertical RecyclerView