Android对话框切换崩溃:需调用removeView()解决视图父容器冲突
解决对话框重复添加View导致的崩溃问题
嘿,我一眼就瞅到问题出在哪了!你在第二个对话框的代码里犯了个常见的小错误——同一个View实例被同时设置为对话框的自定义标题和内容视图,这就导致这个View被两次添加到不同的父容器里,系统自然就抛出IllegalStateException: The specified child already has a parent这个错误了。
问题根源
你看这段代码:
View view = inflater.inflate(R.layout.dialog_call_details, null); // ... builder.setCustomTitle(view); builder.setView(view);
当你调用setCustomTitle(view)时,这个view已经被绑定到对话框的标题容器作为子View了;紧接着又调用setView(view),试图把同一个view放到内容容器里,这就违反了Android的核心规则——一个View只能隶属于一个父布局。
解决方案
有两种思路可以修复这个问题,根据你的布局需求选择:
- 如果
dialog_call_details是完整的对话框布局(包含标题+内容):只需要保留setView(view),删掉setCustomTitle(view)即可,因为整个布局会作为对话框的内容展示,不需要额外设置自定义标题。 - 如果标题和内容是分开的布局:需要分别inflate两个独立的View实例,一个用于标题,一个用于内容,避免重复使用同一个View。
针对你的代码修改
假设你的dialog_call_details是完整的对话框布局,修改后的showBusinessCallPopup代码如下:
public static void showBusinessCallPopup(final Context context, final CallLogEntry call) { if (AppPreferences.isNRF(context)) { CallItem callItem = saveCallEntry(context, call, CLASSIFICATION_TYPE_BUSINESS, "", false, ""); Intent intent = new Intent(context, CallClassificationFormActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); EventBus.getDefault().postSticky(callItem); context.startActivity(intent); return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!Settings.canDrawOverlays(context)) { Log.e(TAG, "Permission Denied: Draw overlays (for popup)"); return; } } LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.dialog_call_details, null); AlertDialog.Builder builder = new AlertDialog.Builder(context, Theme_Material_Light_Dialog_Alert); String toOrFrom = call.Type == CallLog.Calls.INCOMING_TYPE ? "from" : "to"; // 移除重复设置的自定义标题 // builder.setCustomTitle(view); builder.setCancelable(true); builder.setView(view); // 仅保留内容视图设置 final EditText etReference = (EditText)view.findViewById(R.id.etReference); final EditText etComment = (EditText)view.findViewById(R.id.etComment); builder.setPositiveButton("Confirm", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { String reference = etReference.getText().toString(); String comment = etComment.getText().toString(); saveCallEntry(context, call, CLASSIFICATION_TYPE_BUSINESS, reference, false, comment); } }); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { Log.i(TAG, "cancelled"); } }); AlertDialog dialog = builder.create(); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); dialog.show(); }
如果你的标题和内容是分开的布局,那可以这样调整:
// 分别加载标题和内容视图 View titleView = inflater.inflate(R.layout.your_title_layout, null); View contentView = inflater.inflate(R.layout.dialog_call_details, null); builder.setCustomTitle(titleView); builder.setView(contentView); // 从内容视图中获取输入框 final EditText etReference = (EditText)contentView.findViewById(R.id.etReference); final EditText etComment = (EditText)contentView.findViewById(R.id.etComment);
这样修改后,第二个对话框就能正常弹出,不会再出现崩溃啦!
内容的提问来源于stack exchange,提问作者Junta
相关产品推荐
相关产品推荐

