使用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
相关产品推荐
相关产品推荐

