【问题标题】:Showing variable number of items in row in Recycler view在 Recycler 视图中显示可变数量的项目
【发布时间】:2021-05-04 08:54:16
【问题描述】:

我已经设置了视图模型、实时数据、回收器视图、适配器和视图持有者来呈现以下 JSON 响应。有效负载还有其他属性,但与widthUnit 相比,它们并不那么重要。

{
    "canvasUnit": 16,
    "specials": [{
            "display_name": "Noodle Dish with Roasted Black Bean Sauce",
            "heightUnit": 8,
            "widthUnit": 16
        },
        {
            "display_name": "Onion Flavored Rings",
            "heightUnit": 8,
            "widthUnit": 8
        },
        {
            "display_name": "Kikkoman Less Sodium Soy Sauce",
            "heightUnit": 8,
            "widthUnit": 8
        },
        {
            "display_name": "Organic Romaine Hearts",
            "heightUnit": 4,
            "widthUnit": 14
        },
        {
            "display_name": "Navel Oranges 4LBS",
            "heightUnit": 6,
            "widthUnit": 4
        },
    {
      "display_name": "Doritos Ranch", 
      "heightUnit": 6, 
      "widthUnit": 4
    }, 
    {
      "display_name": "Lindt Hello Cookies & Cream 1.4 oz", 
      "heightUnit": 6, 
      "widthUnit": 4
    }
    ]
}

根据widthUnitcanvasUnit 的比率,我需要在同一行上拥有可变数量的视图。在此示例中,第一行的比率为 16 / 16 = 1。所以第一行应该显示与第一行相关的条目

接下来的两个 JSON 对象的值为 widthUnit 为 8。因此它们与 maxUnit 的比率为 0.5,这意味着我需要在第二行显示接下来的两个项目。

同样,由于接下来的 4 个条目的累积宽度为 16,因此应在第 3 行显示 4 个条目。

所以最终的布局应该是这样的

---------------------------------
|                                |
| -----------------------------  |
| |                            | |
| |          entry # 1         | |
| |                            | |
| ------------------------------ |
| 
|  ------------    ------------  |
| | entry # 2  |   | entry # 3 | |
|  -------------    -----------  |
|  ----   ----     ----  -----   |
| | #4 | | #5 |  | #6 | | #7  |  |
|  ----    ---    ----   -----   |
 ---------------------------------   

我该如何完成这样的事情?我试过像这样使用 FlexLayoutManager

在我的活动的onCreate 函数中,

我已经初始化了适配器,如下

val recyclerAdapter = RecyclerAdapter(this)  // Passing the context to the adapter.
val recyclerView = findViewById(R.id.recycler_view)
with(recyclerView) {
            val flexboxLayoutManager = FlexboxLayoutManager(this@MyActivity).apply {
                flexDirection = FlexDirection.ROW
                justifyContent = JustifyContent.FLEX_START
                flexWrap = FlexWrap.WRAP
            }
            layoutManager = flexboxLayoutManager
            adapter = recyclerAdapter
            setHasFixedSize(true)
        }

适配器代码

class RecyclerAdapter(
    private val context: Context
): RecyclerView.Adapter<ViewHolder>() {

    var item: Item? = null;

    override fun getItemCount(): Int = item?.specials?.size ?: 0

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val itemBinding: ItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.item, parent, false)
        return ViewHolder(context, itemBinding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bindViewHolder(item?.specials?.get(position), item?.canvasUnit)
    }
}

ViewHolder

class ViewHolder(
    private val context: Context,
    private val itemBinding: ItemBinding,
): RecyclerView.ViewHolder(
    itemBinding.root
) {

    fun bindViewHolder(special: Specials?, canvasUnit: Int?) {
        special ?: return
        canvasUnit ?: return
        itemBinding.special = special
        itemBinding.executePendingBindings()
    }
}

布局

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="android.view.View"/>
        
        <variable
            name="special"
            type="com.myproject.mobile.model.Specials" />
    </data>

    <androidx.cardview.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/standardMargin2x"
        android:padding="@dimen/standardMargin2x"
        style="@style/CardView"
        android:visibility="@{special != null ?  View.VISIBLE : View.GONE}">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/standardMargin"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/product_image_url"
                android:layout_width="@dimen/product_image_width"
                android:layout_height="@dimen/product_image_height"
                android:importantForAccessibility="no"
                android:layout_alignParentStart="true"
                android:scaleType="fitCenter"
                android:contentDescription="@null"
                android:layout_marginEnd="@dimen/standardMargin2x"
                app:imageUrl="@{special.imageUrl}" />

            <LinearLayout
                android:id="@+id/product_price_container"
                android:layout_marginStart="@dimen/standardMargin2x"
                android:layout_marginBottom="@dimen/standardMargin2x"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toEndOf="@+id/product_image_url"
                android:layout_alignParentEnd="true"
                android:layout_alignWithParentIfMissing="true"
                android:orientation="vertical"
                android:layout_marginEnd="@dimen/standardMargin2x"
                android:gravity="end">

                <TextView
                    android:id="@+id/product_original_price"
                    android:layout_marginBottom="@dimen/standardMargin"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/strikethrough"
                    android:textAppearance="@style/TextAppearance"
                    app:inUSD="@{special.originalPrice}"
                    tools:text="$5.00"/>

                <TextView
                    android:id="@+id/product_price"
                    android:layout_marginBottom="@dimen/standardMargin"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAppearance="@style/TextAppearance.Secondary"
                    app:inUSD="@{special.price}"

                    tools:text="$5.00"/>
            </LinearLayout>
            <TextView
                android:id="@+id/product_display_name"
                android:layout_width="@dimen/text_display_width"
                android:layout_height="wrap_content"
                android:gravity="center|center_vertical"
                android:layout_centerHorizontal="true"
                android:layout_below="@id/product_price_container"
                android:maxLines="2"
                android:ellipsize="end"
                android:text="@{special.displayName}"
                android:textAppearance="@style/TextAppearance.Bold"
                tools:text="Onion flavoured rings"
                />
        </RelativeLayout>

    </androidx.cardview.widget.CardView>
</layout>

数据在卡片视图中呈现如下

但我希望根据我的要求呈现条目。我怎样才能实现这样的事情?我试过浏览以下帖子

  1. RecyclerView with StaggeredGridLayoutManager : variable number of columns and vertically scrollable

【问题讨论】:

    标签: android android-recyclerview


    【解决方案1】:

    我认为你需要使用网格布局并通过计算比率来动态设置项目数。

    就像首先计算用户设备的屏幕尺寸,因为你知道一行应该显示多少个项目,假设 8+8 = 16,那么你需要显示 2 个项目。

    所以,设置每个项目布局的宽度 = total_screen_size/ num_of_items_to_be_shown {这里你可以根据需要考虑一些边距}

    然后相应地设置网格项数。

    【讨论】:

    • 您能粘贴某种代码 sn-p 吗?我不太明白你的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2014-06-13
    • 1970-01-01
    相关资源
    最近更新 更多