简体   繁体   English

从片段显示对话框?

[英]Show dialog from fragment?

I have some fragments that need to show a regular dialog. 我有一些需要显示常规对话框的片段。 On these dialogs the user can choose a yes/no answer, and then the fragment should behave accordingly. 在这些对话框中,用户可以选择是/否答案,然后片段应该相应地运行。

Now, the Fragment class doesn't have an onCreateDialog() method to override, so I guess I have to implement the dialogs outside, in the containing Activity . 现在, Fragment类没有要覆盖的onCreateDialog()方法,所以我想我必须在包含Activity外部实现对话框。 It's ok, but then the Activity needs to report back the chosen answer somehow to the fragment. 没关系,但是Activity需要以某种方式向片段报告所选择的答案。 I could of course use a callback pattern here, so the fragment registers itself at the Activity with a listener class, and the Activity would report back the answer thru that, or something like that. 我当然可以在这里使用一个回调模式,因此片段在Activity使用一个监听器类来注册它,而Activity会通过它报告回答,或类似的东西。

But this seems to be quite a big mess for a simple task as displaying a "simple" yes-no dialog in a fragment. 但对于一个简单的任务来说,这似乎是一个相当大的混乱,因为在一个片段中显示一个“简单的”是 - 否对话框。 Also, this way my Fragment would be less self-contained. 而且,这样我的Fragment就不那么自足了。

Is there some cleaner way to do this? 有没有更清洁的方法来做到这一点?

Edit: 编辑:

The answer to this question doesn't really explain in detail how one should use DialogFragments to display dialogs from Fragments. 这个问题的答案并没有真正详细解释如何使用DialogFragments来显示Fragments中的对话框。 So AFAIK, the way to go is: 所以AFAIK,走的路是:

  1. Display a Fragment. 显示片段。
  2. When needed, instantiate a DialogFragment. 需要时,实例化DialogFragment。
  3. Set the original Fragment as the target of this DialogFragment, with .setTargetFragment() . 使用.setTargetFragment()将原始Fragment设置为此DialogFragment的目标。
  4. Show the DialogFragment with .show() from the original Fragment. 使用原始片段中的.show()显示DialogFragment。
  5. When the user chooses some option on this DialogFragment, notify the original Fragment about this selection (eg the user clicked 'yes'), you can get the reference of the original Fragment with .getTarget(). 当用户在此DialogFragment上选择一些选项时,通知原始片段有关此选择(例如,用户单击“是”),您可以使用.getTarget()获取原始片段的引用。
  6. Dismiss the DialogFragment. 关闭DialogFragment。

您应该使用DialogFragment

I must cautiously doubt the previously accepted answer that using a DialogFragment is the best option. 我必须谨慎怀疑以前接受的答案,即使用DialogFragment是最佳选择。 The intended (primary) purpose of the DialogFragment seems to be to display fragments that are dialogs themselves, not to display fragments that have dialogs to display. DialogFragment的预期(主要)目的似乎是显示对话框本身的片段, 不是显示具有要显示的对话框的片段。

I believe that using the fragment's activity to mediate between the dialog and the fragment is the preferable option. 我相信使用片段的活动在对话框和片段之间进行调解是更好的选择。

Here is a full example of a yes/no DialogFragment: 以下是是/否DialogFragment的完整示例:

The class: 班级:

public class SomeDialog extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
            .setTitle("Title")
            .setMessage("Sure you wanna do this!")
            .setNegativeButton(android.R.string.no, new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // do nothing (will close dialog)
                }
            })
            .setPositiveButton(android.R.string.yes,  new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // do something
                }
            })
            .create();
    }
}

To start dialog: 要开始对话:

        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        // Create and show the dialog.
        SomeDialog newFragment = new SomeDialog ();
        newFragment.show(ft, "dialog");

You could also let the class implement onClickListener and use that instead of embedded listeners. 您还可以让该类实现onClickListener并使用它而不是嵌入式侦听器。

Callback to Activity 回调活动

If you want to implement callback this is how it is done In your activity: 如果你想实现回调,这就是你的活动:

YourActivity extends Activity implements OnFragmentClickListener

and

@Override
public void onFragmentClick(int action, Object object) {
    switch(action) {
        case SOME_ACTION:
        //Do your action here
        break;
    }
}

The callback class: 回调类:

public interface OnFragmentClickListener {
    public void onFragmentClick(int action, Object object);
}

Then to perform a callback from a fragment you need to make sure the listener is attached like this: 然后,要从片段执行回调,您需要确保侦听器附加如下:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnFragmentClickListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement listeners!");
    }
}

And a callback is performed like this: 并且执行回调如下:

mListener.onFragmentClick(SOME_ACTION, null); // null or some important object as second parameter.

For me, it was the following- 对我来说,是以下 -

MyFragment: MyFragment:

public class MyFragment extends Fragment implements MyDialog.Callback
{
    ShowDialog activity_showDialog;

    @Override
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);
        try
        {
            activity_showDialog = (ShowDialog)activity;
        }
        catch(ClassCastException e)
        {
            Log.e(this.getClass().getSimpleName(), "ShowDialog interface needs to be     implemented by Activity.", e);
            throw e;
        }
    }

    @Override
    public void onClick(View view) 
    {
        ...
        MyDialog dialog = new MyDialog();
        dialog.setTargetFragment(this, 1); //request code
        activity_showDialog.showDialog(dialog);
        ...
    }

    @Override
    public void accept()
    {
        //accept
    }

    @Override
    public void decline()
    {
        //decline
    }

    @Override
    public void cancel()
    {
        //cancel
    }

}

MyDialog: MyDialog:

public class MyDialog extends DialogFragment implements View.OnClickListener
{
    private EditText mEditText;
    private Button acceptButton;
    private Button rejectButton;
    private Button cancelButton;

    public static interface Callback
    {
        public void accept();
        public void decline();
        public void cancel();
    }

    public MyDialog()
    {
        // Empty constructor required for DialogFragment
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View view = inflater.inflate(R.layout.dialogfragment, container);
        acceptButton = (Button) view.findViewById(R.id.dialogfragment_acceptbtn);
        rejectButton = (Button) view.findViewById(R.id.dialogfragment_rejectbtn);
        cancelButton = (Button) view.findViewById(R.id.dialogfragment_cancelbtn);
        acceptButton.setOnClickListener(this);
        rejectButton.setOnClickListener(this);
        cancelButton.setOnClickListener(this);
        getDialog().setTitle(R.string.dialog_title);
        return view;
    }

    @Override
    public void onClick(View v)
    {
        Callback callback = null;
        try
        {
            callback = (Callback) getTargetFragment();
        }
        catch (ClassCastException e)
        {
            Log.e(this.getClass().getSimpleName(), "Callback of this class must be implemented by target fragment!", e);
            throw e;
        }

        if (callback != null)
        {
            if (v == acceptButton)
            {   
                callback.accept();
                this.dismiss();
            }
            else if (v == rejectButton)
            {
                callback.decline();
                this.dismiss();
            }
            else if (v == cancelButton)
            {
                callback.cancel();
                this.dismiss();
            }
        }
    }
}

Activity: 活动:

public class MyActivity extends ActionBarActivity implements ShowDialog
{
    ..

    @Override
    public void showDialog(DialogFragment dialogFragment)
    {
        FragmentManager fragmentManager = getSupportFragmentManager();
        dialogFragment.show(fragmentManager, "dialog");
    }
}

DialogFragment layout: DialogFragment布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/dialogfragment_textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="10dp"
        android:text="@string/example"/>

    <Button
        android:id="@+id/dialogfragment_acceptbtn"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/dialogfragment_textview"
        android:text="@string/accept"
        />

    <Button
        android:id="@+id/dialogfragment_rejectbtn"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_alignLeft="@+id/dialogfragment_acceptbtn"
        android:layout_below="@+id/dialogfragment_acceptbtn"
        android:text="@string/decline" />

     <Button
        android:id="@+id/dialogfragment_cancelbtn"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="20dp"
        android:layout_alignLeft="@+id/dialogfragment_rejectbtn"
        android:layout_below="@+id/dialogfragment_rejectbtn"
        android:text="@string/cancel" />

     <Button
        android:id="@+id/dialogfragment_heightfixhiddenbtn"
        android:layout_width="200dp"
        android:layout_height="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="20dp"
        android:layout_alignLeft="@+id/dialogfragment_cancelbtn"
        android:layout_below="@+id/dialogfragment_cancelbtn"
        android:background="@android:color/transparent"
        android:enabled="false"
        android:text=" " />
</RelativeLayout>

As the name dialogfragment_heightfixhiddenbtn shows, I just couldn't figure out a way to fix that the bottom button's height was cut in half despite saying wrap_content , so I added a hidden button to be "cut" in half instead. 就像dialogfragment_heightfixhiddenbtn这个名字dialogfragment_heightfixhiddenbtn显示的那样,我只是想办法解决底部按钮的高度被切成两半的问题,尽管说的是wrap_content ,所以我添加了一个隐藏的按钮,将其“切成两半”。 Sorry for the hack. 对不起黑客。

 public void showAlert(){


     AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
     LayoutInflater inflater = getActivity().getLayoutInflater();
     View alertDialogView = inflater.inflate(R.layout.test_dialog, null);
     alertDialog.setView(alertDialogView);

     TextView textDialog = (TextView) alertDialogView.findViewById(R.id.text_testDialogMsg);
     textDialog.setText(questionMissing);

     alertDialog.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
         public void onClick(DialogInterface dialog, int which) {
             dialog.cancel();
         }
     });
     alertDialog.show();

}

where .test_dialog is of xml custom 其中.test_dialog是xml自定义的

I am a beginner myself and I honestly couldn't find a satisfactory answer that I could understand or implement. 我自己是初学者,老实说,我找不到一个我能理解或实施的令人满意的答案。

So here's an external link that I really helped me achieved what I wanted. 所以这是一个外部链接,我真的帮助我实现了我想要的。 It's very straight forward and easy to follow as well. 它非常简单,也很容易理解。

http://www.helloandroid.com/tutorials/how-display-custom-dialog-your-android-application http://www.helloandroid.com/tutorials/how-display-custom-dialog-your-android-application

THIS WHAT I TRIED TO ACHIEVE WITH THE CODE: 我试图用这个代码来做什么:

I have a MainActivity that hosts a Fragment. 我有一个MainActivity托管片段。 I wanted a dialog to appear on top of the layout to ask for user input and then process the input accordingly. 我希望在布局顶部显示一个对话框,询问用户输入,然后相应地处理输入。 See a screenshot 查看截图

Here's what the onCreateView of my fragment looks 这是我的片段的onCreateView看起来的样子

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_home_activity, container, false);

    Button addTransactionBtn = rootView.findViewById(R.id.addTransactionBtn);

    addTransactionBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Dialog dialog = new Dialog(getActivity());
            dialog.setContentView(R.layout.dialog_trans);
            dialog.setTitle("Add an Expense");
            dialog.setCancelable(true);

            dialog.show();

        }
    });

I hope it will help you 我希望它会对你有所帮助

Let me know if there's any confusion. 如果有任何混淆,请告诉我。 :) :)

    public static void OpenDialog (Activity activity, DialogFragment fragment){

    final FragmentManager fm = ((FragmentActivity)activity).getSupportFragmentManager();

    fragment.show(fm, "tag");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM