如何求解recyclerview.apter问题?

发布于 2025-02-10 05:40:31 字数 2326 浏览 1 评论 0原文

我正在尝试将第一个文本(位置= 0)的重力从'onBindViewHolder(Viewholder:View Holder,位置:INT)'列表中的列表更改为',但是除了第一个元素的重力更改外。你能告诉我这个问题的来源吗?

您可以在下面看到代码,还可以日志

class ButtonsListAdapter(private val dataSet: List<String>) :
    RecyclerView.Adapter<ButtonsListAdapter.ViewHolder>() {

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView
        val divider: View

        init {
            textView = view.findViewById(R.id.textView)
            divider = view.findViewById(R.id.divider)
        }
    }

    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(viewGroup.context)
            .inflate(R.layout.buttons_list_item, viewGroup, false)

        return ViewHolder(view)
    }

    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {

        viewHolder.textView.text = dataSet[position]
        if(position == 0) {
            Log.i("Position", " position ->  $position ")
            viewHolder.textView.gravity = Gravity.START or Gravity.CENTER_VERTICAL
        }
        Log.i("Position", " gravity ->  $position " + viewHolder.textView.gravity)
    }

    override fun getItemCount() = dataSet.size
}

日志

I/Position:  position ->  0 
I/Position:  gravity ->  0 8388627
I/Position:  gravity ->  1 17
I/Position:  gravity ->  2 17
I/Position:  gravity ->  3 17
I/Position:  gravity ->  4 17
I/Position:  gravity ->  5 17
I/Position:  gravity ->  6 17
I/Position:  gravity ->  7 17
I/Position:  gravity ->  8 17
I/Position:  gravity ->  9 8388627
I/Position:  gravity ->  10 17
I/Position:  gravity ->  11 17
I/Position:  gravity ->  12 17
I/Position:  gravity ->  13 17
I/Position:  gravity ->  14 17
I/Position:  gravity ->  15 17
I/Position:  gravity ->  16 17
I/Position:  gravity ->  17 17
I/Position:  gravity ->  9 8388627
I/Position:  gravity ->  8 17
I/Position:  gravity ->  7 17
I/Position:  gravity ->  6 17
I/Position:  gravity ->  5 17
I/Position:  gravity ->  4 17
I/Position:  gravity ->  3 17
I/Position:  gravity ->  2 17
I/Position:  gravity ->  1 17
I/Position:  position ->  0 
I/Position:  gravity ->  0 8388627

I am trying to change first text(position = 0) gravity from List in 'onBindViewHolder(viewHolder: ViewHolder, position: Int)', but, except for the first, the gravity of some elements changes. Could you tell me where this problem comes from?

You can see code below and also logs

class ButtonsListAdapter(private val dataSet: List<String>) :
    RecyclerView.Adapter<ButtonsListAdapter.ViewHolder>() {

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView
        val divider: View

        init {
            textView = view.findViewById(R.id.textView)
            divider = view.findViewById(R.id.divider)
        }
    }

    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(viewGroup.context)
            .inflate(R.layout.buttons_list_item, viewGroup, false)

        return ViewHolder(view)
    }

    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {

        viewHolder.textView.text = dataSet[position]
        if(position == 0) {
            Log.i("Position", " position ->  $position ")
            viewHolder.textView.gravity = Gravity.START or Gravity.CENTER_VERTICAL
        }
        Log.i("Position", " gravity ->  $position " + viewHolder.textView.gravity)
    }

    override fun getItemCount() = dataSet.size
}

Logs

I/Position:  position ->  0 
I/Position:  gravity ->  0 8388627
I/Position:  gravity ->  1 17
I/Position:  gravity ->  2 17
I/Position:  gravity ->  3 17
I/Position:  gravity ->  4 17
I/Position:  gravity ->  5 17
I/Position:  gravity ->  6 17
I/Position:  gravity ->  7 17
I/Position:  gravity ->  8 17
I/Position:  gravity ->  9 8388627
I/Position:  gravity ->  10 17
I/Position:  gravity ->  11 17
I/Position:  gravity ->  12 17
I/Position:  gravity ->  13 17
I/Position:  gravity ->  14 17
I/Position:  gravity ->  15 17
I/Position:  gravity ->  16 17
I/Position:  gravity ->  17 17
I/Position:  gravity ->  9 8388627
I/Position:  gravity ->  8 17
I/Position:  gravity ->  7 17
I/Position:  gravity ->  6 17
I/Position:  gravity ->  5 17
I/Position:  gravity ->  4 17
I/Position:  gravity ->  3 17
I/Position:  gravity ->  2 17
I/Position:  gravity ->  1 17
I/Position:  position ->  0 
I/Position:  gravity ->  0 8388627

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

为你拒绝所有暧昧 2025-02-17 05:40:31

我相信Recyclerview试图使用旧行来节省内存使用情况。
有点像:当视图0熄灭屏幕时,新行9将“回收”它以显示自身(为什么称为RecyClerview)。

如果需要不同的第一行,请尝试覆盖方法int getItemViewType(int position),并指定第一个项目是与其他项目的“不同类型”

(或者您只需在<<代码> if(位置== 0)并强制您想要的重力,但我认为另一种选择更优雅)

I believe the RecyclerView tries to use old rows to save on memory usage.
It's kinda like: when the view 0 goes out the screen, the new line 9 will "recycle" it to show itself (that why it's called RecyclerView).

If you want a different first line, try override the method int getItemViewType(int position) and specify that the first item is a "different type" from the rest

(or you could just add an else on if(position == 0) and force the gravity you want, but I think the other option is more elegant)

往昔成烟 2025-02-17 05:40:31

reyclerview s有几个view holder s,它们交换以使其看起来像一个大列表,但实际上它是沿着传送带骑行的几个盒子,被移动了从末端回到开始。

OnBindViewHolder是您设置其中一个框的内容以显示列表中该位置的项目。您为您提供的Viewholder在设置以显示以前的项目时看起来仍然像它一样,因此您需要确保正确设置所有内容新的。您不更改的任何东西,都会 stick ,看起来就像它显示的最后一项。

因此,这是您的问题:

override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
    viewHolder.textView.text = dataSet[position]
    if(position == 0) {
        viewHolder.textView.gravity = Gravity.START or Gravity.CENTER_VERTICAL
    }
}

显示项目之间的变化是重力的一部分 - 在这里,您将其设置为 item 0 ,但您并未将其设置为其他项目的正常情况。它是粘性,您只将其设置为一种方式,并且永远无法恢复。因此,需要在该回收的View> view holder对象中显示的下一个项目将具有相同的重力设置,因为那是设置的!这是项目9 通过日志进行(您可以看到重复使用启动时会创建多少view> viewholder - 看起来恰好在此中使用了其中的9个案例)


是的,是的,您需要在所有情况下设置重力 - 设置每个项目的整个显示状态,以确保其一致,并且没有一个旧状态可以影响现在的外观:

override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
    viewHolder.textView.text = dataSet[position]
    // explicitly set the gravity every time
    if(position == 0) {
        viewHolder.textView.gravity = Gravity.START or Gravity.CENTER_VERTICAL
    } else {
        viewHolder.textView.gravity = // whatever
    }
}

但是我希望这使得更加清晰 - 您始终需要在绑定项目时使用recyclerview s进行此操作,因为您正在重用填充的旧项目使用旧数据和旧状态。因此,您应该每次完全配置它们,以获取任何可能改变的东西。您不希望任何旧州闲逛!

(Luiz的答案也是一个不错的选择,拥有一个完全独立的项目类型的标题类型允许您使用自己的布局等使用其他View -Codeholder,因此无需继续重新配置单个布局。如果您要进行较小的更改,可能会做得太多 - 您有选择!)

ReyclerViews have a handful of ViewHolders that they swap around to make it look like a large list, but really it's the same few boxes riding along a conveyor belt, being moved from the end back to the start.

onBindViewHolder is where you set the contents of one of those boxes to display the item at that position in the list. The ViewHolder that you're provided with still looks like it did when it was set up to display a previous item, so you need to make sure everything is set up correctly for the new one. Anything you don't change, will stick and look like the last item it was displaying.

So here's your problem:

override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
    viewHolder.textView.text = dataSet[position]
    if(position == 0) {
        viewHolder.textView.gravity = Gravity.START or Gravity.CENTER_VERTICAL
    }
}

Part of the display state that changes between items is the gravity - and here you're setting it for item 0, but you're not setting it to normal for the other items. It's sticky, you only set it one way, and it can never revert. So the next item that needs to display in that recycled ViewHolder object will have that same gravity setting, because that's what it's been set to! Which is item 9 going by your logs (you can see how many ViewHolders are getting created by when the reuse starts - looks like it happens to use 9 of them in this case)


So yeah, you need to set the gravity in all cases - set the whole display state for every item, to ensure it's consistent and that none of the old state can influence how it looks now:

override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
    viewHolder.textView.text = dataSet[position]
    // explicitly set the gravity every time
    if(position == 0) {
        viewHolder.textView.gravity = Gravity.START or Gravity.CENTER_VERTICAL
    } else {
        viewHolder.textView.gravity = // whatever
    }
}

But I hope that makes the broader point clearer - you always need to do this stuff with RecyclerViews when you're binding items, because you're reusing old items that are filled in with old data and old state. So you should fully configure them each time, for anything that could potentially change. You don't want any old state hanging around!

(Luiz's answer is also a good option, having a completely separate item type for a header allows you to use a different ViewHolder with its own layout etc, so there's no need to keep reconfiguring a single layout. But it might be too much work if you're making a small change - you have options!)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文