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

使用Kotlin和XML无法动态添加布局元素的问题求助

问题

尝试将单独定义的布局元素动态添加到页面中,预先不知道需要添加的数量,且每个元素的ImageView和TextView内容需在后端定义。尝试多种实现方式均未成功,运行后仅左上角显示一个元素(需为ImageView设置android:src才会显示)。

Kotlin代码

private lateinit var adapter: ArrayAdapter<*>

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    adapter = ArrayAdapter(this,android.R.layout.simple_list_item_1, resources.getStringArray(R.array.countries_array))
    val gridScreen = findViewById<GridLayout>(R.id.grid_screen)
    for(i in 1..4){
        val gridItem = layoutInflater.inflate(R.layout.container, null)
        //val gridItem = LayoutInflater.from(this).inflate(R.layout.container,null)
        //gridItem.id = View.generateViewId() ###this did not work
        val image1 = gridItem.findViewById<ImageView>(R.id.image_1) 
        //these images exist in this folder by this name
        image1.setImageResource(R.drawable.image1)
        //...etc for each element

        val text = gridItem.findViewById<TextView>(R.id.category)
        text.text = "Text for item $i"
        print(text.text)
        gridScreen.addView(gridItem)
    }
}

主布局XML(activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<android.widget.GridLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="150sp"
        android:layout_height="150sp"
        android:minWidth="160sp"
        android:maxWidth="160sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        tools:context=".MainActivity"
        android:id="@+id/grid_screen">

    <include
            android:id="@+id/container_include"
            layout="@layout/container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tv_emptyTextView"
            android:text="No result"
            android:layout_centerInParent="true"
            android:textSize="20sp"
            android:visibility="gone"/>

</android.widget.GridLayout>

待添加的container布局(container.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container"
              android:layout_width="150sp"
              android:layout_height="160sp"
              android:orientation="vertical">

        <LinearLayout
                android:layout_width="140sp"
                android:layout_height="70sp"
                android:orientation="horizontal">

            <ImageView
                    android:id="@+id/image_1"
                    android:layout_width="70sp"
                    android:layout_height="65sp"
                    android:layout_gravity="center"
                    android:layout_weight="1"
                    android:adjustViewBounds="true"/>

            <ImageView
                    android:id="@+id/image_2"
                    android:layout_width="70sp"
                    android:layout_height="65sp"
                    android:layout_gravity="center"
                    android:layout_weight="1"
                    android:adjustViewBounds="true"/>
        </LinearLayout>
    <LinearLayout
            android:layout_width="140sp"
            android:layout_height="70sp"
            android:orientation="horizontal">

        <ImageView
                android:id="@+id/image_3"
                android:layout_width="70sp"
                android:layout_height="65sp"
                android:layout_gravity="center"
                android:layout_weight="1"
                android:adjustViewBounds="true"/>

        <ImageView
                android:id="@+id/image_4"
                android:layout_width="70sp"
                android:layout_height="65sp"
                android:layout_gravity="center"
                android:layout_weight="1"
                android:adjustViewBounds="true"/>
    </LinearLayout>

    <TextView
            android:id="@+id/category"
            android:layout_width="wrap_content"
            android:layout_height="15sp"
            android:textSize="10sp"
            android:layout_gravity="center"
            android:text="Cathegory"/>

</LinearLayout>
修复建议

1. 修正GridLayout的尺寸与布局属性

主布局中GridLayout的layout_width、layout_height设置为150sp,且限制了maxWidth为160sp,导致容器尺寸过小无法容纳多个元素。修改为:

<android.widget.GridLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:columnCount="2" <!-- 自定义列数,按需调整 -->
        android:alignmentMode="alignMargins"
        android:columnOrderPreserved="false"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        tools:context=".MainActivity"
        android:id="@+id/grid_screen">

2. 正确Inflate布局并传递父布局参数

动态加载布局时,必须传入父布局并设置attachToRoot=false,这样系统会自动生成GridLayout所需的LayoutParams,避免元素重叠或排列异常:

val gridItem = layoutInflater.inflate(R.layout.container, gridScreen, false)

3. 移除冗余的标签

主布局中的<include>标签属于冗余内容,代码已动态添加container布局,保留它会额外显示一个默认元素,直接删除即可。

4. 修正布局单位问题

布局中使用sp作为View宽高单位是错误的,sp仅用于字体大小,View尺寸应使用dp:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container"
              android:layout_width="150dp"
              android:layout_height="160dp"
              android:orientation="vertical">

        <LinearLayout
                android:layout_width="140dp"
                android:layout_height="70dp"
                android:orientation="horizontal">

5. 推荐改用RecyclerView + GridLayoutManager(更适合动态数量场景)

如果元素数量不确定,直接往GridLayout添加View的性能较差,RecyclerView支持View复用,更适合这类场景:

步骤1:修改主布局为RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        android:id="@+id/recycler_grid"/>

步骤2:创建数据类

data class GridItem(
    val imageIds: List<Int>, // 每个item的4张图片资源ID
    val categoryText: String
)

步骤3:实现RecyclerView Adapter

class GridAdapter(private val items: List<GridItem>) : RecyclerView.Adapter<GridAdapter.ViewHolder>() {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val image1: ImageView = itemView.findViewById(R.id.image_1)
        val image2: ImageView = itemView.findViewById(R.id.image_2)
        val image3: ImageView = itemView.findViewById(R.id.image_3)
        val image4: ImageView = itemView.findViewById(R.id.image_4)
        val categoryText: TextView = itemView.findViewById(R.id.category)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.container, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = items[position]
        holder.image1.setImageResource(item.imageIds[0])
        holder.image2.setImageResource(item.imageIds[1])
        holder.image3.setImageResource(item.imageIds[2])
        holder.image4.setImageResource(item.imageIds[3])
        holder.categoryText.text = item.categoryText
    }

    override fun getItemCount() = items.size
}

步骤4:在Activity中初始化RecyclerView

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val recyclerView = findViewById<RecyclerView>(R.id.recycler_grid)
    // 设置Grid布局管理器,2列
    recyclerView.layoutManager = GridLayoutManager(this, 2)
    // 模拟后端返回的数据
    val items = listOf(
        GridItem(listOf(R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4), "Text for item 1"),
        GridItem(listOf(R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4), "Text for item 2"),
        GridItem(listOf(R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4), "Text for item 3"),
        GridItem(listOf(R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4), "Text for item 4")
    )
    recyclerView.adapter = GridAdapter(items)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 03:10:01