46

我正在使用 android 兼容性库(v4 修订版 8)。在自定义 DialogFragment 中,未调用覆盖的方法 onViewCreated。例如。

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 没有被记录。

4

6 回答 6

22

好吧,onViewCreated 状态的文档“在 onCreateView(LayoutInflater, ViewGroup, Bundle) 返回后立即调用”。

DialogFragment 使用 onCreateDialog 而不是 onCreateView,因此不会触发 onViewCreated。(这将是我的工作理论,我还没有深入到 android 源来确认)。

于 2012-05-15T06:20:03.953 回答
14

这就是我确保在 kotlin 中调用 onViewCreated 的方式:

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()
    }
}
于 2019-09-05T03:18:51.900 回答
13

根据我的测试,onViewCreated如果 onCreateView 返回 null 则不会调用,这是默认行为,因此如果您不使用 onCreateView 而是手动调用setContentViewin onCreateDialog,则可以手动调用onViewCreatedfrom 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;
}

在这种情况下,请确保其中的根元素my_dialog.xmlandroid:id="@+id/dialog_content"

于 2014-02-24T17:49:39.717 回答
11

您可以从源代码中看到发生了什么:

首先,因为你不覆盖onCreateView()你的片段的视图将是空的。这可以从——默认返回的源码Fragmentnull中看出:

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

其次,由于您的 view 为 null ,FragmentManager因此不会调用onViewCreated(). 从源代码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;
}
于 2015-11-24T18:15:29.050 回答
2

根据文档(Selecting Between Dialog or Embedding)并由我自己测试,您可以覆盖 OnCreateView,使用您的自定义布局对其进行膨胀并返回它。OnViewCreated 将启动

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
           View view = inflater.inflate(R.layout.custom_layout, null);
           //do whatever        
           return view; 
    }
于 2014-06-03T07:27:09.407 回答
0

该文档指出 onCreateDialog 将在 onCreateView (DialogFragment 文档)之前调用,onCreateView 将在 onActivityCreated (片段文档)之前调用。因此这将是调用流程:

onCreate
onCreateDialog
onCreateView
onActivityCreated

因此,请在 onActivityCreated 中执行您在 OnViewCreated 中执行的操作,您应该已设置好。

于 2020-11-03T10:57:36.140 回答