Android Fragment添加TableRow时报The specified child already has a parent错误如何解决
错误产生原因
- 你XML布局中已经将
id=store、id=amount、id=date这三个TextView作为id=tableRowOne的子元素,同时tableRowOne本身也已经是TableLayout的子元素。所有在布局中声明的View在inflate后就已经绑定了父布局,你在结果监听中反复调用row.addView(store)、table.addView(row),相当于重复将已有父布局的View添加到新的父容器,触发了 IllegalStateException。 - 业务逻辑错误:你原本的需求是添加新的数据行,但你代码中一直复用布局里的表头行和表头TextView,没有为新数据创建独立的View实例。
- 数据接收逻辑冗余:单次点击提交的三个数据,你拆成了三个独立的FragmentResultListener接收,还分别对同一个行做添加操作,逻辑混乱。
修复方案
第一步:调整数据发送逻辑(可选,推荐)
发送数据的页面不要拆分三个requestKey发送,直接将三个参数放入同一个Bundle,用同一个requestKey发送,示例:
// 发送端代码示例 bundleOf( "bundleKeyStore" to storeText, "bundleKeyAmount" to amountText, "bundleKeyDate" to dateText ).let { setFragmentResult("requestKey", it) }
第二步:修改HistoryFragment代码
仅保留一个结果监听器,每次接收数据时动态创建新的行和TextView实例:
class HistoryFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle? ): View { val view: View = inflater.inflate(R.layout.fragment_history, container, false) val table : TableLayout = view.findViewById(R.id.tableHistorie) // 仅用一个监听器接收全部三个数据 setFragmentResultListener("requestKey") { _, bundle -> val storeName = bundle.getString("bundleKeyStore") ?: "" val amountVal = bundle.getString("bundleKeyAmount") ?: "" val dateVal = bundle.getString("bundleKeyDate") ?: "" // 动态创建新的行 val newRow = TableRow(requireContext()) // 动态创建三个TextView val tvStore = TextView(requireContext()).apply { text = storeName layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT) } val tvAmount = TextView(requireContext()).apply { text = amountVal layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT) } val tvDate = TextView(requireContext()).apply { text = dateVal layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT) } // 按顺序添加到行 newRow.addView(tvStore) newRow.addView(tvAmount) newRow.addView(tvDate) // 行添加到表格 table.addView(newRow) } return view } }
如果你坚持要保留三个独立的监听器,就需要先缓存三个接收的值,等三个值都齐了再执行一次行创建逻辑,避免重复添加不完整的行。
内容的提问来源于stack exchange,提问作者dkiwikid
相关产品推荐
相关产品推荐

