You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据接口响应动态实现巴士座位的RecyclerView网格布局?

Got it, let's fix this bus seat layout issue. The problem with RecyclerView + GridLayoutManager is that it's great for column spans but doesn't handle row spans cleanly—so using a GridLayout directly is the way to go here since it natively supports both row and column spans. Here's a step-by-step implementation:

1. First, define your Seat model

Create a data class to map the JSON response:

data class Seat(
    val column: Int,
    val length: Int, // Vertical span (number of rows the seat occupies)
    val name: String,
    val row: Int,
    val width: Int // Horizontal span (number of columns the seat occupies)
)

2. Parse the JSON response

Use Gson (or Moshi) to convert the JSON string into a list of Seat objects:

import com.google.gson.Gson

// Replace with your actual JSON string
val jsonResponse = "[...]"
val seatList = Gson().fromJson(jsonResponse, Array<Seat>::class.java).toList()

3. Set up your layout XML

Add a GridLayout to your activity/fragment layout—we'll populate it programmatically:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <GridLayout
        android:id="@+id/seatGrid"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:alignmentMode="alignMargins"
        android:useDefaultMargins="true"/>

</LinearLayout>

4. Calculate grid dimensions

First, figure out how many columns and rows we need to fit all seats (including their spans):

// Calculate total columns needed (max column + seat width)
val totalColumns = seatList.maxOf { it.column + it.width }
// Calculate total rows needed (max row + seat length)
val totalRows = seatList.maxOf { it.row + it.length }

// Set grid dimensions
seatGrid.columnCount = totalColumns
seatGrid.rowCount = totalRows

5. Dynamically add seats to the GridLayout

Create a view for each seat, set its span parameters, and add it to the grid. We'll use a Button for simplicity, but you can use a custom CardView if you want more styling:

// Define dimensions (adjust these values to fit your design)
val seatMargin = resources.getDimensionPixelSize(R.dimen.seat_margin) // e.g., 4dp
val seatTextSize = 12f

seatList.forEach { seat ->
    val seatButton = Button(this).apply {
        text = seat.name
        textSize = seatTextSize
        gravity = Gravity.CENTER
        // Set custom background (create a selector drawable for different states)
        background = ContextCompat.getDrawable(this@MainActivity, R.drawable.seat_background)
        // Handle seat clicks
        setOnClickListener {
            it.isSelected = !it.isSelected
            // Add your selection logic here
        }
    }

    // Configure GridLayout parameters with spans
    val layoutParams = GridLayout.LayoutParams().apply {
        // Set column span: start at seat.column, span seat.width columns
        columnSpec = GridLayout.spec(seat.column, seat.width, 1f)
        // Set row span: start at seat.row, span seat.length rows
        rowSpec = GridLayout.spec(seat.row, seat.length, 1f)
        // Make seats responsive (fill available space)
        width = 0
        height = 0
        // Add margins between seats
        marginStart = seatMargin
        marginEnd = seatMargin
        marginTop = seatMargin
        marginBottom = seatMargin
    }

    seatButton.layoutParams = layoutParams
    seatGrid.addView(seatButton)
}

6. Add a custom seat background (optional)

Create a selector drawable to style seats for available, selected, and occupied states. Save this as res/drawable/seat_background.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true">
        <shape android:shape="rectangle">
            <solid android:color="@color/teal_200"/>
            <corners android:radius="8dp"/>
            <stroke android:width="2dp" android:color="@color/black"/>
        </shape>
    </item>
    <item android:state_enabled="false">
        <shape android:shape="rectangle">
            <solid android:color="@color/grey"/>
            <corners android:radius="8dp"/>
            <stroke android:width="2dp" android:color="@color/black"/>
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white"/>
            <corners android:radius="8dp"/>
            <stroke android:width="2dp" android:color="@color/black"/>
        </shape>
    </item>
</selector>

Why this works better than RecyclerView

GridLayout natively supports both row and column spans, which is exactly what you need for those longer seats in your layout. RecyclerView's GridLayoutManager is designed for uniform row heights, so it struggles with items that span multiple rows.

This implementation will dynamically render your seats exactly as per the JSON data, including all the spans, and it's responsive to different screen sizes.

内容的提问来源于stack exchange,提问作者Sandip Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:48:42