I am working with an application that involves to dialog boxes that should appear one after the other. What I mean is that, when I click on the positive button of the first dialog box it should then bring up another second dialog box. The issue I am facing is with the second dialog box, the second one will not pop up and it causes the application to crash.
I get an error that says "java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first."
public static void showBusinessOrPrivateStartDialog(final Context context, final CallLogEntry call)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
// If new version of android, then check permission
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_type, null);
AlertDialog.Builder builder = new AlertDialog.Builder(context, Theme_Material_Light_Dialog_Alert);
builder.setTitle("Was this a private or a business call?");
builder.setMessage("Please select a call type");
builder.setIcon(R.drawable.ic_deviceinsight);
builder.setCancelable(true);
//builder.setView(view);
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
// Occurs when user cancels the dialog, or clicks somewhere else in the screen or presses the back button
Log.i(TAG, "cancelled");
saveCallEntry(context, call, CLASSIFICATION_TYPE_BUSINESS, "", true, "");
}
});
builder.setPositiveButton("Business", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
CallClassification.showBusinessCallPopup(context, call);
}
});
builder.setNegativeButton("Private", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
saveCallEntry(context, call, CLASSIFICATION_TYPE_PRIVATE, "", false, "");
}
});
AlertDialog dialog = builder.create();
// Rather use something like TYPE_SYSTEM_ALERT, if possible.
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); // TYPE_SYSTEM_ERROR
dialog.show();
}
This is the second method for the second dialog box and my app crashes on dialog.show
public static void showBusinessCallPopup(final Context context, final CallLogEntry call)
{
// NEW NRF
if (AppPreferences.isNRF(context)) {
CallItem callItem = saveCallEntry(context, call, CLASSIFICATION_TYPE_BUSINESS, "", false, "");
// SHOW NEW FORM
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 new version of android, then check permission
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.setTitle("Business call");
builder.setCustomTitle(view);
//builder.setMessage("Please enter reference details for the call " + toOrFrom + " " + call.Number);
//builder.setIcon(R.drawable.ic_deviceinsight);
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); // TYPE_SYSTEM_ERROR
dialog.show();
}
and here is my xml. I have included the xml in this post because I read somewhere that the way the height and width of my textboxes is defined might be causing an issue.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="5dp"
tools:context=".calls.CallClassification">
<TextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:padding="5dp"
android:text="Please enter reference details for the call "
android:textColor="@color/colorPrimaryDark"
android:textSize="16sp"/>
<AutoCompleteTextView
android:id="@+id/etReference"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@color/colorAccent"
android:hint="Matter Code *"
android:imeOptions="actionNext"
android:inputType="text"
android:maxLength="255"
android:text=""
android:textColor="@color/colorPrimary"
android:textColorHint="@color/colorTextHint"
android:textSize="14sp"/>
<CheckBox
android:id="@+id/cbBillable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:button="@null"
android:buttonTint="@color/colorAccent"
android:checked="true"
android:drawableRight="?android:attr/listChoiceIndicatorMultiple"
android:paddingBottom="3dp"
android:paddingTop="3dp"
android:text="Billable"
android:textColor="@color/colorPrimaryDark"
android:textSize="14sp"/>
<EditText
android:id="@+id/etComment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@color/colorAccent"
android:hint="Enter comment"
android:imeOptions="actionDone"
android:inputType="text"
android:lines="1"
android:maxLength="1000"
android:maxLines="4"
android:minLines="1"
android:text=""
android:textColor="@color/colorPrimary"
android:textColorHint="@color/colorTextHint"
android:textSize="14sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/bCancel"
style="@style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Cancel"/>
<Button
android:id="@+id/bOk"
style="@style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="GO"/>
</LinearLayout>
</LinearLayout>
After hearing to your experience, I could think of one more solution. Rather than declaring AlertDialog variable inside each of the methods, declare one global variable so that you can make sure that only one Dialog is shown at any instance.
While declaring, make
AlertDialog dialog = null;
in class Then in,
showBusinessOrPrivateStartDialog() {
if(dialog == null) {
dialog = build.create();
}
}
builder.setPositiveButton("Business", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
CallClassification.showBusinessCallPopup(context, call);
}
});
builder.setOnDismissListener(new OnDismissListener() {
public void onDismiss() {
dialog = null;
}
}
Then again in showBusinessCallPopup(),
if(dialog == null) {
dialog = build.create();
}
Hope this helps you.