无法居中 RecyclerView 项

huangapple go评论44阅读模式
英文:

Unable to center recyclerview item

问题

以下是您要翻译的内容:

在为了使我的RecyclerView适配器更加动态我通过编程方式将宽度设置为特定百分比但我现在无法将项目居中似乎在XML中硬编码边距适用于RecyclerView项可以解决问题但这不是理想的解决方法似乎"android:gravity"不是RecyclerView上可用的属性任何地方都似乎不起作用我尝试在我的"ViewHolder.from(parent).apply"中编程方式添加填充但出现错误"Val cannot be reassigned"

我已经没有更多的想法了有什么帮助吗我在RecyclerView项中使用ConstraintLayout

```kotlin
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder.from(parent).apply {
        val targetWidth = parent.measuredWidth * 0.9
        itemView.layoutParams.width = targetWidth.toInt()
    }
}

我的适配器代码

package com.example.recyclerview_2.view

import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.view.marginEnd
import androidx.core.view.marginStart
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.recyclerview_2.R
import com.example.recyclerview_2.databinding.RecyclerviewItemBinding
import com.example.recyclerview_2.model.models.Bill
import com.example.recyclerview_2.utils.Format
import kotlin.reflect.KFunction1

private const val TAG = "Adapter"
class Adapter(private val itemClickListener: KFunction1<Bill, Unit>) : ListAdapter<Bill, Adapter.ViewHolder>(AsyncDifferConfig.Builder<Bill>(DiffCallBack()).build()) {

    class ViewHolder(val binding: RecyclerviewItemBinding) : RecyclerView.ViewHolder(binding.root) {

        fun bind(data: Bill, itemClickListener: () -> Unit){
            binding.billName.text = data.name.replaceFirstChar {
                it.uppercase()
            }
            binding.billAmt.text = Format.addTrailingZeros(data.amount) + "$"
            binding.dateDue = data.dateDue
            if(data.reoccurring){
                binding.reoccurring = data.reoccurringInterval
            }else{
                binding.billReoccuring.text = "Bill is not reoccurring"
            }
            itemView.setOnClickListener {
                Log.d("Clicked","${data._id}")
                itemClickListener()
            }
        }
        companion object{
            fun from(parent: ViewGroup): ViewHolder {
                var layoutInflater = LayoutInflater.from(parent.context)
                var binding = RecyclerviewItemBinding.inflate(layoutInflater, parent, false)
                return ViewHolder(binding)
            }
        }

    }

    private class DiffCallBack : DiffUtil.ItemCallback<Bill>(){
        override fun areItemsTheSame(oldItem: Bill, newItem: Bill): Boolean = oldItem._id == newItem._id

        override fun areContentsTheSame(oldItem: Bill, newItem: Bill): Boolean = oldItem == newItem

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder.from(parent).apply {
            val targetWidth = parent.measuredWidth * 0.9
            itemView.layoutParams.width = targetWidth.toInt()
        }
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
                val item = currentList[position]
                holder.bind(item, { itemClickListener(item) })
    }

    override fun getItemCount(): Int {
        return currentList.size
    }
}

[![图片1][1]][1]

[![图片2][2]][2]


[1]: https://i.stack.imgur.com/fJFVH.png
[2]: https://i.stack.imgur.com/ikO4W.png
<details>
<summary>英文:</summary>
In order to make my recyclerview adapter more dynamic I programmatically have set the width to be a certain percentage.  But I cannot now center the items, appears hardcoding margin in the XML for the recyclerview item works, but this is not ideal.  Appears &quot;android:gravity&quot; is not an available attribute on recyclerview.  android:layout_gravity anywhere doesnt seem to work.  I though that I would try in my &quot;ViewHolder.from(parent).apply to programmatically add padding but I get an error &quot;Val cannot be reassigned&quot;
[![picture1][1]][1]
Im out of ideas at this point, any help?  Im using constraintLayout for my recyclerview item.

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder.from(parent).apply {
val targetWidth = parent.measuredWidth * .9
itemView.layoutParams.width = targetWidth.toInt()
}
}


My Adapter code

package com.example.recyclerview_2.view

import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.view.marginEnd
import androidx.core.view.marginStart
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.recyclerview_2.R
import com.example.recyclerview_2.databinding.RecyclerviewItemBinding
import com.example.recyclerview_2.model.models.Bill
import com.example.recyclerview_2.utils.Format
import kotlin.reflect.KFunction1

private const val TAG = "Adapter"
class Adapter(private val itemClickListener: KFunction1<Bill, Unit>) : ListAdapter<Bill, Adapter.ViewHolder>(AsyncDifferConfig.Builder<Bill>(DiffCallBack()).build()) {

//When a inner keyword is used here you cannot create a companion object
//When the &#39;inner&#39; keyword is used members of the outer class are all accessible
class ViewHolder(val binding: RecyclerviewItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(data: Bill, itemClickListener: () -&gt; Unit){
binding.billName.text = data.name.replaceFirstChar {
it.uppercase()
}
binding.billAmt.text = Format.addTrailingZeros(data.amount) + &quot;$&quot;
binding.dateDue = data.dateDue
if(data.reoccurring){
binding.reoccurring = data.reoccurringInterval
}else{
binding.billReoccuring.text = &quot;Bill is not reoccurring&quot;
}
itemView.setOnClickListener {
Log.d(&quot;ClickED&quot;,&quot;${data._id}&quot;)
itemClickListener()
}
}
companion object{
fun from(parent: ViewGroup): ViewHolder {
var layoutInflater = LayoutInflater.from(parent.context)
var binding = RecyclerviewItemBinding.inflate(layoutInflater, parent, false)
return ViewHolder(binding)
}
}
}
private class DiffCallBack : DiffUtil.ItemCallback&lt;Bill&gt;(){
override fun areItemsTheSame(oldItem: Bill, newItem: Bill): Boolean = oldItem._id == newItem._id
override fun areContentsTheSame(oldItem: Bill, newItem: Bill): Boolean = oldItem == newItem
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder.from(parent).apply {
val targetWidth = parent.measuredWidth * .9
itemView.layoutParams.width = targetWidth.toInt()
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = currentList[position]
holder.bind(item, { itemClickListener(item) })
}
override fun getItemCount(): Int {
return currentList.size
}

}

[![picture2][2]][2]
[1]: https://i.stack.imgur.com/fJFVH.png
[2]: https://i.stack.imgur.com/ikO4W.png
</details>
# 答案1
**得分**: 1
`LayoutManager` 是负责管理 `RecyclerView` 中的项视图排列方式的部分。你可能应该只设计你的项布局(为 `ViewHolder` 填充的布局)以使其内容居中,即主要布局的宽度设置为 `wrap_content`,然后将*其中的内容*按照你的要求排列。这样做还可以提供更大的灵活性,因为这并不意味着*所有内容*都必须居中。
如果你希望内容占据宽度的 90%,你可以使用 `ConstraintLayout`,并在 5% 和 95% 处添加 [`Guideline`s][1] 并将内容约束到它。你还可以在主要布局内嵌套另一个布局,并使用 `layout_constraintWidth_percent` 将其宽度设置为 *0.9*(父布局宽度的 90%) - 个人认为这更有限制性(而不是具有一个扁平的布局),但这取决于你。
请记住,如果需要带有背景的“内容区域”,你可以添加普通的 `View`,并将其置于其他视图的后面 - 它们*不需要*在另一个布局内部!
[1]: https://developer.android.com/develop/ui/views/layout/constraint-layout#constrain-to-a-guideline
<details>
<summary>英文:</summary>
The `LayoutManager` is what handles how item views are arranged in the `RecyclerView`. You should probably just design your item layout (the one you inflate for the `ViewHolder`) to have its contents centred, i.e. the main layout with width `wrap_content`, then the stuff *inside that* arranged how you want it. This also gives you more flexibility, since it doesn&#39;t mean *everything* has to be centred.
If you want your content to take up 90% of the width, you could use a `ConstraintLayout` with [`Guideline`s][1] at 5% and 95% and constrain stuff to that. You could also nest another layout inside that main layout, and constrain its width with `layout_constraintWidth_percent` set to *0.9* (90% of the parent&#39;s width) - personally I feel like that&#39;s more limiting (instead of having one flat layout) but it&#39;s up to you.
Remember you can add plain `View`s if you need a *&quot;content area&quot;* with a background, and stick that behind the other views - they don&#39;t *need* to be inside another layout!
[1]: https://developer.android.com/develop/ui/views/layout/constraint-layout#constrain-to-a-guideline
</details>

huangapple
  • 本文由 发表于 2023年3月7日 01:39:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/75654079.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定