Android ViewGroup.addView()调用成功但子View不显示如何解决
问题根因
动态添加的TextView不显示和sleep_records_container容器高度无关,核心错误是动态创建控件时的宽高设置方式不对:
- 你直接调用
startSleepTextView.width = LayoutParams.WRAP_CONTENT、startSleepTextView.height = LayoutParams.WRAP_CONTENT是无效写法。View类的width/height属性只接收实际像素尺寸值,而LayoutParams.WRAP_CONTENT的常量值为-2,直接赋值相当于把控件宽高设为-2px,控件测量后实际尺寸为0,自然无法渲染显示。 - 所有布局规则类参数(包括WRAP_CONTENT、MATCH_PARENT、边距、对齐规则等),必须通过控件的
LayoutParams对象设置,不能直接赋值给View的宽高属性。 - 额外隐患:你创建的内层包裹用
sleepRecordLinearLayout也没有设置合法的布局参数,同时观察LiveData时用this作为生命周期宿主,在Fragment销毁视图时会有内存泄漏风险。
修复方案
将观察oneMonthSleepRecords的代码替换为如下正确实现即可:
// 注意这里把this替换成viewLifecycleOwner,适配Fragment视图生命周期 sleepRecordViewModel.oneMonthSleepRecords.observe(viewLifecycleOwner, Observer { oneMonthSleepRecords -> Log.i("SleepRecordFragment", "oneMonthSleepRecords.size: ${oneMonthSleepRecords.size}") binding.sleepRecordsContainer.removeAllViews() oneMonthSleepRecords.forEach { sleepRecord -> Log.i("SleepRecordFragment", "Observe oneMonthSleepRecords: ${sleepRecord.toString()}") // 创建TextView,通过LayoutParams设置宽高规则 val startSleepTextView = TextView(requireContext()).apply { val startSleepDate = Date(sleepRecord.startTimeMilli) // 显式传入Locale,避免区域设置导致的日期格式异常 val formatter = SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault()) val startSleepText = getString(R.string.start_sleep_datetime, formatter.format(startSleepDate)) text = startSleepText // 注意:LayoutParams的类型要和父容器类型匹配,父容器是LinearLayout就用LinearLayout.LayoutParams layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT ) Log.i("SleepRecordFragment", "start sleep text: ${startSleepText}") } // 创建内层包裹的垂直线性布局,同样设置合法LayoutParams val sleepRecordLinearLayout = LinearLayout(requireContext()).apply { orientation = LinearLayout.VERTICAL layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT ) addView(startSleepTextView) } binding.sleepRecordsContainer.addView(sleepRecordLinearLayout) } Log.i("SleepRecordFragment", "size in sleep record container: ${binding.sleepRecordsContainer.size}") })
修改后重新运行即可看到动态添加的睡眠记录文本,不需要修改现有XML布局的容器高度配置。
内容的提问来源于stack exchange,提问作者リョウタ
相关产品推荐
相关产品推荐

