52

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.

Gaurav Vashisth
  • 7,547
  • 8
  • 35
  • 56
  • Have you found a solution for this in the meantime? – Thomas Keller Aug 29 '12 at 11:24
  • 1
    According to latest documentation once you override `onCreateDialog`, `onCreateView` won't be called same as `onViewCreated` https://developer.android.com/reference/android/app/DialogFragment#onCreateDialog(android.os.Bundle) – john-salib Mar 26 '19 at 09:04

6 Answers6

30

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()
    }
}
Carson Holzheimer
  • 2,890
  • 25
  • 36
  • 2
    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 `onCreateView` – GenError Apr 16 '22 at 15:46
  • 1
    "dialogView" is non-null type can not be set to null in onDestroyView. BTW, this line of code seem to be unnecessary. – qianlv Jun 01 '22 at 07:52
  • didnt work for me.. but using view binding with this technique just work.. i dont know why – Kakaranara Apr 29 '23 at 04:14
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).

Barak
  • 16,318
  • 9
  • 52
  • 84
  • my problem is something like this http://stackoverflow.com/questions/7692713/onviewcreated-with-compatibility-library but the solution is'nt working – Gaurav Vashisth May 15 '12 at 07:33
  • 11
    `onCreateView` is fired when building a DialogFragment, even when also using `onCreateDialog`. Still, `onViewCreated` is not fired when building a DialogFragment. Odd behavior. – losttime Apr 05 '13 at 06:36
  • dialogfragment use onCreateView when super.onCreateDialog is returned. – njzk2 Feb 04 '14 at 22:03
  • 7
    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)... – Eugene Jul 22 '15 at 15:45
  • onViewCreated() is called in some fragments and for some other fragments it is not. Strange behavior. – Kusal Dissanayake Feb 02 '18 at 04:49
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;
}
bcorso
  • 45,608
  • 10
  • 63
  • 75
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"

vinc3m1
  • 4,075
  • 1
  • 26
  • 23
  • 2
    The only problem with this approach is if you're embeddeding the `DialogFragment`; in this case, `onViewCreated` would be called twice. – Oleg Vaskevich Jun 15 '14 at 16:37
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; 
    }
diferno
  • 114
  • 4
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.

Pepijn
  • 1,439
  • 17
  • 16