Android DialogFragment onViewCreated not called
Asked Answered
L

6

55

I am using android compatibility library (v4 revision 8). In the custom DialogFragment the overrided method onViewCreated is not getting called.For eg.

public class MyDialogFragment extends DialogFragment{
    private String mMessage;
    public MyDialogFragment(String message) {
        mMessage = message;
    }

    @Override
    public Dialog onCreateDialog( Bundle savedInstanceState){
        super.onCreateDialog(savedInstanceState);
        Log.d("TAG", "onCreateDialog");
        setRetainInstance(true); 
        //....do something
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        Log.d("TAG", "onViewCreated");
        //...do something
    }
}

onViewCreated is not getting logged.

Lalo answered 15/5, 2012 at 6:5 Comment(2)
Have you found a solution for this in the meantime?Jammie
According to latest documentation once you override onCreateDialog, onCreateView won't be called same as onViewCreated developer.android.com/reference/android/app/…Albinus
O
34

This is how I make sure onViewCreated is called in kotlin:

class MyDialog: DialogFragment() {

    private lateinit var dialogView: View

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        dialogView = LayoutInflater.from(context).inflate(R.layout.dialog, null)
        val dialog = MaterialAlertDialogBuilder(context!!)
                .setView(dialogView)
                .create()

        return dialog
    }

    // Need to return the view here or onViewCreated won't be called by DialogFragment, sigh
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return dialogView
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // Yay it's now called!
    }

    override fun onDestroyView() {
        dialogView = null
        super.onDestroyView()
    }
}
Odetteodeum answered 5/9, 2019 at 3:18 Comment(3)
Thank you! This works flawlessly and makes it very easy to add flow collectors to onViewCreated! Minor change I made: since I use view binding, I don't need the additional val, I can just return binding.root in onCreateViewCoffeepot
"dialogView" is non-null type can not be set to null in onDestroyView. BTW, this line of code seem to be unnecessary.Woolsey
didnt work for me.. but using view binding with this technique just work.. i dont know whySeveren
A
26

Well, the docs for onViewCreated state "Called immediately after onCreateView(LayoutInflater, ViewGroup, Bundle) has returned".

DialogFragment uses onCreateDialog and not onCreateView, so onViewCreated is not fired. (Would be my working theory, I haven't dived into the android source to confirm).

Analysand answered 15/5, 2012 at 6:20 Comment(5)
my problem is something like this #7693213 but the solution is'nt workingLalo
onCreateView is fired when building a DialogFragment, even when also using onCreateDialog. Still, onViewCreated is not fired when building a DialogFragment. Odd behavior.Recognizance
dialogfragment use onCreateView when super.onCreateDialog is returned.Enlil
I'm just curious why it is so hard to override the onViewCreated() for DialogFragment and throw a RuntimeException so developers know this method is not a part of Dialog (who extends Fragment)...Toothwort
onViewCreated() is called in some fragments and for some other fragments it is not. Strange behavior.Whitmore
V
15

You can see what's happening from the source code:

First, since you don't override onCreateView() your fragment's view will be null. This can be seen from the source code of Fragment -- the default returns null:

// android.support.v4.app.Fragment.java
@Nullable
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
        @Nullable Bundle savedInstanceState) {
    return null;
}

Second, since you're view is null the FragmentManager will not call onViewCreated(). From the source code of FragmentManager:

// android.support.v4.app.FragmentManager.java
if (f.mView != null) {
    f.mInnerView = f.mView;
    // ... 

    // only called if the fragments view is not null!
    f.onViewCreated(f.mView, f.mSavedFragmentState);
} else {
    f.mInnerView = null;
}
Verona answered 24/11, 2015 at 18:15 Comment(0)
F
13

From my testing, onViewCreated isn't called if onCreateView returns null, which is the default behavior, so if you're not using onCreateView but manually calling setContentView in onCreateDialog, you can manually call onViewCreated from onCreateDialog:

@Override public Dialog onCreateDialog(Bundle savedInstanceState) {
    final Dialog d = super.onCreateDialog(savedInstanceState);
    d.setContentView(R.layout.my_dialog);
    // ... do stuff....
    onViewCreated(d.findViewById(R.id.dialog_content), savedInstanceState);
    return d;
}

In this case, make sure the root element in my_dialog.xml has android:id="@+id/dialog_content"

Fattal answered 24/2, 2014 at 17:49 Comment(1)
The only problem with this approach is if you're embeddeding the DialogFragment; in this case, onViewCreated would be called twice.Alfreda
Q
2

According to the doc (Selecting Between Dialog or Embedding) and having it tested by myself, you can override OnCreateView, inflate it with your custom layout and return it. OnViewCreated will be launched

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
           View view = inflater.inflate(R.layout.custom_layout, null);
           //do whatever        
           return view; 
    }
Quirinal answered 3/6, 2014 at 7:27 Comment(0)
H
1

The documentation states that onCreateDialog will be called before onCreateView (DialogFragment documentation) and onCreateView will be called before onActivityCreated (Fragment documentation. Therefore this would be the flow of calls:

onCreate
onCreateDialog
onCreateView
onActivityCreated

So do what you would do in OnViewCreated in onActivityCreated and you should be set.

Haemoid answered 3/11, 2020 at 10:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.