کادرهای گفتگو

امتحان کردن روش «نوشتن»
‫Jetpack Compose جعبه‌ابزار واسط کاربر توصیه‌شده برای Android است. با نحوه افزودن عناصر در «نوشتن» آشنا شوید.

چارگوش گفتگو پنجره کوچکی است که از کاربر می‌خواهد تصمیمی بگیرد یا اطلاعات تکمیلی وارد کند. چارگوش صفحه را پر نمی‌کند و معمولاً برای رویدادهای مشروطی استفاده می‌شود که کاربران را ملزم می‌کند قبل‌از اینکه بتوانند ادامه دهند کنشی انجام دهند.

تصویری که کادر گفتگوی ساده‌ای را نشان می‌دهد
شکل ۱. کادر گفتگوی ساده.

کلاس Dialog کلاس پایه برای چارگوش‌های گفتگو است، اما Dialog را مستقیماً نمونه‌سازی نکنید. درعوض، از یکی از زیرکلاس‌های زیر استفاده کنید:

AlertDialog
کادر گفتگویی که می‌تواند عنوان، حداکثر سه دکمه، فهرستی از موارد قابل‌انتخاب، یا چیدمان سفارشی را نشان دهد.
DatePickerDialog یا TimePickerDialog
کادر گفتگویی با میانای کاربر ازپیش تعریف‌شده که به کاربر امکان می‌دهد تاریخ یا زمان را انتخاب کند.

این کلاس‌ها سبک و ساختار کادر گفتگوی شما را تعریف می‌کنند. همچنین به DialogFragment به‌عنوان محتوی برای چارگوش گفتگوی خود نیاز دارید. کلاس DialogFragment همه کنترل‌های لازم برای ایجاد کردن کادر گفتگوی شما و مدیریت ظاهر آن را فراهم می‌کند، به‌جای اینکه متدهای مربوط به شیء Dialog را فراخوانی کنید.

استفاده از DialogFragment برای مدیریت کردن کادر گفتگو باعث می‌شود رویدادهای چرخه حیات مثل زمانی که کاربر روی دکمه «بازگشت» تک‌ضرب می‌زند یا صفحه‌نمایش را می‌چرخاند به‌درستی مدیریت شود. کلاس DialogFragment همچنین به شما امکان می‌دهد از رابط کاربری گفتگو به‌عنوان یک عنصر جاسازی‌شدنی در یک رابط کاربری بزرگ‌تر استفاده مجدد کنید—درست مثل یک Fragment سنتی— مثلاً وقتی می‌خواهید رابط کاربری گفتگو در صفحه‌های بزرگ و کوچک متفاوت به‌نظر برسد.

بخش‌های زیر در این سند نحوه استفاده از DialogFragment را در ترکیب با AlertDialog شرح می‌دهد. اگر می‌خواهید انتخابگر تاریخ یا زمان ایجاد کنید، افزودن انتخابگر به برنامه را بخوانید.

ایجاد قطعه کادر گفتگو

با گسترش DialogFragment و ایجاد AlertDialog در روش onCreateDialog() بازخوان، می‌توانید انواع مختلفی از طراحی‌های کادر گفتگو را انجام دهید، ازجمله چیدمان‌های سفارشی و مواردی که در کادرهای گفتگوی «طراحی مواد» توضیح داده شده است.

برای مثال، در اینجا AlertDialog پایه که در DialogFragment مدیریت می‌شود آورده شده است:

کاتلین

class StartGameDialogFragment : DialogFragment() {
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return activity?.let {
            // Use the Builder class for convenient dialog construction.
            val builder = AlertDialog.Builder(it)
            builder.setMessage("Start game")
                .setPositiveButton("Start") { dialog, id ->
                    // START THE GAME!
                }
                .setNegativeButton("Cancel") { dialog, id ->
                    // User cancelled the dialog.
                }
            // Create the AlertDialog object and return it.
            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }
}

class OldXmlActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_old_xml)

        StartGameDialogFragment().show(supportFragmentManager, "GAME_DIALOG")
    }
}

جاوا

public class StartGameDialogFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction.
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(R.string.dialog_start_game)
               .setPositiveButton(R.string.start, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // START THE GAME!
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // User cancels the dialog.
                   }
               });
        // Create the AlertDialog object and return it.
        return builder.create();
    }
}
// ...

StartGameDialogFragment().show(supportFragmentManager, "GAME_DIALOG");

وقتی نمونه‌ای از این کلاس را ایجاد می‌کنید و show() را در آن شیء فرا می‌خوانید، کادر گفتگو همان‌طور که در شکل زیر نشان داده شده است ظاهر می‌شود.

تصویری که کادر گفتگوی ساده‌ای را با دو دکمه کنش نشان می‌دهد
شکل ۲. کادر گفتگویی با پیام و دو دکمه کنش.

بخش بعدی جزئیات بیشتری درباره استفاده از AlertDialog.Builder میاناهای برنامه‌سازی کاربردی برای ایجاد کادر گفتگو ارائه می‌دهد.

بسته به پیچیدگی کادربندی، می‌توانید انواع مختلفی از روش‌های دیگر پاسخ‌گویی در DialogFragment، ازجمله همه روش‌های پایه چرخه حیات قطعه را پیاده‌سازی کنید.

ساختن کادر گفتگوی هشدار

کلاس AlertDialog به شما امکان می‌دهد انواع مختلفی از طراحی‌های کادر گفتگو بسازید و اغلب تنها کلاس کادر گفتگویی است که به آن نیاز دارید. همان‌طور که در شکل زیر نشان داده شده است، سه ناحیه در کادر گفتگوی هشدار وجود دارد:

  • عنوان: این مورد اختیاری است و فقط زمانی استفاده می‌شود که ناحیه محتوا توسط پیام، فهرست، یا چیدمان سفارشی مفصلی اشغال شده باشد. اگر نیاز دارید پیام یا سؤال ساده‌ای را بیان کنید، به عنوان نیاز ندارید.
  • ناحیه محتوا: این ناحیه می‌تواند پیام، فهرست، یا چیدمان سفارشی دیگری را نمایش دهد.
  • دکمه‌های کنش: در یک چارگوش گفتگو می‌تواند حداکثر سه دکمه کنش وجود داشته باشد.

کلاس AlertDialog.Builder میاناهای برنامه‌سازی کاربردی‌ای ارائه می‌دهد که به شما امکان می‌دهد AlertDialog را با این نوع محتوا، ازجمله چیدمان سفارشی، ایجاد کنید.

برای ساختن AlertDialog، این کارها را انجام دهید:

کاتلین

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setMessage("I am the message")
    .setTitle("I am the title")

val dialog: AlertDialog = builder.create()
dialog.show()

جاوا

// 1. Instantiate an AlertDialog.Builder with its constructor.
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

// 2. Chain together various setter methods to set the dialog characteristics.
builder.setMessage(R.string.dialog_message)
       .setTitle(R.string.dialog_title);

// 3. Get the AlertDialog.
AlertDialog dialog = builder.create();

تکه کد قبلی این چارگوش گفتگو را تولید می‌کند:

تصویری که کادر گفتگویی با عنوان، ناحیه محتوا، و دو دکمه کنش را نشان می‌دهد.
شکل ۳. چیدمان کادر گفتگوی هشدار پایه.

افزودن دکمه

برای افزودن دکمه‌های کنش مثل دکمه‌های شکل ۲، روش‌های setPositiveButton() و setNegativeButton() را فراخوانی کنید:

کاتلین

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setMessage("I am the message")
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

جاوا

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Add the buttons.
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // User taps OK button.
           }
       });
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // User cancels the dialog.
           }
       });
// Set other dialog properties.
...

// Create the AlertDialog.
AlertDialog dialog = builder.create();

روش‌های set...Button() به عنوانی برای دکمه نیاز دارند که ازطریق منبع رشته ارائه می‌شود و DialogInterface.OnClickListener که کنش موردنظر را هنگام ضربه زدن کاربر روی دکمه تعریف می‌کند.

سه دکمه کنش وجود دارد که می‌توانید اضافه کنید:

  • مثبت: از این برای پذیرفتن و ادامه دادن کنش (کنش «تأیید») استفاده کنید.
  • منفی: از این برای لغو کردن کنش استفاده کنید.
  • خنثی: از این گزینه زمانی استفاده کنید که کاربر ممکن است نخواهد کنش را ادامه دهد اما لزوماً نمی‌خواهد آن را لغو کند. این دکمه بین دکمه‌های مثبت و منفی قرار می‌گیرد. برای مثال، کنش می‌تواند «بعداً به من یادآوری کن» باشد.

فقط می‌توانید یک دکمه از هر نوع به AlertDialog اضافه کنید. برای مثال، نمی‌توانید بیش‌از یک دکمه «مثبت» داشته باشید.

تکه کد قبلی چارگوش گفتگوی هشداری مانند زیر به شما می‌دهد:

تصویری که چارگوش گفتگوی هشدار را با عنوان، پیام، و دو دکمه کنش نشان می‌دهد.
شکل ۴. کادر گفتگوی هشداری با عنوان، پیام، و دو دکمه کنش.

افزودن فهرست

سه نوع فهرست با AlertDialog API دردسترس است:

  • فهرست سنتی تک‌انتخابی.
  • فهرست انتخاب تکی دائمی (دکمه‌های رادیویی).
  • فهرست چندگزینه‌ای دائمی (چارگوش‌های انتخاب).

برای ایجاد فهرست تک‌انتخابی مانند فهرست شکل ۵، از روش setItems() استفاده کنید:


کاتلین

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }
    .setItems(arrayOf("Item One", "Item Two", "Item Three")) { dialog, which ->
        // Do something on item tapped.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

جاوا

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle(R.string.pick_color)
           .setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int which) {
               // The 'which' argument contains the index position of the selected item.
           }
    });
    return builder.create();
}

این تکه‌کد کادر گفتگویی مانند زیر تولید می‌کند:

تصویری که کادر گفتگویی با عنوان و فهرست را نشان می‌دهد.
شکل ۵. کادر گفتگویی با عنوان و فهرست.

چون فهرست در ناحیه محتوای کادر گفتگو نشان داده می‌شود، کادر گفتگو نمی‌تواند هم پیام و هم فهرست را نشان دهد. با setTitle()، عنوانی برای کادر گفتگو تنظیم کنید. برای مشخص کردن موارد فهرست، با setItems() تماس بگیرید و آرایه‌ای را ارسال کنید. یا می‌توانید بااستفاده از setAdapter() فهرستی را مشخص کنید. با این کار می‌توانید فهرست را با داده‌های پویا—مثلاً از پایگاه داده—بااستفاده از ListAdapter پشتیبانی کنید.

اگر فهرستتان را با ListAdapter پشتیبانی می‌کنید، همیشه از Loader استفاده کنید تا محتوا به‌صورت ناهمزمان بار شود. این موضوع در ساختن چیدمان‌ها با آداپتور و بارکننده‌ها بیشتر توضیح داده شده است.

افزودن فهرست چندگزینه‌ای یا تک‌گزینه‌ای ماندگار

برای افزودن فهرستی از موارد چندگزینه‌ای (چارگوش‌های انتخاب) یا موارد تک‌گزینه‌ای (دکمه‌های رادیویی)، به‌ترتیب از روش‌های setMultiChoiceItems() یا setSingleChoiceItems() استفاده کنید.

برای مثال، در اینجا نحوه ایجاد فهرست چندگزینه‌ای مانند فهرست نشان‌داده‌شده در شکل ۶ آمده است که موارد انتخاب‌شده را در ArrayList ذخیره می‌کند:

کاتلین

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }
    .setMultiChoiceItems(
        arrayOf("Item One", "Item Two", "Item Three"), null) { dialog, which, isChecked ->
        // Do something.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

جاوا

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    selectedItems = new ArrayList();  // Where we track the selected items
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Set the dialog title.
    builder.setTitle(R.string.pick_toppings)
    // Specify the list array, the items to be selected by default (null for
    // none), and the listener through which to receive callbacks when items
    // are selected.
           .setMultiChoiceItems(R.array.toppings, null,
                      new DialogInterface.OnMultiChoiceClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int which,
                       boolean isChecked) {
                   if (isChecked) {
                       // If the user checks the item, add it to the selected
                       // items.
                       selectedItems.add(which);
                   } else if (selectedItems.contains(which)) {
                       // If the item is already in the array, remove it.
                       selectedItems.remove(which);
                   }
               }
           })
    // Set the action buttons
           .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // User taps OK, so save the selectedItems results
                   // somewhere or return them to the component that opens the
                   // dialog.
                   ...
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   ...
               }
           });

    return builder.create();
}
تصویری که کادر گفتگویی حاوی فهرستی از موارد چندگزینه‌ای را نشان می‌دهد.
شکل ۶. فهرستی از موارد چندگزینه‌ای.

کادر گفتگوی هشدار تک‌انتخابی را می‌توان به این صورت دریافت کرد:

کاتلین

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }
    .setSingleChoiceItems(
        arrayOf("Item One", "Item Two", "Item Three"), 0
    ) { dialog, which ->
        // Do something.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

جاوا

        String[] choices = {"Item One", "Item Two", "Item Three"};
        
        AlertDialog.Builder builder = AlertDialog.Builder(context);
        builder
                .setTitle("I am the title")
                .setPositiveButton("Positive", (dialog, which) -> {

                })
                .setNegativeButton("Negative", (dialog, which) -> {

                })
                .setSingleChoiceItems(choices, 0, (dialog, which) -> {

                });

        AlertDialog dialog = builder.create();
        dialog.show();

این کار به مثال زیر منجر می‌شود:

تصویری که کادر گفتگویی حاوی فهرستی از موارد تک‌انتخابی را نشان می‌دهد.
شکل ۷. فهرستی از موارد تک‌انتخابی.

ایجاد چیدمان سفارشی

اگر می‌خواهید در کادر گفتگویی چیدمان سفارشی داشته باشید، چیدمانی بسازید و با فراخوانی setView() در شیء AlertDialog.Builder، آن را به AlertDialog اضافه کنید.

تصویری که چیدمان کادر گفتگوی سفارشی را نشان می‌دهد.
شکل ۸. چیدمان کادر گفتگوی سفارشی.

به‌طور پیش‌فرض، چیدمان سفارشی پنجره گفتگوی را پر می‌کند، اما همچنان می‌توانید از AlertDialog.Builder روش برای افزودن دکمه‌ها و عنوان استفاده کنید.

برای مثال، در اینجا فایل چیدمان برای چارگوش گفتگوی سفارشی قبلی آمده است چیدمان:

res/layout/dialog_signin.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <ImageView
        android:src="@drawable/header_logo"
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:scaleType="center"
        android:background="#FFFFBB33"
        android:contentDescription="@string/app_name" />
    <EditText
        android:id="@+id/username"
        android:inputType="textEmailAddress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginBottom="4dp"
        android:hint="@string/username" />
    <EditText
        android:id="@+id/password"
        android:inputType="textPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginBottom="16dp"
        android:fontFamily="sans-serif"
        android:hint="@string/password"/>
</LinearLayout>

برای ازهم بازکردن چیدمان در DialogFragment، LayoutInflater با getLayoutInflater() را دریافت کنید و inflate() را فراخوانی کنید. پارامتر اول شناسه منبع چیدمان و پارامتر دوم نمای والد برای چیدمان است. سپس می‌توانید setView() را فراخوانی کنید تا چیدمان را در کادر گفتگو قرار دهید. این مورد در مثال زیر نشان داده شده است.

کاتلین

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return activity?.let {
        val builder = AlertDialog.Builder(it)
        // Get the layout inflater.
        val inflater = requireActivity().layoutInflater;

        // Inflate and set the layout for the dialog.
        // Pass null as the parent view because it's going in the dialog
        // layout.
        builder.setView(inflater.inflate(R.layout.dialog_signin, null))
                // Add action buttons.
                .setPositiveButton(R.string.signin,
                        DialogInterface.OnClickListener { dialog, id ->
                            // Sign in the user.
                        })
                .setNegativeButton(R.string.cancel,
                        DialogInterface.OnClickListener { dialog, id ->
                            getDialog().cancel()
                        })
        builder.create()
    } ?: throw IllegalStateException("Activity cannot be null")
}

جاوا

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Get the layout inflater.
    LayoutInflater inflater = requireActivity().getLayoutInflater();

    // Inflate and set the layout for the dialog.
    // Pass null as the parent view because it's going in the dialog layout.
    builder.setView(inflater.inflate(R.layout.dialog_signin, null))
    // Add action buttons
           .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // Sign in the user.
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   LoginDialogFragment.this.getDialog().cancel();
               }
           });
    return builder.create();
}

اگر می‌خواهید گفتگوی سفارشی داشته باشید، می‌توانید به‌جای استفاده از میاناهای برنامه‌سازی کاربردی Dialog، Activity را به‌عنوان گفتگو نمایش دهید. فعالیتی ایجاد کنید و زمینه آن را روی Theme.Holo.Dialog در <activity> عنصر مانیفست تنظیم کنید:

<activity android:theme="@android:style/Theme.Holo.Dialog" >

اکنون فعالیت در پنجره گفتگو به‌جای تمام‌صفحه نمایش داده می‌شود.

رویدادها را به میزبان کادر گفتگو برمی‌گرداند

وقتی کاربر روی یکی از دکمه‌های کنش کادر گفتگو ضربه می‌زند یا موردی را از فهرست آن انتخاب می‌کند، DialogFragment شما ممکن است کنش لازم را خودش انجام دهد، اما اغلب می‌خواهید رویداد را به فعالیت یا قطعه‌ای که کادر گفتگو را باز می‌کند تحویل دهید. برای انجام این کار، واسطی با روشی برای هر نوع رویداد کلیک تعریف کنید. سپس، آن میانای کاربری را در عنصر میزبان پیاده‌سازی کنید که رویدادهای کنش را از کادر گفتگو دریافت می‌کند.

برای مثال، در اینجا DialogFragment وجود دارد که رابطی را تعریف می‌کند که ازطریق آن رویدادها را به فعالیت میزبان برمی‌گرداند:

کاتلین

class NoticeDialogFragment : DialogFragment() {
    // Use this instance of the interface to deliver action events.
    internal lateinit var listener: NoticeDialogListener

    // The activity that creates an instance of this dialog fragment must
    // implement this interface to receive event callbacks. Each method passes
    // the DialogFragment in case the host needs to query it.
    interface NoticeDialogListener {
        fun onDialogPositiveClick(dialog: DialogFragment)
        fun onDialogNegativeClick(dialog: DialogFragment)
    }

    // Override the Fragment.onAttach() method to instantiate the
    // NoticeDialogListener.
    override fun onAttach(context: Context) {
        super.onAttach(context)
        // Verify that the host activity implements the callback interface.
        try {
            // Instantiate the NoticeDialogListener so you can send events to
            // the host.
            listener = context as NoticeDialogListener
        } catch (e: ClassCastException) {
            // The activity doesn't implement the interface. Throw exception.
            throw ClassCastException((context.toString() +
                    " must implement NoticeDialogListener"))
        }
    }
}

جاوا

public class NoticeDialogFragment extends DialogFragment {

    // The activity that creates an instance of this dialog fragment must
    // implement this interface to receive event callbacks. Each method passes
    // the DialogFragment in case the host needs to query it.
    public interface NoticeDialogListener {
        public void onDialogPositiveClick(DialogFragment dialog);
        public void onDialogNegativeClick(DialogFragment dialog);
    }

    // Use this instance of the interface to deliver action events.
    NoticeDialogListener listener;

    // Override the Fragment.onAttach() method to instantiate the
    // NoticeDialogListener.
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // Verify that the host activity implements the callback interface.
        try {
            // Instantiate the NoticeDialogListener so you can send events to
            // the host.
            listener = (NoticeDialogListener) context;
        } catch (ClassCastException e) {
            // The activity doesn't implement the interface. Throw exception.
            throw new ClassCastException(activity.toString()
                    + " must implement NoticeDialogListener");
        }
    }
    ...
}

فعالیتی که میزبان کادر گفتگو است نمونه‌ای از کادر گفتگو را با سازنده تکه کادر گفتگو ایجاد می‌کند و رویدادهای کادر گفتگو را ازطریق پیاده‌سازی رابط NoticeDialogListener دریافت می‌کند:

کاتلین

class MainActivity : FragmentActivity(),
        NoticeDialogFragment.NoticeDialogListener {

    fun showNoticeDialog() {
        // Create an instance of the dialog fragment and show it.
        val dialog = NoticeDialogFragment()
        dialog.show(supportFragmentManager, "NoticeDialogFragment")
    }

    // The dialog fragment receives a reference to this Activity through the
    // Fragment.onAttach() callback, which it uses to call the following
    // methods defined by the NoticeDialogFragment.NoticeDialogListener
    // interface.
    override fun onDialogPositiveClick(dialog: DialogFragment) {
        // User taps the dialog's positive button.
    }

    override fun onDialogNegativeClick(dialog: DialogFragment) {
        // User taps the dialog's negative button.
    }
}

جاوا

public class MainActivity extends FragmentActivity
                          implements NoticeDialogFragment.NoticeDialogListener{
    ...
    public void showNoticeDialog() {
        // Create an instance of the dialog fragment and show it.
        DialogFragment dialog = new NoticeDialogFragment();
        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
    }

    // The dialog fragment receives a reference to this Activity through the
    // Fragment.onAttach() callback, which it uses to call the following
    // methods defined by the NoticeDialogFragment.NoticeDialogListener
    // interface.
    @Override
    public void onDialogPositiveClick(DialogFragment dialog) {
        // User taps the dialog's positive button.
        ...
    }

    @Override
    public void onDialogNegativeClick(DialogFragment dialog) {
        // User taps the dialog's negative button.
        ...
    }
}

چون فعالیت میزبان NoticeDialogListener را پیاده‌سازی می‌کند—که توسط onAttach() روش تماس برگشتی نشان‌داده‌شده در مثال قبلی اعمال می‌شود—تکه‌گفتگوی می‌تواند از روش‌های تماس برگشتی رابط برای ارائه رویدادهای کلیک به فعالیت استفاده کند:

کاتلین

    override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
        return activity?.let {
            // Build the dialog and set up the button click handlers.
            val builder = AlertDialog.Builder(it)

            builder.setMessage(R.string.dialog_start_game)
                    .setPositiveButton(R.string.start,
                            DialogInterface.OnClickListener { dialog, id ->
                                // Send the positive button event back to the
                                // host activity.
                                listener.onDialogPositiveClick(this)
                            })
                    .setNegativeButton(R.string.cancel,
                            DialogInterface.OnClickListener { dialog, id ->
                                // Send the negative button event back to the
                                // host activity.
                                listener.onDialogNegativeClick(this)
                            })

            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }

جاوا

public class NoticeDialogFragment extends DialogFragment {
    ...
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Build the dialog and set up the button click handlers.
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(R.string.dialog_start_game)
               .setPositiveButton(R.string.start, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Send the positive button event back to the host activity.
                       listener.onDialogPositiveClick(NoticeDialogFragment.this);
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Send the negative button event back to the host activity.
                       listener.onDialogNegativeClick(NoticeDialogFragment.this);
                   }
               });
        return builder.create();
    }
}

نمایش کادر گفتگو

وقتی می‌خواهید کادر گفتگوی خود را نشان دهید، نمونه‌ای از DialogFragment ایجاد کنید و show() را فراخوانی کنید، با ارسال FragmentManager و نام برچسب برای قطعه کادر گفتگو.

می‌توانید FragmentManager را با تماس گرفتن با getSupportFragmentManager() از FragmentActivity یا با تماس گرفتن با getParentFragmentManager() از Fragment دریافت کنید. برای مثال، به موارد زیر مراجعه کنید:

کاتلین

fun confirmStartGame() {
    val newFragment = StartGameDialogFragment()
    newFragment.show(supportFragmentManager, "game")
}

جاوا

public void confirmStartGame() {
    DialogFragment newFragment = new StartGameDialogFragment();
    newFragment.show(getSupportFragmentManager(), "game");
}

دومین آرگومان، "game"، نام برچسب منحصربه‌فردی است که سیستم از آن برای ذخیره و بازیابی وضعیت قطعه درصورت لزوم استفاده می‌کند. برچسب همچنین به شما امکان می‌دهد با فراخوانی findFragmentByTag() به قطعه دسترسی پیدا کنید.

نمایش کادر گفتگو به‌صورت تمام‌صفحه یا به‌عنوان تکه‌کد جاسازی‌شده

ممکن است بخواهید بخشی از طراحی واسط کاربر شما در برخی‌از موقعیت‌ها به‌صورت کادر گفتگو و در برخی دیگر به‌صورت تمام‌صفحه یا قطعه جاسازی‌شده نمایش داده شود. همچنین ممکن است بخواهید بسته به اندازه صفحه نمایش دستگاه، به‌صورت متفاوتی نمایش داده شود. کلاس DialogFragment برای انجام این کار انعطاف‌پذیری ارائه می‌دهد، زیرا می‌تواند به‌عنوان Fragment جاسازی‌شدنی عمل کند.

بااین‌حال، نمی‌توانید از AlertDialog.Builder یا Dialog اشیای دیگر برای ساختن کادر گفتگو در این مورد استفاده کنید. اگر می‌خواهید DialogFragment جاسازی‌شدنی باشد، واسط کاربر گفتگوی را در چیدمان تعریف کنید، سپس چیدمان را در onCreateView() بازخوان بار کنید.

در اینجا نمونه‌ای از DialogFragment آورده شده است که می‌تواند به‌صورت کادر گفتگو یا تکه‌کد جاسازی‌شدنی، بااستفاده از چیدمانی به‌نام purchase_items.xml ظاهر شود:

کاتلین

class CustomDialogFragment : DialogFragment() {

    // The system calls this to get the DialogFragment's layout, regardless of
    // whether it's being displayed as a dialog or an embedded fragment.
    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
        // Inflate the layout to use as a dialog or embedded fragment.
        return inflater.inflate(R.layout.purchase_items, container, false)
    }

    // The system calls this only when creating the layout in a dialog.
    override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
        // The only reason you might override this method when using
        // onCreateView() is to modify the dialog characteristics. For example,
        // the dialog includes a title by default, but your custom layout might
        // not need it. Here, you can remove the dialog title, but you must
        // call the superclass to get the Dialog.
        val dialog = super.onCreateDialog(savedInstanceState)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        return dialog
    }
}

جاوا

public class CustomDialogFragment extends DialogFragment {
    // The system calls this to get the DialogFragment's layout, regardless of
    // whether it's being displayed as a dialog or an embedded fragment.
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Inflate the layout to use as a dialog or embedded fragment.
        return inflater.inflate(R.layout.purchase_items, container, false);
    }

    // The system calls this only when creating the layout in a dialog.
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // The only reason you might override this method when using
        // onCreateView() is to modify the dialog characteristics. For example,
        // the dialog includes a title by default, but your custom layout might
        // not need it. Here, you can remove the dialog title, but you must
        // call the superclass to get the Dialog.
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        return dialog;
    }
}

مثال زیر براساس اندازه صفحه تعیین می‌کند که آیا این تکه‌برنامه به‌عنوان کادر گفتگو یا میانای کاربر تمام‌صفحه نمایش داده شود:

کاتلین

fun showDialog() {
    val fragmentManager = supportFragmentManager
    val newFragment = CustomDialogFragment()
    if (isLargeLayout) {
        // The device is using a large layout, so show the fragment as a
        // dialog.
        newFragment.show(fragmentManager, "dialog")
    } else {
        // The device is smaller, so show the fragment fullscreen.
        val transaction = fragmentManager.beginTransaction()
        // For a polished look, specify a transition animation.
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity.
        transaction
                .add(android.R.id.content, newFragment)
                .addToBackStack(null)
                .commit()
    }
}

جاوا

public void showDialog() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    CustomDialogFragment newFragment = new CustomDialogFragment();

    if (isLargeLayout) {
        // The device is using a large layout, so show the fragment as a
        // dialog.
        newFragment.show(fragmentManager, "dialog");
    } else {
        // The device is smaller, so show the fragment fullscreen.
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        // For a polished look, specify a transition animation.
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity.
        transaction.add(android.R.id.content, newFragment)
                   .addToBackStack(null).commit();
    }
}

برای کسب اطلاعات بیشتر درباره انجام تراکنش‌های قطعه، به قطعه‌ها مراجعه کنید.

در این مثال، مقدار بولی mIsLargeLayout مشخص می‌کند که آیا دستگاه کنونی باید از طراحی چیدمان بزرگ برنامه استفاده کند و درنتیجه این تکه را به‌صورت کادر گفتگو نمایش دهد یا تمام‌صفحه. بهترین راه برای تنظیم این نوع مقدار بولی این است که مقدار منبع bool را با مقدار منبع جایگزین برای اندازه‌های مختلف صفحه اعلام کنید. برای مثال، در اینجا دو نسخه از منبع بولی برای اندازه‌های مختلف صفحه‌نمایش آورده شده است:

res/values/bools.xml

<!-- Default boolean values -->
<resources>
    <bool name="large_layout">false</bool>
</resources>

res/values-large/bools.xml

<!-- Large screen boolean values -->
<resources>
    <bool name="large_layout">true</bool>
</resources>

سپس می‌توانید مقدار mIsLargeLayout را درطول روش onCreate() فعالیت مقداردهی اولیه کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    isLargeLayout = resources.getBoolean(R.bool.large_layout)
}

جاوا

boolean isLargeLayout;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    isLargeLayout = getResources().getBoolean(R.bool.large_layout);
}

نمایش فعالیت به‌عنوان کادر گفتگو در صفحه‌نمایش‌های بزرگ

به‌جای نمایش کادر گفتگو به‌عنوان میانای کاربری تمام‌صفحه در صفحه‌های کوچک، می‌توانید با نمایش Activity به‌عنوان کادر گفتگو در صفحه‌های بزرگ، به نتیجه یکسانی برسید. روشی که انتخاب می‌کنید به طراحی برنامه‌تان بستگی دارد، اما وقتی برنامه‌تان برای صفحه‌های کوچک طراحی شده است و می‌خواهید با نمایش فعالیت کوتاه‌مدت به‌عنوان کادر گفتگو، تجربه کاربری را در رایانه‌های لوحی بهبود دهید، اغلب نمایش فعالیت به‌عنوان کادر گفتگو مفید است.

برای نمایش فعالیت به‌عنوان کادر گفتگو فقط در صفحه‌نمایش‌های بزرگ، Theme.Holo.DialogWhenLarge زمینه را به عنصر مانیفست <activity> اعمال کنید:

<activity android:theme="@android:style/Theme.Holo.DialogWhenLarge" >

برای کسب اطلاعات بیشتر درباره سبک‌دهی فعالیت‌ها با زمینه، به سبک‌ها و زمینه‌ها مراجعه کنید.

بستن کادر گفتگو

وقتی کاربر روی دکمه کنشی که با AlertDialog.Builder ساخته شده است تک‌ضرب می‌زند، سیستم کادر گفتگو را برای شما می‌بندد.

وقتی کاربر روی موردی در فهرست کادر گفتگو تک‌ضرب می‌زند، سیستم نیز کادر گفتگو را می‌بندد، مگر اینکه فهرست از دکمه‌های رادیویی یا چارگوش‌های انتخاب استفاده کند. درغیراین‌صورت، می‌توانید با فراخوانی dismiss() در DialogFragment، کادر گفتگوی خود را به‌صورت دستی ببندید.

اگر نیاز دارید وقتی چارگوش گفتگو بسته می‌شود کنش‌های خاصی انجام دهید، می‌توانید روش onDismiss() را در DialogFragment پیاده‌سازی کنید.

همچنین می‌توانید یک گفتگو را لغو کنید. این رویداد ویژه نشان می‌دهد که کاربر بدون تکمیل کردن تکلیف از چارگوش گفتگو خارج می‌شود. این اتفاق زمانی می‌افتد که کاربر روی دکمه «برگشتن» یا روی صفحه‌نمایش خارج از ناحیه کادر گفتگو تک‌ضرب بزند یا اگر به‌طور صریح cancel() را در Dialog فراخوانی کنید، مثلاً در پاسخ به دکمه «لغو» در کادر گفتگو.

همان‌طور که در مثال قبلی نشان داده شده است، می‌توانید با پیاده‌سازی onCancel() در کلاس DialogFragment به رویداد لغو پاسخ دهید.