অ্যান্ড্রয়েড ডায়ালগফ্রেগমেন্ট বনাম ডায়ালগ


244

গুগল সুপারিশ করে যে আমরা ব্যবহার করে DialogFragmentসাধারণের পরিবর্তে Dialogব্যবহার করি Fragments API, তবে DialogFragmentসাধারণ হ্যাঁ-না নিশ্চিতকরণ বার্তার বাক্সের জন্য বিচ্ছিন্নভাবে ব্যবহার করা অযৌক্তিক । এই ক্ষেত্রে সেরা অনুশীলন কি?


5
সংক্ষেপে, অন্যান্য বিষয়গুলির মধ্যে, সহজ Dialogবা AlertDialog.Builder::create()::show()একটি ডায়ালগ তৈরি করবে যা আপনি পর্দাটি ঘোরানোর সময় অদৃশ্য হয়ে যায়।
ব্যবহারকারী 1032613

উত্তর:


83

হ্যাঁ, ব্যবহার করুন DialogFragmentএবং এতে হ্যাঁ / না নিশ্চিতকরণ বোতামগুলির onCreateDialogসাহায্যে একটি সাধারণ তৈরি করতে আপনি কেবল একটি সতর্কতা ডায়ালগ নির্মাতা ব্যবহার করতে পারেন AlertDialog। মোটেও খুব বেশি কোড নয়।

আপনার খণ্ডগুলিতে ইভেন্টগুলি পরিচালনা করার ক্ষেত্রে এটি করার বিভিন্ন উপায় থাকবে তবে আমি কেবল Handlerআমার মধ্যে একটি বার্তা সংজ্ঞায়িত করি Fragment, DialogFragmentএটির কনস্ট্রাক্টরের মাধ্যমে প্রবেশ করান এবং তারপরে বিভিন্ন ক্লিক ইভেন্টগুলিকে বরাদ্দকারী হিসাবে আমার খণ্ডটির হ্যান্ডলারের কাছে বার্তাগুলি প্রেরণ করি। আবার এটি করার বিভিন্ন উপায় তবে নিম্নলিখিতগুলি আমার পক্ষে কাজ করে।

কথোপকথনে একটি বার্তা রাখুন এবং এটি কনস্ট্রাক্টারে ইনস্ট্যান্ট করুন:

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

onClickListenerআপনার কথোপকথনে প্রয়োগ করুন এবং তারপরে হ্যান্ডলারটিকে যথাযথ হিসাবে কল করুন:

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

সম্পাদন করা

এবং Messageপার্সেবল হিসাবে আপনি এটি এটিকে সঞ্চয় করতে onSaveInstanceStateএবং এটি পুনরুদ্ধার করতে পারেন

outState.putParcelable("okMessage", okMessage);

তারপরে onCreate

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

4
সমস্যাটি OkMessage নয় - সমস্যাটি হল OkMessage targetযা আপনি যদি কোনও বান্ডেল থেকে লোড করেন তবে তা বাতিল হয়ে যাবে। যদি কোনও বার্তার টার্গেটটি নাল হয় এবং আপনি ব্যবহার করেন তবে sendToTargetআপনি একটি নালপয়েন্টার এক্সসেপশন পাবেন - বার্তাটি নালার কারণে নয়, তবে এর লক্ষ্য হিসাবে।
এইচআরএনটি

2
ডায়ালগের পরিবর্তে ডায়ালগফ্রেগমেন্ট ব্যবহারের সুবিধা কী?
রাফেল পিটগ্রোসো

80
একটি ডায়ালগফ্রেগমেন্ট ব্যবহার করার সুবিধাটি হ'ল ডায়ালগের সমস্ত জীবনচক্র আপনার জন্য পরিচালনা করা হবে। 'ডায়লগ ফাঁস হয়ে গেছে ...' আবার ত্রুটি পাবেন না। ডায়ালগফ্রেগমেন্ট এ যান এবং ডায়ালগগুলি ভুলে যান।
Snicolas

6
আমি মনে করি কনস্ট্রাক্টরের মাধ্যমে OkMessage পাস করার পরিবর্তে setArguments () এবং getArguments () ব্যবহার করা উচিত।
pjv

1
আচ্ছা আমি বিল্ডারটিকে বেশ সহজেই ব্যবহার করি এবং আমি এই অ্যান্ড্রয়েডের সাথে ক্রিয়াকলাপ পরিচালনা পরিচালনা করি: configChanges = "লোকেল | কীবোর্ডহিডেন্ট | ওরিয়েন্টেশন | স্ক্রিন সাইজ" এবং আমি অ্যাপ্লিকেশনগুলিতে কোনও সমস্যা দেখছি না ...
রেনেটিক

67

আপনি জেনেরিক ডায়ালগফ্রেগমেন্ট সাবক্লাসগুলি হ্যাঁসনো ডায়ালগ এবং OkDialog এর মতো তৈরি করতে পারেন, এবং আপনি যদি আপনার অ্যাপ্লিকেশনে প্রচুর সংলাপ ব্যবহার করেন তবে শিরোনাম এবং বার্তায় পাস করতে পারেন।

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();
    }
}

তারপরে নিম্নলিখিতটি ব্যবহার করে এটি কল করুন:

    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");

এবং ফলাফল হ্যান্ডেল করুন onActivityResult


হ্যাঁ, ডায়ালগফ্রেগমেন্টটি আপনার জন্য সমস্ত জীবনচক্র ইভেন্ট পরিচালনা করে।
ashishduh

1
আমি ঘূর্ণন পুরাতন ডায়লগ এখনও বিদ্যমান এবং এটা পুরানো বিদ্যমান না টুকরা assignent রাখে পর এটা না মনে (dialog.setTargetFragment (এই, YES_NO_CALL);) যাতে ঘূর্ণন পর getTargetFragment () onActivityResult নেই হবে।
Malachiasz

7
কি কি YES_NO_CALL, getFragmentManager()এবং onActivityResult?
এমসাইসিলু

2
YES_NO_CALLঅনুরোধ কোড হ'ল একটি কাস্টম ইন্ট। getFragmentManager()ক্রিয়াকলাপের জন্য খণ্ড ব্যবস্থাপক পান এবং onActivityResult()এটি একটি খণ্ড লাইফাইসাইকাল কলব্যাক পদ্ধতি।
অশিশদহ

3
গেটফ্রেগমেন্টম্যানেজার () কে getSupportFragmentManager () দিয়ে প্রতিস্থাপন করুন;
অবিনাশ ভার্মা

33

সতর্কতা ডায়ালগের মাধ্যমে ডায়ালগফ্রেগমেন্ট ব্যবহার করুন:


  • 13 স্তরের এপিআই প্রবর্তনের পরে :

    showDialog ভ্রমণ থেকে পদ্ধতি অবচিত । কোডে অন্য কোথাও একটি ডায়ালগ শুরু করা পরামর্শ দেওয়া হয় না কারণ আপনাকে নিজেই ডায়ালগটি পরিচালনা করতে হবে (উদাহরণস্বরূপ ওরিয়েন্টেশন পরিবর্তন)।

  • পার্থক্য ডায়ালগফ্রেগমেন্ট - সতর্কতা ডায়ালগ

    এরা কি এতো আলাদা? ডায়ালগফ্রেগমেন্ট সম্পর্কিত অ্যান্ড্রয়েড রেফারেন্স থেকে :

    একটি ডায়ালগফ্রেগমেন্ট এমন একটি খণ্ড যা ডায়ালগ উইন্ডোটি প্রদর্শন করে এটির ক্রিয়াকলাপের উইন্ডোর উপরে ভাসমান। এই খণ্ডটিতে একটি ডায়ালগ অবজেক্ট রয়েছে, যা এটি খণ্ডটির অবস্থার উপর ভিত্তি করে উপযুক্ত হিসাবে প্রদর্শন করে। কথোপকথনের নিয়ন্ত্রণ (কখন এটি প্রদর্শন করতে হবে, লুকিয়ে রাখবেন, বরখাস্ত করবেন তা সিদ্ধান্ত নেবেন) ডায়ালগটিতে সরাসরি কল দিয়ে নয়, এখানে এপিআইয়ের মাধ্যমে করা উচিত ।

  • অন্যান্য নোট

    • বিভিন্ন স্ক্রিন আকারের সাথে ডিভাইসের বৈচিত্রের কারণে টুকরোগুলি অ্যান্ড্রয়েড কাঠামোর একটি প্রাকৃতিক বিবর্তন।
    • ডায়ালগফ্রেগমেন্টস এবং টুকরোগুলি সমর্থন লাইব্রেরিতে উপলব্ধ করা হয়েছে যা অ্যান্ড্রয়েডের সমস্ত ব্যবহৃত ব্যবহৃত সংস্করণগুলিতে শ্রেণিকে ব্যবহারযোগ্য করে তোলে।

28

আমি ব্যবহার করার সুপারিশ করব DialogFragment

অবশ্যই, এটির সাথে একটি "হ্যাঁ / না" ডায়ালগ তৈরি করা জটিল বিষয় বিবেচনা করে এটি সাধারণ কাজ হওয়া উচিত, তবে এটির সাথে একটি অনুরূপ ডায়ালগ বাক্স তৈরি Dialogকরা অবাক করা বিষয় হিসাবেও জটিল।

(ক্রিয়াকলাপের জীবনচক্রটি এটিকে জটিল করে তোলে - আপনাকে অবশ্যই Activityডায়লগ বাক্সের জীবনচক্র পরিচালনা করতে হবে - এবং কাস্টম প্যারামিটারগুলি পাস করার কোনও উপায় নেই যেমন Activity.showDialog8 এর নিচে এপিআই স্তর ব্যবহার করে কাস্টম বার্তা )

সুন্দর জিনিসটি হ'ল আপনি সাধারণত নিজের বিমূর্ততাটি DialogFragmentখুব সহজেই শীর্ষে তৈরি করতে পারেন।


আপনি কীভাবে সতর্কতা ডায়ালগ কলব্যাকগুলি পরিচালনা করবেন (হ্যাঁ, না)?
আলেক্সি জখারভ

হোস্টিং ক্রিয়াকলাপে কোনও Stringপরামিতি লাগে এমন কোনও পদ্ধতি প্রয়োগ করা সবচেয়ে সহজ উপায় । যখন ব্যবহারকারী "হ্যাঁ" ক্লিক করেন, উদাহরণস্বরূপ, ডায়ালগটি ক্রিয়াকলাপের পদ্ধতিটিকে প্যারামিটার দিয়ে "সম্মত" করে। ডায়লগটি দেখানোর সময় এই পরামিতিগুলি নির্দিষ্ট করা হয়, উদাহরণস্বরূপ AskDialog.ask ("আপনি কি এই শর্তাদির সাথে সম্মত হন?", "সম্মত", "অসমত");
এইচআরএনটি

5
তবে আমার ক্রিয়াকলাপ নয়, খণ্ডের ভিতরে কলব্যাক দরকার। আমি সেটট্রেটফ্রেগমেন্ট ব্যবহার করতে পারি এবং এটি ইন্টারফেসে কাস্ট করতে পারি। তবে এটা নরক।
আলেক্সি জখারভ

এছাড়াও আপনি লক্ষ্য একটি ট্যাগ সেটিং এবং ব্যবহার করে লক্ষ্য টুকরা আনা পারে FragmentManager'র findFragmentByTag। তবে হ্যাঁ, এটির জন্য মোটামুটি কোড দরকার।
hrnt

@AlexeyZakharov আমি জানি এই 5 বছর সম্পর্কে দেরি হয়ে গেছে কিন্তু আপনি পাস পারে Fragment this এবং আপনার আছে Activity extendsআপনার Interface। থ্রেডিংয়ের ক্ষেত্রে সাবধানতা অবলম্বন করে আপনি যখন ইন্টারফেস কলগুলি পপিং করে যাবেন যখন আপনি যখন প্রয়োজন না তখন অগত্যা সেগুলি চান না যদি আপনার চুক্তি চেক না হয়। নিশ্চিত নয় যে এটি মেমরি এবং বিজ্ঞপ্তি নির্ভরতা স্প্যাগেটির সাথে কী করে, অন্য কেউ কি চিম ইন করতে পছন্দ করবে? অন্য বিকল্পটি হল Message/ Handlerতবে আপনার এখনও সম্মতিযুক্ত সমস্যা থাকতে পারে।
ট্রিকনোলজি

8

বিল্ডার প্যাটার্ন সহ জেনেরিক সতর্কতা ডায়ালগফ্র্যাগমেন্ট

আমার প্রকল্পে, আমি এটি ইতিমধ্যে AlertDialog.Builderইতিমধ্যে অনেক ব্যবহার করেছি যে এটি সমস্যাযুক্ত। যাইহোক, আমি আমার অ্যাপের কোথাও এত কোড পরিবর্তন করতে চাইনি। অতিরিক্ত হিসাবে, আমি প্রকৃতপক্ষে OnClickListenersতাদের বেনামী ক্লাস হিসাবে পাস করার অনুরাগী যেখানে তাদের প্রয়োজন (এটি ব্যবহার করার সময় setPositiveButton(),setNegativeButton() ইত্যাদি) পরিবর্তে ডায়ালগ খণ্ড এবং ধারক খণ্ডের মধ্যে যোগাযোগের জন্য হাজার হাজার কলব্যাক পদ্ধতি প্রয়োগ করার দরকার নেই, যা করতে পারে আমার মতামত, খুব বিভ্রান্তিকর এবং জটিল কোডে নেতৃত্ব দিন। বিশেষত, যদি আপনার এক টুকরোতে একাধিক বিভিন্ন সংলাপ থাকে এবং তারপরে বর্তমানে কোন ডায়ালগটি প্রদর্শিত হচ্ছে তার মধ্যে কলব্যাক বাস্তবায়নের মধ্যে পার্থক্য করা প্রয়োজন।

অতএব, আমি জেনেরিক AlertDialogFragmentসহায়ক শ্রেণি তৈরি করতে বিভিন্ন পদ্ধতির সমন্বয় করেছি যা ঠিক এর মতো ব্যবহার করা যেতে পারে AlertDialog:


সমাধান

( দয়া করে নোট করুন যে আমি আমার কোডে জাভা 8 লাম্বদা এক্সপ্রেশন ব্যবহার করছি, সুতরাং আপনি যদি ল্যাম্বদা এক্সপ্রেশনটি ব্যবহার না করেন তবে আপনাকে কোডের কিছু অংশ পরিবর্তন করতে হতে পারে ))

/**
 * 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
}

, USAGE

// 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();

আমি এখানে কেবল আমার সমাধান ভাগ করে নেওয়ার জন্যই এখানে পোস্ট করছি না, কারণ আমি আপনাকে আপনার মতামতের জন্য লোকদের জিজ্ঞাসা করতে চেয়েছিলাম: এই পন্থাটি কি কিছুটা বৈধ বা সমস্যাযুক্ত?


3
এটি একটি খুব আকর্ষণীয় ধারণা, তবে আমি মনে করি না যে API নকশা কাজ করে। আপনি যদি সেটপোসিটিভ বাটন () -কে সেটস-পজিটিভ বাটন () এ কোনও অনিক্লিকলিস্টার পাস করেন, যখন ডিভাইসটি ঘোরানো হয় এবং বান্ডিল আরোগুলি থেকে খণ্ডটি পুনরায় তৈরি করা হয়, অনক্লিকলিস্টনারগুলি পার্সেবল থেকে সঠিকভাবে পুনরায় তৈরি করা যাবে না। মূল সমস্যাটি হ'ল আপনি ঘূর্ণনের সময় কোনও শ্রোতা পুনরায় তৈরি করতে পারবেন না, তবে API ইন্টারফেস (যা ইন্টারফেসগুলি নেয়) এটির দাবি করে। আমার ইচ্ছা এই ঘটনাটি না ঘটে (যেমন আমি ধারণাটি পছন্দ করি)।
জার্গস

1
দুর্দান্ত ধারণা, তবে @ জার্গস যেমন বলেছে, এটি কার্যকর হয় না। উত্তীর্ণ শ্রোতারা ঘোরানোর সময় সঠিকভাবে পুনরায় তৈরি করা হয় না।
গ্রাহাম বোরল্যান্ড

আমার ফলাফলগুলি হ'ল এটি আসলে ঘূর্ণায়মান এবং অ্যাপ্লিকেশনটিতে পুনরায় চালু করার জন্য কাজ করে (উদাহরণস্বরূপ হোম স্ক্রিনে যাওয়ার পরে), তবে কার্যকলাপটি সম্পূর্ণরূপে ধ্বংস হওয়ার পরে পুনরুদ্ধার করা হয় না (তবে অনক্লিকলিস্টেনাররা প্রকৃতপক্ষে হারিয়ে গেছে)। (অ্যান্ড্রয়েড ৪.৪.৪ এবং অ্যান্ড্রয়েড 5.1.1 এ পরীক্ষিত)
3'17

আমি এই সঠিক প্রয়োগটি পরীক্ষা করে দেখিনি তবে যা যা পরীক্ষা করেছি, সেখান থেকে একটি পার্সেবল শ্রোতা একটি খণ্ডের বান্ডেলে পাস করে পুনরায় তৈরি করতে ডাকা হয়। আমি জানি না কেন তবে এটি কাজ করে বলে মনে হচ্ছে।
সাদ ফারুক

@ এফএলএক্সএপস, কাস্টম ভিউয়ের ক্ষেত্রে আপনি কীভাবে সন্তানের মতামত পেতে এবং তাদের সম্পত্তিগুলি পরিবর্তন করতে বা শ্রোতাদের প্রয়োগ করতে পারেন? আপনার ক্লাসে আপনি কোনও সংলাপের উদাহরণ ফিরিয়ে দিচ্ছেন না এবং যদি কেউ শিশু দৃষ্টিভঙ্গি অর্জন করার চেষ্টা করে তবে এটি ব্যতিক্রম ঘটতে পারে
জুবায়ের রেহমান

5

আমি @ অশিষদুহের জবাবটির কিছুটা সরলীকরণের পরামর্শ দিতে পারি:

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();
}

এটি ব্যবহারকারীর (শ্রেণির) উপাদানটির অভ্যন্তরগুলির সাথে পরিচিত হওয়ার প্রয়োজনীয়তা সরিয়ে দেয় এবং ব্যবহারকে সত্যই সহজ করে তোলে:

AlertDialogFragment.showAlert(title, message, this);

পিএস আমার ক্ষেত্রে আমার একটি সাধারণ সতর্কতা ডায়ালগ দরকার ছিল তাই আমি তৈরি করেছি created আপনি প্রয়োজনটি হ্যাঁ / না বা অন্য যে কোনও ধরণের প্রয়োজনে প্রয়োগ করতে পারেন।


1

সাধারণ হ্যাঁ বা কোনও কথোপকথনের জন্য ডায়ালগটি ব্যবহার করুন।

যখন আপনার আরও জটিল ভিউগুলির প্রয়োজন হয় যেখানে আপনাকে লাইফেসাইকেলের যেমন অনক্রিট, অনুরোধের অনুমতিগুলি ধরে রাখা দরকার তখন কোনও জীবনচক্র ওভাররাইড আমি একটি ডায়ালগ খণ্ড ব্যবহার করব। এইভাবে আপনি কলিং ক্রিয়াকলাপের সাথে যোগাযোগ না করে ডায়ালগটির চালানোর জন্য অনুমতি এবং অন্য কোনও কোড পৃথক করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.