DialogFragment with a custom layout causes a crash in my application

回眸只為那壹抹淺笑 提交于 2019-12-22 04:08:27

问题


I have problem with Dialog fragment. Simple dialog with my custom layout is working ok. But I want to initiate controls when dialog is showing. I'm trying to do this in method onActivityCreated. But getView() return null, so I thought that I must set my custom view in onCreateView instead of onCreateDialog. And here the error occurs. When I use onCreateView then my application crashes. Here is my code:

class StatisticDialog extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder .setPositiveButton(getString(android.R.string.ok), new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // FIRE ZE MISSILES!
                   }
               });
        // Create the AlertDialog object and return it
        return builder.create();
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.statistics, container, true);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }
}

I open this dialog on button click on activity:

StatisticDialog dlg = new StatisticDialog(); 
dlg.show(getSupportFragmentManager(), "missiles");  

And errors:

11-08 18:05:14.470: E/AndroidRuntime(1075): FATAL EXCEPTION: main
11-08 18:05:14.470: E/AndroidRuntime(1075): android.util.AndroidRuntimeException: requestFeature() must be called before adding content
11-08 18:05:14.470: E/AndroidRuntime(1075):     at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:215)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at com.android.internal.app.AlertController.installContent(AlertController.java:234)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.app.AlertDialog.onCreate(AlertDialog.java:336)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.app.Dialog.dispatchOnCreate(Dialog.java:351)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.app.Dialog.show(Dialog.java:256)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.support.v4.app.DialogFragment.onStart(DialogFragment.java:385)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.support.v4.app.Fragment.performStart(Fragment.java:1336)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:907)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1083)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:635)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1431)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:420)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.os.Handler.handleCallback(Handler.java:615)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.os.Handler.dispatchMessage(Handler.java:92)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.os.Looper.loop(Looper.java:137)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at android.app.ActivityThread.main(ActivityThread.java:4745)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at java.lang.reflect.Method.invokeNative(Native Method)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at java.lang.reflect.Method.invoke(Method.java:511)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-08 18:05:14.470: E/AndroidRuntime(1075):     at dalvik.system.NativeStart.main(Native Method)

回答1:


try this:

class StatisticDialog extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(R.layout.statistics, null);
        builder.setView(view);
        builder.setPositiveButton(getString(android.R.string.ok), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                // FIRE ZE MISSILES!
            }
        });
        // Create the AlertDialog object and return it
        return builder.create();
    }
}



回答2:


Avoid request feature crash:

public class MyCombinedFragment extends DialogFragment { private boolean isModal = false;

public static MyCombinedFragment newInstance()
{
    MyCombinedFragment frag = new MyCombinedFragment();
    frag.isModal = true; // WHEN FRAGMENT IS CALLED AS A DIALOG SET FLAG
    return frag;
}

public MyCombinedFragment()
{
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{
    if(isModal) // AVOID REQUEST FEATURE CRASH
    {
    return super.onCreateView(inflater, container, savedInstanceState);
    }
    else
    {
    View view = inflater.inflate(R.layout.fragment_layout, container, false);
    setupUI(view);
    return view;
    }
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    AlertDialog.Builder alertDialogBuilder = null;
    alertDialogBuilder = new AlertDialog.Builder(getActivity());
    View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_layout, null);
    alertDialogBuilder.setView(view);
    alertDialogBuilder.setTitle(“Modal Dialog“);
    alertDialogBuilder.setPositiveButton("Cancel", new DialogInterface.OnClickListener()
    {
        @Override
        public void onClick(DialogInterface dialog, int which)
        {
            dialog.dismiss();
        }
    });
    setupUI(view);
    return alertDialogBuilder.create();
}

}




回答3:


you should use DialogFragment that is flexible to set it any layout. you should follow this steps. perhaps it is complicated but very strong and flexible. the more important things is your Activity getting Date from Dialogfragment.

1- Create a class of instance to listen and get date from your dialogfragment from your activity.I named it as OnMFDialogFragmentDoneListener.java.

2-create your DialogFragment and define your layout in onCreateView method and 3-use your class and new methods in your activity

I create a DialogFragment to get user name and password form user and delivers this date to activity.Dialog fragment contains a textview, two EditText and two buttons(Logon and cancel. but you can use anythings.

step 1: OnMFDialogFragmentDoneListener.java

public interface OnMFDialogFragmentDoneListener {

public void onMFDialogFragmentDone(String tag,boolean cancelled,
                               CharSequence username,
                               CharSequence password);
}

the method onMFDialogFragmentDone must be define in DialogFragment class to send info to yor activity and in your activity to get info.(info= the date that user typed in DialogFragmetn like txt or others).

step2 design your DialogFragment class.

  public class MFDialogFragment extends DialogFragment
    implements View.OnClickListener{


private EditText editTextusername,editTextpassword;

public static MFDialogFragment newInstance(String title){
    MFDialogFragment mfDialogFragment=new MFDialogFragment();

    Bundle bundle =new Bundle();
    bundle.putString("title",title);
    mfDialogFragment.setArguments(bundle);
    return mfDialogFragment;
}



@Override
public void onAttach(Activity act){

    try{
        OnMFDialogFragmentDoneListener
                test= (OnMFDialogFragmentDoneListener) act;
    }catch (ClassCastException cce){
        ////...activity !!!! not listen to me
    }
        super.onAttach(act);
}


@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    this.setCancelable(true);
    int style = DialogFragment.STYLE_NORMAL, theme = 0;
    setStyle(style, theme);
}

public View onCreateView(LayoutInflater inflater,
                         ViewGroup container, Bundle bundle) {

        View v = inflater.inflate(R.layout.mfdialogfragmentlayout, container,
                false);

        TextView tvtitle = (TextView) v.findViewById(R.id.tv_dialogfragmentuserpass_title);
        tvtitle.setText(getArguments().getString("title"));

        editTextusername = (EditText) v.findViewById(R.id.et_dialogfragmentuserpass_username);
        editTextpassword = (EditText) v.findViewById(R.id.et_dialogfragmentuserpass_password);


        Button btnlogin = (Button) v.findViewById(R.id.btn_dialogfragmentuserpass_login);
        btnlogin.setOnClickListener(this);
        Button btncancel = (Button) v.findViewById(R.id.btn_dialogfragmentuserpass_cancel);
        btncancel.setOnClickListener(this);


    if(bundle!=null) {
        editTextpassword.setText(bundle.getCharSequence("SaveInstanceStatepassword"));
        editTextusername.setText(bundle.getCharSequence("SaveInstanceStateusername"));
    }






    return v;
}

@Override
public void onSaveInstanceState(Bundle icicle) {
    super.onSaveInstanceState(icicle);
    icicle.putCharSequence("SaveInstanceStatepassword", editTextpassword.getText());
    icicle.putCharSequence("SaveInstanceStateusername", editTextusername.getText());

}


public void onClick(View v)
{
    OnMFDialogFragmentDoneListener act = (OnMFDialogFragmentDoneListener)getActivity();
    if (v.getId() == R.id.btn_dialogfragmentuserpass_login)
    {

        act.onMFDialogFragmentDone(this.getTag(), false,
                editTextusername.getText(),editTextpassword.getText());
        dismiss();
        return;
    }
    if (v.getId() == R.id.btn_dialogfragmentuserpass_cancel)
    {
        act.onMFDialogFragmentDone(this.getTag(), true, "nousername", "nopass");
        dismiss();
        return;
    }


}
}

step 3- use your DialogFragment in your activity first you add the code "implements OnMFDialogFragmentDoneListener" to your activity class like

public class MainActivity extends Activity
    implements OnMFDialogFragmentDoneListener

second

public static final String 
PROMPT_MFDIALOGFRAGMENT_TAG="PROMPT_MFDIALOGFRAGMENT_TAG";

third

define the method to get data that inputed to Dialogfragment by

public  void  onMFDialogFragmentDone(String tag, boolean cancelled,
                                     CharSequence username,
                                     CharSequence password){
    String total;

    total=username.toString()+"...."+password.toString();
    Toast.makeText(this,total,Toast.LengthShort).show();
}

your date are username and password next is define a simple method to call your dialog

public void MFDialogFragmentShow(){
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    MFDialogFragment mfDialogFragment =
            MFDialogFragment.newInstance("Login to your account");
    mfDialogFragment.show(ft, PROMPT_MFDIALOGFRAGMENT_TAG);

}

It's done. your frgaments layout mfdialogfragmentlayout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Title"
    android:id="@+id/tv_dialogfragmentuserpass_title"/>
<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="User Name"

    android:id="@+id/et_dialogfragmentuserpass_username"/>
<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="Password"
    android:password="true"
    android:id="@+id/et_dialogfragmentuserpass_password"/>
<LinearLayout
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Login"
        android:id="@+id/btn_dialogfragmentuserpass_login"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cancel"
        android:id="@+id/btn_dialogfragmentuserpass_cancel"/>


    </LinearLayout>
</LinearLayout>



回答4:


There is getShowDialog() method exist in DialogFragment class. Here is an explanation: developer.android.com

 if (!getShowsDialog()) {
            View rootView = inflater.inflate(R.layout.fr_layout, container, false);
            initViews(rootView);
            return rootView;
        } else {
            return super.onCreateView(inflater, container, savedInstanceState);
        }
    }


来源:https://stackoverflow.com/questions/13294030/dialogfragment-with-a-custom-layout-causes-a-crash-in-my-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!