Diálogo simple de Android.Creemos cuadros de diálogo simples y reutilizables… | Por Kaan Çelen | Accenture Industries X Turquía | Marzo de 2022

Vamos a crear diálogos simples y reutilizables. Nuestra demostración final se verá así.
Puede encontrar el código fuente aquí => https://github.com/kaancelen/SimpleDialog
Mi objetivo es proporcionar un icono, un título, una descripción y una etiqueta de botón al crear un cuadro de diálogo y registrar un oyente de clic en el botón. De modo que puede utilizar el mismo cuadro de diálogo con diferente texto y funcionalidad.

Primero creemos nuestro dialog_simple.xml. Debe tener un aspecto como este. Por supuesto, puede personalizar el cuadro de diálogo según sus necesidades.

xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_dialog"> android:id="@+id/iv_dialog_icon"
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
android:layout_marginTop="@dimen/spacing_l"
android:src="@drawable/ic_success"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android:id="@+id/tv_dialog_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_xl"
android:layout_marginTop="@dimen/spacing_xl"
android:layout_marginEnd="@dimen/spacing_xl"
android:textSize="@dimen/text_size_xl"
android:textColor="@color/black"
android:gravity="center"
tools:text="Title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iv_dialog_icon" />
android:id="@+id/tv_dialog_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_xl"
android:layout_marginTop="@dimen/spacing_s"
android:layout_marginEnd="@dimen/spacing_xl"
android:textSize="@dimen/text_size_l"
android:textColor="@color/black"
android:gravity="center"
tools:text="Description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_dialog_title" />
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2"
android:paddingHorizontal="@dimen/spacing_xl"
android:paddingVertical="@dimen/spacing_xl"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_dialog_description">
android:id="@+id/bt_dialog_negative"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_weight="1"
android:layout_marginEnd="@dimen/spacing_s"
android:backgroundTint="@color/grey"
android:gravity="center"
android:text="@string/negative_button_label"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="@dimen/text_size_l" />
android:id="@+id/bt_dialog_positive"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_weight="1"
android:layout_marginStart="@dimen/spacing_s"
android:gravity="center"
android:text="@string/positive_button_label"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="@dimen/text_size_l" />
Ahora que mi dialog_simple.xml está listo, es hora de implementar la clase SimpleDialog. Antes de eso, creé una clase abstracta para nuestro DialogFragment y configuré mi tema y las métricas de diálogo.
abstract class XDialogFragment : DialogFragment() {override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return Dialog(requireActivity(), R.style.Theme_Dialog).apply {
requestWindowFeature(Window.FEATURE_NO_TITLE)
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
}
}
Puse nuevas propiedades de estilo en themes.xml. Configuré %95 porque quiero que mi diálogo tenga un ancho de pantalla estático de %95.Si no lo establece, el ancho se representará como contenidos del paquete.
Es hora de presentar nuestra clase SimpleDialog. Comience con pasos de bebé.
class SimpleDialog : XDialogFragment() {private lateinit var binding: DialogSimpleBinding
override fun onCreateView(
}
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = DialogSimpleBinding.inflate(inflater, container, false)
return binding.root
}
Si ves la línea roja debajo DialogSimpleBinding Esto se debe a que es posible que no tenga viewBinding habilitado en su archivo build.gradle. Ahora ve a tu archivo build.gradle (módulo donde coloques SimpleDialog) y agrega lo siguiente.
plugins {
...
id 'kotlin-android-extensions'
id 'kotlin-kapt'
}android {
...
buildFeatures {
viewBinding true
}
}
Ahora mi objetivo es crear un cuadro de diálogo como el siguiente.
val dialog = SimpleDialog.newInstance(
iconResId = R.drawable.ic_success,
titleResId = R.string.title,
description = getString(R.string.description),
positiveButtonResId = R.string.positive_button_label,
negativeButtonResId = R.string.negative_button_label
)Para lograr esto, creé un método estático que toma un parámetro y lo coloca en el paquete de Dialog. Use las anotaciones «@DrawableRes» «@StringRes» para pasar recursos directamente.
class SimpleDialog : XDialogFragment() {
...
companion object {
private const val ARG_KEY_TITLE = "arg_key_title"
private const val ARG_KEY_DESCRIPTION = "arg_key_description"
private const val ARG_KEY_BUTTON_POSITIVE = "arg_key_button_positive"
private const val ARG_KEY_BUTTON_NEGATIVE = "arg_key_button_negative"
private const val ARG_KEY_ICON = "arg_key_icon"fun newInstance(
@DrawableRes iconResId: Int?,
@StringRes titleResId: Int?,
description: String?,
@StringRes positiveButtonResId: Int?,
@StringRes negativeButtonResId: Int?
) = SimpleDialog().apply {
arguments = Bundle().apply {
iconResId?.let {
putInt(ARG_KEY_ICON, it)
}
titleResId?.let {
putInt(ARG_KEY_TITLE, it)
}
description?.let {
putString(ARG_KEY_DESCRIPTION, it)
}
positiveButtonResId?.let {
putInt(ARG_KEY_BUTTON_POSITIVE, it)
}
negativeButtonResId?.let {
putInt(ARG_KEY_BUTTON_NEGATIVE, it)
}
}
}
}
}
Ahora es el momento de analizar el paquete y asignarlo a la interfaz de usuario.vamos a cubrir onViewCreated
Si no desea que el usuario cierre el cuadro de diálogo sin presionar ningún botón (como tocar fuera del cuadro de diálogo o presionar el botón Atrás).necesitas configurar esCancelable = falso
class SimpleDialog : XDialogFragment() {
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)isCancelable = false // Prevent user dismiss
arguments?.getInt(ARG_KEY_ICON)?.let {
if (it != 0) {
binding.ivDialogIcon.setImageResource(it)
}
}
arguments?.getInt(ARG_KEY_TITLE)?.let {
if (it != 0) {
binding.tvDialogTitle.setText(it)
}
}
arguments?.getString(ARG_KEY_DESCRIPTION)?.let {
if (it.isNotEmpty()) {
binding.tvDialogDescription.text = it
}
}
arguments?.getInt(ARG_KEY_BUTTON_POSITIVE)?.let {
if (it != 0) {
binding.btDialogPositive.setText(it)
}
}
arguments?.getInt(ARG_KEY_BUTTON_NEGATIVE)?.let {
if (it != 0) {
binding.btDialogNegative.setText(it)
}
}
}
...
}
Ahora que estamos casi listos, lo único que falta es el botón de devolución de llamada. Vamos a crear un alias de tipo para onClickListener y agregar el método de registro a nuestro SimpleDialog.
class SimpleDialog : XDialogFragment() {...
private var positiveListener: OnClickListener? = null
private var negativeListener: OnClickListener? = null
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
binding.btDialogPositive.setOnClickListener {
dismiss()
positiveListener?.invoke()
}
binding.btDialogNegative.setOnClickListener {
dismiss()
negativeListener?.invoke()
}
}
fun setOnPositiveClickListener(listener: OnClickListener) {
positiveListener = listener
}
fun setOnNegativeClickListener(listener: OnClickListener) {
negativeListener = listener
}
...
}
typealias OnClickListener = () -> Unit
Podemos registrar al usuario haciendo clic como a continuación.
val dialog = SimpleDialog.newInstance(
iconResId = R.drawable.ic_success,
titleResId = R.string.title,
description = getString(R.string.description),
positiveButtonResId = R.string.positive_button_label,
negativeButtonResId = R.string.negative_button_label
)
dialog.setOnPositiveClickListener {
Toast.makeText(this, "Positive Button Clicked", Toast.LENGTH_LONG).show()
}
dialog.setOnNegativeClickListener {
Toast.makeText(this, "Negative Button Clicked", Toast.LENGTH_LONG).show()
}








