【问题标题】:How to scroll with smoothScrollToPosition of RecyclerView with dynamic position in recyclerview?如何使用 RecyclerView 的 SmoothScrollToPosition 滚动并在 recyclerview 中使用动态位置?
【发布时间】:2020-12-29 03:02:12
【问题描述】:

我使用 tabLayout 作为 recyclerView 适配器的标题。滚动到 recyclerview 项目的静态位置我没有问题。例如位置 2 表示披萨标题。标签 0 表示披萨。

override fun onTabSelected(tab: TabLayout.Tab?) {
if (tab.position == 0)
recyclerview.smoothScrollToPosition(2)}

问题是我不知道如何滚动到一些我没有位置的标题项目的位置。据我所知,我可以通过 onBindViewHolder 函数获取所有项目位置,直到它们在屏幕上可见。正确的。 但是当所有项目都不可见或者我在列表的第一个时,我怎么能得到其余的标题位置?例如,饮料标题位置在列表的末尾,当用户单击饮料标签转到时,我需要知道位置。这似乎不是一个好方法。

我的情况是,我有一个 recyclerview 适配器。它有两种物品类型。

1-标题项目类型(食物类型如:三明治 - 比萨 - ...)

2 项类型(食物类型:那不勒斯比萨 - 芝加哥比萨 - ...)

我的方法是:我创建一个 hashmap。试图用标题项目填充它。 。 我把它填在了onbindviewholder中。正如我之前描述的那样。在我将所有列表滚动到结束之前,不会立即计算所有标题项的位置。所以 returnPositionHedaer 函数总是返回 0。

RecyclerViewAdapter 类:

class RecyclerAdapterInside( PlaceId:String?=null, var myReceivedData: List<ItemClass>?=null, val context:Context, private val ButtonFinish:RecyclerAdapterInsideButtonFinishCallback):RecyclerView.Adapter<RecyclerView.ViewHolder>() {

private var allHeader:HashMap<String,Int> = hashMapOf()

    companion object {
        const val Type_Header = 1
        const val Type_Item = 2
    }
  private inner class CategoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var message: TextView = itemView.findViewById(R.id.textViewCategory)
        fun bind(position: Int)
        {
            Log.d("inner Category","it is in CategoryViewHolder Header")
            message.text = myReceivedData?.get(position)?.name

            allHeader.put(message.text.toString(),position)

            Log.d("itemss iewHolder",allHeader.keys.toString())

        }
    }
    private inner class ItemViewholder(itemview: View) : RecyclerView.ViewHolder(itemview) {
        val Name = itemview.findViewById(R.id.ItemName) as TextView
        val Price = itemview.findViewById(R.id.ItemPrice) as TextView
        val Category = itemview.findViewById(R.id.ItemCategory) as TextView
        val Image = itemView.findViewById(R.id.ImgInsideMenu) as ImageView
        val BtnAdd = itemView.findViewById(R.id.AddBtn) as Button
        var count = itemview.findViewById(R.id.showCounter) as TextView
        val BtnMin = itemView.findViewById(R.id.MinBtn) as Button
        fun bind(position: Int) {

            Log.d("value name is","${Name.text}")

            Log.d("inner Category","it is in ItemViewHolder Header")

            Name.text = myReceivedData!![position].name
        Price.text = "Price :" + myReceivedData!![position].price
...
}

    override fun getItemViewType(position: Int): Int {
        return when (myReceivedData!!.get(position).getviewType()) {
            1 -> Type_Header
            2 -> Type_Item
            else -> -1
        }

    }

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        if (viewType == Type_Header)
        {
            Log.d("OncreateViewHolder","it is in oncreateview holder type header")
            return CategoryViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.categoryheader, parent, false))
        }
        else
        {
            Log.d("OncreateViewHolder","it is in oncreateview holder type item")
            return ItemViewholder(LayoutInflater.from(parent.context).inflate(R.layout.itemforrecyclerviewinside, parent, false)
            )
        }
    }

   override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)
    {
        when (myReceivedData!![position].getviewType())
        {
            Type_Header ->
            {
                Log.d("OnBindViewHolder","it is in OnBind holder type header")
                (holder as CategoryViewHolder).bind(position)
            }
            Type_Item ->
            {
                Log.d("OnTypeViewHolder","it is in OnBind holder type item")
                (holder as ItemViewholder).bind(position)
            }
        }
    }
   


 fun returnPositionHedaer(name:String):Int
        {
            for (hashMap in allHeader)
            {
                Log.d("itemss",hashMap.key)
                if (hashMap.key == name)
                {
                 return hashMap.value
                }
            }
            return 0

        }
}

我使用类别食物列表动态填充我的 TabLayout 选项卡。我的适配器对标题项使用相同的类别。

那些部分已经工作了。我在这里写它们是为了更清楚地说明。在这一部分中,我调用 returnPositionHedaer 并将所选选项卡的 tabName 传递给它。这种方法似乎从来没有奏效过。 我再说一遍,我在 recyclerview 中有一个动态位置,当在 TabLayout 中单击相关选项卡时,我需要计算要滚动的标题项的位置。 我在 tabLayout 中的选项卡和 recyclerview 中的项目之间的关系或链接是名称。 我的方法不行。

你有什么建议?

MenuFragment 类:

//to more clarify,has no problem 
private fun setupTabLayout():List<String>
{
    if(tabLayout!!.tabCount>0)
        CoroutineScope(Dispatchers.Main).launch{tabLayout!!.removeAllTabs()}
for(i in 0 until fullMenu!!.size){
    CategoryList.add(i,fullMenu!![i].category)
    Log.d("category",CategoryList[i])
}

val tabCategory=CategoryList.distinct()



CoroutineScope(Dispatchers.Main).launch {
    if (tabCategory.size > 3)
        tabLayout!!.setTabMode(TabLayout.MODE_SCROLLABLE);
    else {
        tabLayout!!.setTabMode(TabLayout.MODE_FIXED);
        tabLayout!!.setTabGravity(TabLayout.GRAVITY_FILL);
    }

    for (i in 0 until tabCategory.size)
    {
        tabLayout?.addTab(tabLayout!!.newTab().setText(tabCategory[i]), i)
        Log.d("addingtab",tabCategory[i])
    }
} }  //to more clarify,has no problem 





 override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

 setupTabLayout()

  tabLayout!!.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener{


            override fun onTabReselected(tab: TabLayout.Tab?) {

            }

            override fun onTabUnselected(tab: TabLayout.Tab?) {

            }

            override fun onTabSelected(tab: TabLayout.Tab?) {
                isUserScrolling = false
                val position = tab!!.position
                val tabName = tab.text

                CoroutineScope(Dispatchers.Main).launch {

recyclerview.smoothScrollToPosition( recyclerAdapter.returnPositionHedaer(tabName.toString()))
                //always return 0 position
}
            }
        })
}

【问题讨论】:

    标签: android android-recyclerview android-tablayout


    【解决方案1】:

    制作一个通用的物品类

    data class MyItem(private val item:ItemClass,private headerName:String?=null)
    

    将此传递给您的适配器

    RecyclerAdapterInside( PlaceId:String?=null, var myReceivedData: List<MyItem>?=null, val context:Context, private val ButtonFinish:RecyclerAdapterInsideButtonFinishCallback)
    

    然后找位置

    fun returnPositionHeader(name:String):Int {
       return myReceivedData.indexOfFirst { it.headerName=name }
    }
    

    【讨论】:

      【解决方案2】:

      对于那些有这个挑战的人,我可以轻松应对。您只需要从您的 recyclerview 适配器数据模型创建一个数组。在传递给适配器之前创建一个属性,例如将其命名为 poition。目的是保存数组数据模型中每个项目的位置,并使用计数器为每个数组项目分配位置。最后将其传递给适配器。现在你知道什么项目有什么位置了。

      菜单类()

      open class ItemClass()
      {
          private var position = 0
      
          var name: String?=null
          var _id: String? =null
          var __v: Int? =0
          var category: String?=null
          var description: String?=null
          var image: String? =null
          var price: String? =null
          var rating: String? =null
      
          open fun ItemHeaderClass(position:Int,viewType: Int, name: String) {
                  this.position=position
                  this.viewType = viewType
                  this.name=name
              }
      
      }
      

      菜单片段

      for(item in category)
              {
                  val myclass=ItemClass()
                  myclass.ItemHeaderClass(counter++, 1, item)
                  calculatedAllItemOfList.add(myclass)
      
                  val items = createItemListForRecycler(item, allItem)
                  calculatedAllItemOfList.addAll(items)
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-05
        • 2020-11-08
        • 2017-01-23
        • 2016-08-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多