Hộp thoại Android vs Hộp thoại


244

Google khuyên chúng ta nên sử dụng DialogFragmentthay vì đơn giản Dialogbằng cách sử dụng Fragments API, nhưng thật vô lý khi sử dụng một cách ly DialogFragmentcho hộp thông báo xác nhận Có-Không đơn giản. Thực hành tốt nhất trong trường hợp này là gì?


5
Nói tóm lại, trong số những thứ khác, đơn giản Dialoghoặc AlertDialog.Builder::create()::show()sẽ tạo một hộp thoại biến mất khi bạn xoay màn hình.
dùng1032613

Câu trả lời:


83

Có, sử dụng DialogFragmentvà trong onCreateDialogbạn chỉ cần sử dụng trình tạo AlertDialog để tạo một đơn giản AlertDialogvới các nút xác nhận Có / Không. Không có nhiều mã ở tất cả.

Liên quan đến việc xử lý các sự kiện trong đoạn của bạn, sẽ có nhiều cách khác nhau để thực hiện nhưng tôi chỉ cần xác định một thông báo Handlertrong đó Fragment, chuyển nó DialogFragmentqua hàm tạo của nó và sau đó chuyển tin nhắn lại cho trình xử lý đoạn của tôi như là sự chấp thuận cho các sự kiện nhấp chuột khác nhau. Một lần nữa cách khác nhau để làm điều đó nhưng sau đây làm việc cho tôi.

Trong hộp thoại giữ một thông báo và khởi tạo nó trong hàm tạo:

private Message okMessage;
...
okMessage = handler.obtainMessage(MY_MSG_WHAT, MY_MSG_OK);

Thực hiện onClickListenertrong hộp thoại của bạn và sau đó gọi trình xử lý khi thích hợp:

public void onClick(.....
    if (which == DialogInterface.BUTTON_POSITIVE) {
        final Message toSend = Message.obtain(okMessage);
        toSend.sendToTarget();
    }
 }

Biên tập

Và như Messagelà bưu kiện, bạn có thể lưu nó vào onSaveInstanceStatevà khôi phục nó

outState.putParcelable("okMessage", okMessage);

Sau đó trong onCreate

if (savedInstanceState != null) {
    okMessage = savedInstanceState.getParcelable("okMessage");
}

4
Vấn đề không phải là okMessage - vấn đề là okMessage targetsẽ không có giá trị nếu bạn tải nó từ Gói. Nếu mục tiêu của Tin nhắn là null và bạn sử dụng sendToTarget, bạn sẽ nhận được NullPulumException - không phải vì Tin nhắn là null, mà vì mục tiêu của nó là.
hrnt

2
Những lợi thế của việc sử dụng DialogFragment thay vì Dialog là gì?
Raphael Petegrosso

79
Ưu điểm của việc sử dụng DialogFragment là tất cả vòng đời của hộp thoại sẽ được xử lý cho bạn. Bạn sẽ không bao giờ gặp lỗi 'hộp thoại đã bị rò rỉ ...' một lần nữa. Đi tới DialogFragment và quên Dialogs.
Snicolas

6
Tôi nghĩ rằng setArgument () và getArgument () nên được sử dụng thay vì truyền okMessage thông qua hàm tạo.
pjv

1
Vâng, tôi sử dụng Builder khá dễ dàng và tôi xử lý việc quản lý hoạt động với android này: configChanges = "locale | keyboardHidden | direction | screenSize" và tôi không thấy bất kỳ vấn đề nào trong các ứng dụng ...
Renetik

67

Bạn có thể tạo các lớp con DialogFragment chung như YesNoDialog và OkDialog, và chuyển tiêu đề và tin nhắn nếu bạn sử dụng nhiều hộp thoại trong ứng dụng của mình.

public class YesNoDialog extends DialogFragment
{
    public static final String ARG_TITLE = "YesNoDialog.Title";
    public static final String ARG_MESSAGE = "YesNoDialog.Message";

    public YesNoDialog()
    {

    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        Bundle args = getArguments();
        String title = args.getString(ARG_TITLE);
        String message = args.getString(ARG_MESSAGE);

        return new AlertDialog.Builder(getActivity())
            .setTitle(title)
            .setMessage(message)
            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, null);
                }
            })
            .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_CANCELED, null);
                }
            })
            .create();
    }
}

Sau đó gọi nó bằng cách sử dụng như sau:

    DialogFragment dialog = new YesNoDialog();
    Bundle args = new Bundle();
    args.putString(YesNoDialog.ARG_TITLE, title);
    args.putString(YesNoDialog.ARG_MESSAGE, message);
    dialog.setArguments(args);
    dialog.setTargetFragment(this, YES_NO_CALL);
    dialog.show(getFragmentManager(), "tag");

Và xử lý kết quả trong onActivityResult.


Có, DialogFragment xử lý tất cả các sự kiện vòng đời cho bạn.
ashishduh

1
Tôi nghĩ rằng điều đó không xảy ra bởi vì sau khi xoay Dialog cũ vẫn tồn tại và nó vẫn được gán cho đoạn cũ không tồn tại (hộp thoại.setTargetFragment (cái này, YES_NO_CALL);) nên sau khi xoay getTargetFragment (). OnActivityResult không hoạt động
Malachiasz

7
những gì là YES_NO_CALL, getFragmentManager()onActivityResult?
msysmilu

2
YES_NO_CALLlà một int tùy chỉnh đó là mã yêu cầu. getFragmentManager()được người quản lý phân đoạn cho hoạt động và onActivityResult()là một phương thức gọi lại vòng đời của đoạn.
ashishduh

3
Thay thế getFragmentManager () bằng getSupportFragmentManager ();
Avinash Verma

33

Sử dụng DialogFragment trên AlertDialog:


  • Kể từ khi giới thiệu API cấp 13 :

    các ShowDialog phương pháp từ Hoạt động đang bị phản đối . Không thể gọi hộp thoại ở nơi khác trong mã vì bạn sẽ phải tự mình quản lý hộp thoại (ví dụ: thay đổi hướng).

  • DialogFragment khác biệt - AlertDialog

    Có phải họ rất khác nhau? Từ tài liệu tham khảo Android liên quan đến DialogFragment :

    DialogFragment là một đoạn hiển thị một cửa sổ hộp thoại, nổi trên đầu cửa sổ hoạt động của nó. Đoạn này chứa một đối tượng Hộp thoại, nó hiển thị là phù hợp dựa trên trạng thái của đoạn đó. Kiểm soát hộp thoại (quyết định khi nào hiển thị, ẩn, loại bỏ nó) nên được thực hiện thông qua API ở đây , không phải bằng các cuộc gọi trực tiếp trên hộp thoại.

  • Ghi chú khác

    • Các mảnh vỡ là một sự phát triển tự nhiên trong khung Android do sự đa dạng của các thiết bị với kích thước màn hình khác nhau.
    • DialogFragments và Fragment được cung cấp trong thư viện hỗ trợ, giúp lớp có thể sử dụng được trong tất cả các phiên bản Android được sử dụng hiện tại.

28

Tôi khuyên bạn nên sử dụng DialogFragment.

Chắc chắn, việc tạo một hộp thoại "Có / Không" với nó khá phức tạp vì nó khá đơn giản, nhưng việc tạo một hộp thoại tương tự Dialogcũng phức tạp một cách đáng ngạc nhiên.

(Vòng đời hoạt động làm cho nó phức tạp - bạn phải cho phép Activityquản lý vòng đời của hộp thoại - và không có cách nào để truyền tham số tùy chỉnh, ví dụ như thông báo tùy chỉnh Activity.showDialognếu sử dụng các cấp API dưới 8)

Điều tuyệt vời là bạn thường có thể xây dựng sự trừu tượng của riêng mình trên đầu trang DialogFragmentkhá dễ dàng.


Làm thế nào bạn sẽ xử lý các cuộc gọi lại hộp thoại cảnh báo (có, không)?
Alexey Zakharov

Cách dễ nhất là triển khai một phương thức trong Hoạt động lưu trữ có Stringtham số. Ví dụ, khi người dùng nhấp vào "Có", hộp thoại sẽ gọi phương thức của Activity với tham số "đồng ý". Các tham số này được chỉ định khi hiển thị hộp thoại, ví dụ AskDialog.ask ("Bạn có đồng ý với các điều khoản này không?", "Đồng ý", "không đồng ý");
hrnt

5
Nhưng tôi cần gọi lại bên trong đoạn, không hoạt động. Tôi có thể sử dụng setTargetFragment và chuyển nó sang giao diện. Nhưng đó là địa ngục.
Alexey Zakharov

Bạn cũng có thể lấy mảnh mục tiêu bằng cách thiết lập một thẻ để các mục tiêu và sử dụng FragmentManager's findFragmentByTag. Nhưng vâng, nó đòi hỏi một chút mã.
hrnt

@AlexeyZakharov Tôi biết điều này muộn khoảng 5 năm nhưng bạn có thể vượt qua Fragment this và có Activity extendsbạn Interface. Mặc dù cẩn thận khi xâu chuỗi, bạn có thể tắt các cuộc gọi giao diện khi bạn không nhất thiết muốn chúng nếu không kiểm tra được sự đồng thời của bạn. Không chắc chắn điều này làm gì với bộ nhớ và spaghetti phụ thuộc vòng tròn mặc dù, bất cứ ai khác muốn hòa nhập? Tùy chọn khác là Message/ Handlernhưng bạn vẫn có thể có vấn đề tương tranh.
thủ thuật

8

AlertDialogFragment chung với mẫu Builder

Trong dự án của tôi, tôi đã sử dụng AlertDialog.Builderđã rất nhiều trước khi tôi phát hiện ra rằng đó là vấn đề. Tuy nhiên, tôi không muốn thay đổi nhiều mã ở bất kỳ đâu trong ứng dụng của mình. Ngoài ra, tôi thực sự là một fan hâm mộ của việc chuyển qua OnClickListenerscác lớp ẩn danh khi cần thiết (nghĩa là khi sử dụng setPositiveButton(), setNegativeButton()v.v.) thay vì phải thực hiện hàng ngàn phương thức gọi lại để giao tiếp giữa một đoạn hộp thoại và đoạn giữ, có thể, trong ý kiến ​​của tôi, dẫn đến mã rất khó hiểu và phức tạp. Đặc biệt, nếu bạn có nhiều hộp thoại khác nhau trong một đoạn và sau đó cần phân biệt trong triển khai gọi lại giữa hộp thoại nào hiện đang được hiển thị.

Do đó, tôi đã kết hợp các cách tiếp cận khác nhau để tạo ra một AlertDialogFragmentlớp trợ giúp chung có thể được sử dụng chính xác như AlertDialog :


GIẢI PHÁP

( XIN LƯU Ý rằng tôi đang sử dụng các biểu thức lambda Java 8 trong mã của mình, vì vậy bạn có thể phải thay đổi các phần của mã nếu bạn chưa sử dụng biểu thức lambda .)

/**
 * Helper class for dialog fragments to show a {@link AlertDialog}. It can be used almost exactly
 * like a {@link AlertDialog.Builder}
 * <p />
 * Creation Date: 22.03.16
 *
 * @author felix, http://flx-apps.com/
 */
public class AlertDialogFragment extends DialogFragment {
    protected FragmentActivity activity;
    protected Bundle args;
    protected String tag = AlertDialogFragment.class.getSimpleName();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activity = getActivity();
        args = getArguments();
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = setDialogDefaults(new AlertDialog.Builder(getActivity())).create();

        if (args.containsKey("gravity")) {
            dialog.getWindow().getAttributes().gravity = args.getInt("gravity");
        }

        dialog.setOnShowListener(d -> {
            if (dialog != null && dialog.findViewById((android.R.id.message)) != null) {
                ((TextView) dialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
            }
        });
        return dialog;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);

        if (args.containsKey("onDismissListener")) {
            Parcelable onDismissListener = args.getParcelable("onDismissListener");
            if (onDismissListener != null && onDismissListener instanceof ParcelableOnDismissListener) {
                ((ParcelableOnDismissListener) onDismissListener).onDismiss(this);
            }
        }
    }

    /**
     * Sets default dialog properties by arguments which were set using {@link #builder(FragmentActivity)}
     */
    protected AlertDialog.Builder setDialogDefaults(AlertDialog.Builder builder) {
        args = getArguments();
        activity = getActivity();

        if (args.containsKey("title")) {
            builder.setTitle(args.getCharSequence("title"));
        }

        if (args.containsKey("message")) {
            CharSequence message = args.getCharSequence("message");
            builder.setMessage(message);
        }

        if (args.containsKey("viewId")) {
            builder.setView(getActivity().getLayoutInflater().inflate(args.getInt("viewId"), null));
        }

        if (args.containsKey("positiveButtonText")) {
            builder.setPositiveButton(args.getCharSequence("positiveButtonText"), (dialog, which) -> {
                onButtonClicked("positiveButtonListener", which);
            });
        }

        if (args.containsKey("negativeButtonText")) {
            builder.setNegativeButton(args.getCharSequence("negativeButtonText"), (dialog, which) -> {
                onButtonClicked("negativeButtonListener", which);
            });
        }

        if (args.containsKey("neutralButtonText")) {
            builder.setNeutralButton(args.getCharSequence("neutralButtonText"), (dialog, which) -> {
                onButtonClicked("neutralButtonListener", which);
            });
        }

        if (args.containsKey("items")) {
            builder.setItems(args.getStringArray("items"), (dialog, which) -> {
                onButtonClicked("itemClickListener", which);
            });
        }

        // @formatter:off
        // FIXME this a pretty hacky workaround: we don't want to show the dialog if onClickListener of one of the dialog's button click listener were lost
        //       the problem is, that there is no (known) solution for parceling a OnClickListener in the long term (only for state changes like orientation change,
        //       but not if the Activity was completely lost)
        if (
                (args.getParcelable("positiveButtonListener") != null && !(args.getParcelable("positiveButtonListener") instanceof ParcelableOnClickListener)) ||
                (args.getParcelable("negativeButtonListener") != null && !(args.getParcelable("negativeButtonListener") instanceof ParcelableOnClickListener)) ||
                (args.getParcelable("neutralButtonListener") != null && !(args.getParcelable("neutralButtonListener") instanceof ParcelableOnClickListener)) ||
                (args.getParcelable("itemClickListener") != null && !(args.getParcelable("itemClickListener") instanceof ParcelableOnClickListener))
        ) {
            new DebugMessage("Forgot onClickListener. Needs to be dismissed.")
                    .logLevel(DebugMessage.LogLevel.VERBOSE)
                    .show();
            try {
                dismissAllowingStateLoss();
            } catch (NullPointerException | IllegalStateException ignored) {}
        }
        // @formatter:on

        return builder;
    }

    public interface OnDismissListener {
        void onDismiss(AlertDialogFragment dialogFragment);
    }

    public interface OnClickListener {
        void onClick(AlertDialogFragment dialogFragment, int which);
    }

    protected void onButtonClicked(String buttonKey, int which) {
        ParcelableOnClickListener parcelableOnClickListener = getArguments().getParcelable(buttonKey);
        if (parcelableOnClickListener != null) {
            parcelableOnClickListener.onClick(this, which);
        }
    }

    // region Convenience Builder Pattern class almost similar to AlertDialog.Builder
    // =============================================================================================

    public AlertDialogFragment builder(FragmentActivity activity) {
        this.activity = activity;
        this.args = new Bundle();
        return this;
    }

    public AlertDialogFragment addArguments(Bundle bundle) {
        args.putAll(bundle);
        return this;
    }

    public AlertDialogFragment setTitle(int titleStringId) {
        return setTitle(activity.getString(titleStringId));
    }

    public AlertDialogFragment setTitle(CharSequence title) {
        args.putCharSequence("title", title);
        return this;
    }

    public AlertDialogFragment setMessage(int messageStringId) {
        return setMessage(activity.getString(messageStringId));
    }

    public AlertDialogFragment setMessage(CharSequence message) {
        args.putCharSequence("message", message);
        return this;
    }

    public AlertDialogFragment setPositiveButton(int textStringId, OnClickListener onClickListener) {
        return setPositiveButton(activity.getString(textStringId), onClickListener);
    }

    public AlertDialogFragment setPositiveButton(CharSequence text, AlertDialogFragment.OnClickListener onClickListener) {
        args.putCharSequence("positiveButtonText", text);
        args.putParcelable("positiveButtonListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setNegativeButton(int textStringId, AlertDialogFragment.OnClickListener onClickListener) {
        return setNegativeButton(activity.getString(textStringId), onClickListener);
    }

    public AlertDialogFragment setNegativeButton(CharSequence text, AlertDialogFragment.OnClickListener onClickListener) {
        args.putCharSequence("negativeButtonText", text);
        args.putParcelable("negativeButtonListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setNeutralButton(int textStringId, AlertDialogFragment.OnClickListener onClickListener) {
        return setNeutralButton(activity.getString(textStringId), onClickListener);
    }

    public AlertDialogFragment setNeutralButton(CharSequence text, AlertDialogFragment.OnClickListener onClickListener) {
        args.putCharSequence("neutralButtonText", text);
        args.putParcelable("neutralButtonListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setOnDismissListener(OnDismissListener onDismissListener) {
        if (onDismissListener == null) {
            return this;
        }

        Parcelable p = new ParcelableOnDismissListener() {
            @Override
            public void onDismiss(AlertDialogFragment dialogFragment) {
                onDismissListener.onDismiss(dialogFragment);
            }
        };
        args.putParcelable("onDismissListener", p);
        return this;
    }

    public AlertDialogFragment setItems(String[] items, AlertDialogFragment.OnClickListener onClickListener) {
        args.putStringArray("items", items);
        args.putParcelable("itemClickListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setView(int viewId) {
        args.putInt("viewId", viewId);
        return this;
    }

    public AlertDialogFragment setGravity(int gravity) {
        args.putInt("gravity", gravity);
        return this;
    }

    public AlertDialogFragment setTag(String tag) {
        this.tag = tag;
        return this;
    }

    public AlertDialogFragment create() {
        setArguments(args);
        return AlertDialogFragment.this;
    }

    public AlertDialogFragment show() {
        create();
        try {
            super.show(activity.getSupportFragmentManager(), tag);
        }
        catch (IllegalStateException e1) {

            /**
             * this whole part is used in order to attempt to show the dialog if an
             * {@link IllegalStateException} was thrown (it's kinda comparable to
             * {@link FragmentTransaction#commitAllowingStateLoss()} 
             * So you can remove all those dirty hacks if you are sure that you are always
             * properly showing dialogs in the right moments
             */

            new DebugMessage("got IllegalStateException attempting to show dialog. trying to hack around.")
                    .logLevel(DebugMessage.LogLevel.WARN)
                    .exception(e1)
                    .show();

            try {
                Field mShownByMe = DialogFragment.class.getDeclaredField("mShownByMe");
                mShownByMe.setAccessible(true);
                mShownByMe.set(this, true);
                Field mDismissed = DialogFragment.class.getDeclaredField("mDismissed");
                mDismissed.setAccessible(true);
                mDismissed.set(this, false);
            }
            catch (Exception e2) {
                new DebugMessage("error while showing dialog")
                        .exception(e2)
                        .logLevel(DebugMessage.LogLevel.ERROR)
                        .show();
            }
            FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
            transaction.add(this, tag);
            transaction.commitAllowingStateLoss(); // FIXME hacky and unpredictable workaround
        }
        return AlertDialogFragment.this;
    }

    @Override
    public int show(FragmentTransaction transaction, String tag) {
        throw new NoSuchMethodError("Please use AlertDialogFragment.show()!");
    }

    @Override
    public void show(FragmentManager manager, String tag) {
        throw new NoSuchMethodError("Please use AlertDialogFragment.show()!");
    }

    protected ParcelableOnClickListener createParcelableOnClickListener(AlertDialogFragment.OnClickListener onClickListener) {
        if (onClickListener == null) {
            return null;
        }

        return new ParcelableOnClickListener() {
            @Override
            public void onClick(AlertDialogFragment dialogFragment, int which) {
                onClickListener.onClick(dialogFragment, which);
            }
        };
    }

    /**
     * Parcelable OnClickListener (can be remembered on screen rotation)
     */
    public abstract static class ParcelableOnClickListener extends ResultReceiver implements AlertDialogFragment.OnClickListener {
        public static final Creator<ResultReceiver> CREATOR = ResultReceiver.CREATOR;

        ParcelableOnClickListener() {
            super(null);
        }

        @Override
        public abstract void onClick(AlertDialogFragment dialogFragment, int which);
    }

    /**
     * Parcelable OnDismissListener (can be remembered on screen rotation)
     */
    public abstract static class ParcelableOnDismissListener extends ResultReceiver implements AlertDialogFragment.OnDismissListener {
        public static final Creator<ResultReceiver> CREATOR = ResultReceiver.CREATOR;

        ParcelableOnDismissListener() {
            super(null);
        }

        @Override
        public abstract void onDismiss(AlertDialogFragment dialogFragment);
    }


    // =============================================================================================
    // endregion
}

SỬ DỤNG

// showing a normal alert dialog with state loss on configuration changes (like device rotation)
new AlertDialog.Builder(getActivity())
        .setTitle("Are you sure? (1)")
        .setMessage("Do you really want to do this?")
        .setPositiveButton("Yes", (dialog, which) -> Toast.makeText(getContext(), "Yes clicked", Toast.LENGTH_SHORT).show())
        .setNegativeButton("Cancel", null)
        .show();

// showing a dialog fragment using the helper class with no state loss on configuration changes
new AlertDialogFragment.builder(getActivity())
        .setTitle("Are you sure? (2)")
        .setMessage("Do you really want to do this?")
        .setPositiveButton("Yes", (dialog, which) -> Toast.makeText(getContext(), "Yes clicked", Toast.LENGTH_SHORT).show())
        .setNegativeButton("Cancel", null)
        .show();

Tôi đăng bài này ở đây không chỉ để chia sẻ giải pháp của mình, mà còn vì tôi muốn hỏi mọi người về ý kiến ​​của bạn: Cách tiếp cận này hợp pháp hay có vấn đề ở một mức độ nào đó?


3
Đây là một ý tưởng rất thú vị, nhưng tôi không nghĩ rằng thiết kế API hoạt động. Nếu bạn chuyển OnClickListener cho setPositiveButton (), khi thiết bị được xoay và đoạn được tạo lại từ Bundle args, OnClickListener sẽ không được tạo lại chính xác từ Parcelable. Vấn đề cơ bản là bạn không thể tạo lại người nghe trong khi xoay vòng, nhưng giao diện API (có giao diện) yêu cầu điều đó. Tôi ước điều này không xảy ra (vì tôi thích ý tưởng này).
Xargs

1
Ý tưởng hay, nhưng như @Xargs nói, nó không hoạt động. Các thính giả truyền vào không được tái tạo chính xác khi xoay.
Graham Borland

Kết quả của tôi là nó thực sự hoạt động khi xoay và tiếp tục lại ứng dụng (chẳng hạn như sau khi đi đến màn hình chính), nhưng không phải khi hoạt động được khôi phục sau khi nó bị hủy hoàn toàn (khi đó OnClickListener thực sự bị mất). (Đã thử nghiệm trên Android 4.4.4 và Android 5.1.1)
flxapps

Tôi đã không kiểm tra việc thực hiện chính xác này nhưng từ những gì tôi đã kiểm tra, một trình nghe có thể phân chia được chuyển đến một gói phân đoạn được gọi chính xác khi tạo lại. Tôi không biết tại sao nhưng nó dường như làm việc.
Saad Farooq

@flxapps, trong trường hợp chế độ xem tùy chỉnh, làm thế nào bạn có thể có được lượt xem con và thay đổi thuộc tính của chúng hoặc áp dụng trình nghe? Trong lớp của bạn, bạn sẽ không trả lại bất kỳ trường hợp hộp thoại nào và điều đó có thể gây ra ngoại lệ nếu ai đó sẽ cố gắng có được lượt xem trẻ em
Zubair Rehman

5

Tôi có thể đề nghị một chút đơn giản hóa câu trả lời của @ ashishduh:

public class AlertDialogFragment extends DialogFragment {
public static final String ARG_TITLE = "AlertDialog.Title";
public static final String ARG_MESSAGE = "AlertDialog.Message";

public static void showAlert(String title, String message, Fragment targetFragment) {
    DialogFragment dialog = new AlertDialogFragment();
    Bundle args = new Bundle();
    args.putString(ARG_TITLE, title);
    args.putString(ARG_MESSAGE, message);
    dialog.setArguments(args);
    dialog.setTargetFragment(targetFragment, 0);
    dialog.show(targetFragment.getFragmentManager(), "tag");
}

public AlertDialogFragment() {}

@NonNull
@Override
public AlertDialog onCreateDialog(Bundle savedInstanceState)
{
    Bundle args = getArguments();
    String title = args.getString(ARG_TITLE, "");
    String message = args.getString(ARG_MESSAGE, "");

    return new AlertDialog.Builder(getActivity())
            .setTitle(title)
            .setMessage(message)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, null);
                }
            })
            .create();
}

Nó loại bỏ sự cần thiết của người dùng (của lớp) để làm quen với các phần bên trong của thành phần và làm cho việc sử dụng thực sự đơn giản:

AlertDialogFragment.showAlert(title, message, this);

PS Trong trường hợp của tôi, tôi cần một hộp thoại cảnh báo đơn giản để đó là những gì tôi đã tạo. Bạn có thể áp dụng cách tiếp cận với Có / Không hoặc bất kỳ loại nào bạn cần.


1

Sử dụng Hộp thoại cho các hộp thoại đơn giản hoặc không.

Khi bạn cần các chế độ xem phức tạp hơn, trong đó bạn cần nắm giữ vòng đời như oncreate, yêu cầu quyền, bất kỳ ghi đè vòng đời nào tôi sẽ sử dụng một đoạn hộp thoại. Do đó, bạn tách các quyền và bất kỳ mã nào khác mà hộp thoại cần để hoạt động mà không phải giao tiếp với hoạt động gọi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.