Search code examples
androidandroid-fragmentsandroid-dialogfragmentdialogfragment

How to retain customTitle in DialogFragment after screen rotation?


I created a class that extends from DialogFragment. It worked fine, until I included a customTitle to this dialog. The problem I have until now, happened when changing orientation, leading the app to crash.

FATAL EXCEPTION: main
 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.tdms.stingymoney/com.example.tdms.stingymoney.ListAccounts}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
                                                                                        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2262)
                                                                                        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2316)
                                                                                        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3828)
                                                                                        at android.app.ActivityThread.access$800(ActivityThread.java:158)
                                                                                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1302)
                                                                                        at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                        at android.os.Looper.loop(Looper.java:176)
                                                                                        at android.app.ActivityThread.main(ActivityThread.java:5365)
                                                                                        at java.lang.reflect.Method.invokeNative(Native Method)
                                                                                        at java.lang.reflect.Method.invoke(Method.java:511)
                                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
                                                                                        at dalvik.system.NativeStart.main(Native Method)
                                                                                     Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
                                                                                        at android.view.ViewGroup.addViewInner(ViewGroup.java:3566)
                                                                                        at android.view.ViewGroup.addView(ViewGroup.java:3437)
                                                                                        at android.support.v7.app.AlertController.setupTitle(AlertController.java:631)
                                                                                        at android.support.v7.app.AlertController.setupView(AlertController.java:462)
                                                                                        at android.support.v7.app.AlertController.installContent(AlertController.java:214)
                                                                                        at android.support.v7.app.AlertDialog.onCreate(AlertDialog.java:240)
                                                                                        at android.app.Dialog.dispatchOnCreate(Dialog.java:357)
                                                                                        at android.app.Dialog.onRestoreInstanceState(Dialog.java:423)
                                                                                        at android.support.v4.app.DialogFragment.onActivityCreated(DialogFragment.java:396)
                                                                                        at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1970)
                                                                                        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1092)
                                                                                        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
                                                                                        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1230)
                                                                                        at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2042)
                                                                                        at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:165)
                                                                                        at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:543)
                                                                                        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1181)
                                                                                        at android.app.Activity.performStart(Activity.java:5336)
                                                                                        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2234)
                                                                                        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2316) 
                                                                                        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3828) 
                                                                                        at android.app.ActivityThread.access$800(ActivityThread.java:158) 
                                                                                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1302) 
                                                                                        at android.os.Handler.dispatchMessage(Handler.java:99) 
                                                                                        at android.os.Looper.loop(Looper.java:176) 
                                                                                        at android.app.ActivityThread.main(ActivityThread.java:5365) 
                                                                                        at java.lang.reflect.Method.invokeNative(Native Method) 
                                                                                        at java.lang.reflect.Method.invoke(Method.java:511) 
                                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102) 
                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869) 
                                                                                        at dalvik.system.NativeStart.main(Native Method) 

I solved the crash above setting null to customTitle in onDestroyView method, but now, when changing orientation, I lose my customTitle... This is my code now:

    public class AlertDialogFragment extends DialogFragment{

        View customTitle;

public interface OnYesNoResult{
            void onDialogResult(boolean result, int requestCode);
        }

        public AlertDialogFragment(){}

        public void setCustomTitleView(View view){
            this.customTitle = view;

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstances){
            this.setRetainInstance(true);
            //
            Dialog dialog = new AlertDialog.Builder(getActivity())

                            .setTitle("title")
                            .setCustomTitle(customTitle)
                            .setMessage("message")                         
                            .create();


            return dialog;
        }


        @Override
        public void onDestroyView() {
           if (getDialog() != null && getRetainInstance())
                getDialog().setDismissMessage(null);
            super.onDestroyView();
            customTitle = null;

           if (view != null) {
                ViewGroup parentViewGroup = (ViewGroup) view.getParent();
                if (parentViewGroup != null) {
                    parentViewGroup.removeAllViews();

                }
            }
        }

    }

How can I keep my customTitle in DialogFragment, without crashing the app or losing it when changing the screen orientation?

Thanks!


Solution

  • Replace:

     if (view != null) {
                ViewGroup parentViewGroup = (ViewGroup) view.getParent();
                if (parentViewGroup != null) {
                    parentViewGroup.removeAllViews();
    
                }
            }
        }
    

    To

    if(customTitle.getParent()!=null)
    ((ViewGroup)customTitle.getParent()).removeView(customTitle);