Diferencia entre revisiones de «Ventás de Diálogos»

De MediaWiki
Ir a la navegación Ir a la búsqueda
(O código Java do DialogFragment)
(Diálogo cunha selección múltiple (checkboxes))
(No se muestran 10 ediciones intermedias del mismo usuario)
Línea 197: Línea 197:
  
 
</android.support.constraint.ConstraintLayout>
 
</android.support.constraint.ConstraintLayout>
</ScrollView>
 
 
</LinearLayout>
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Línea 208: Línea 205:
  
  
<syntaxhighlight lang="xml" line enclose="div" highlight="1" >
+
<syntaxhighlight lang="xml" line enclose="div" highlight="" >
 
<?xml version="1.0" encoding="utf-8"?>
 
<?xml version="1.0" encoding="utf-8"?>
<resources>
 
 
<resources>
 
<resources>
 
     <string name="app_name">Aprendiendo</string>
 
     <string name="app_name">Aprendiendo</string>
Línea 238: Línea 234:
  
 
<br />
 
<br />
 +
 
===Definición do recurso de tipo Layout usado polo diálogo con entrada de texto (o último)===
 
===Definición do recurso de tipo Layout usado polo diálogo con entrada de texto (o último)===
 
Explicado posteriormente.
 
Explicado posteriormente.
Línea 965: Línea 962:
  
  
* No caso de implementar a Interface a nivel da Activity como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Xesti%C3%B3n_de_Eventos xa vimos nesta Wiki], ao método onClick chegará como información o Diálog e o botón que foi premido.
+
* No caso de implementar a Interface a nivel da Activity como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Xesti%C3%B3n_de_Eventos xa vimos nesta Wiki], ao método onClick chegará como información o Diálog e o botón que foi premido. (ler nota ao final do exemplo)
 +
 
 
:* Os botóns se poden identificar polas constantes definidas na [https://developer.android.com/reference/android/content/DialogInterface clase DialogInterface]
 
:* Os botóns se poden identificar polas constantes definidas na [https://developer.android.com/reference/android/content/DialogInterface clase DialogInterface]
 
::* [https://developer.android.com/reference/android/content/DialogInterface#BUTTON_POSITIVE DialogInterface.BUTTON_POSITIVE]
 
::* [https://developer.android.com/reference/android/content/DialogInterface#BUTTON_POSITIVE DialogInterface.BUTTON_POSITIVE]
Línea 1016: Línea 1014:
 
:::'''Liñas 6-13:''' Aquí xestionamos o evento OnClick de todos os botóns de todos os diálogos que rexistren o evento contra a interface da Activity.  
 
:::'''Liñas 6-13:''' Aquí xestionamos o evento OnClick de todos os botóns de todos os diálogos que rexistren o evento contra a interface da Activity.  
 
:::'''Liña 33:''' Na liña 33 asociamos o diálogo creado para poder ter unha referencia ao mesmo fora do método.
 
:::'''Liña 33:''' Na liña 33 asociamos o diálogo creado para poder ter unha referencia ao mesmo fora do método.
 +
 +
 +
: <u>'''Nota:'''</u> Probado e parece que non funciona correctamente.
 +
: A referencia ao diálogo creado non se corresponde coa referencia recibida no método DialogInterface.onClick. Aparece un número identificativo decrementado sempre nunha unidade con respecto ao identificador do diálogo no DialogInterface.onClick.
  
  
Línea 1056: Línea 1058:
  
  
     <string-array name="array_elem_seleccion1_ud03_01_dialogs">
+
     <string-array name="array_elem_seleccion1_ud03_02_dialogs">
 
         <item>Opción un</item>
 
         <item>Opción un</item>
 
         <item>Opción dous</item>
 
         <item>Opción dous</item>
Línea 1077: Línea 1079:
 
                 builder.setIcon(android.R.drawable.ic_dialog_alert)
 
                 builder.setIcon(android.R.drawable.ic_dialog_alert)
 
                     .setTitle("Escolle unha opción")
 
                     .setTitle("Escolle unha opción")
                     .setItems(R.array.array_elem_seleccion1_ud03_01_dialogs, new DialogInterface.OnClickListener() {
+
                     .setItems(R.array.array_elem_seleccion1_ud03_02_dialogs, new DialogInterface.OnClickListener() {
 
                     public void onClick(DialogInterface dialog, int posicion) {
 
                     public void onClick(DialogInterface dialog, int posicion) {
 
                         // O usuario selecciona unha das opcións do listado
 
                         // O usuario selecciona unha das opcións do listado
Línea 1169: Línea 1171:
 
<resources>
 
<resources>
  
     <string-array name="array_elem_seleccion2_ud03_01_dialogs">
+
     <string-array name="array_elem_seleccion2_ud03_02_dialogs">
 
         <item>Coche</item>
 
         <item>Coche</item>
 
         <item>Moto</item>
 
         <item>Moto</item>
Línea 1197: Línea 1199:
  
 
                 Resources res = getResources();
 
                 Resources res = getResources();
                 final String[] matriz = res.getStringArray(R.array.array_elem_seleccion2_ud03_01_dialogs);
+
                 final String[] matriz = res.getStringArray(R.array.array_elem_seleccion2_ud03_02_dialogs);
  
 
                 // Non incluír mensaxe dentro de este tipo de diálogo!!!
 
                 // Non incluír mensaxe dentro de este tipo de diálogo!!!
Línea 1332: Línea 1334:
 
====O XML do DialogFragment====
 
====O XML do DialogFragment====
  
'''Código da clase fragment_u3_15_layout_dialogo'''<br/>
+
'''Código da clase fragment_ud03_02_layout_dialogo'''<br/>
 
<syntaxhighlight lang="xml" line enclose="div" highlight="" >
 
<syntaxhighlight lang="xml" line enclose="div" highlight="" >
 
<?xml version="1.0" encoding="utf-8"?>
 
<?xml version="1.0" encoding="utf-8"?>
Línea 1442: Línea 1444:
 
         rootView = inflater.inflate(R.layout.fragment_ud03_02_layout_dialogo, container, false);
 
         rootView = inflater.inflate(R.layout.fragment_ud03_02_layout_dialogo, container, false);
  
         Button btn = (Button) rootView.findViewById(R.id.btnEnDialogo);  // Exemplo de referencia a un view dentro do layout do DialogFragment
+
         Button btn = (Button) rootView.findViewById(R.id.btnPechar_Frg_UD03_02_Dialogs);  // Exemplo de referencia a un view dentro do layout do DialogFragment
 
   
 
   
 
        
 
        
Línea 1500: Línea 1502:
 
                 datosDialogFragment.password = editPassword.getText().toString();
 
                 datosDialogFragment.password = editPassword.getText().toString();
  
                 ((UD03_02_Dialogs)UD03_02_Dlg_Fragments.this.getActivity()).pecharDialogo();  // Poderíamos chamar a algún método da Activity que abriu o Dialog se queremos
+
                 ((UD03_02_Dialogs)getActivity()).pecharDialogo();  // Poderíamos chamar a algún método da Activity que abriu o Dialog se queremos
 
                 dismiss();
 
                 dismiss();
 
             }
 
             }
Línea 1801: Línea 1803:
 
:* '''2º PASO:''' Agora implementamos dita interface no Activity que vai chamar ao DialogFragment. Ao implementala teremos que implementar o su método (neste caso onComplete) o cal levará o obxecto da clase Bundle cos datos.
 
:* '''2º PASO:''' Agora implementamos dita interface no Activity que vai chamar ao DialogFragment. Ao implementala teremos que implementar o su método (neste caso onComplete) o cal levará o obxecto da clase Bundle cos datos.
 
:: Polo tanto, cando dende o DialogFragment se chame a este método cos datos, a Activity principal os recibirá neste parámetro.
 
:: Polo tanto, cando dende o DialogFragment se chame a este método cos datos, a Activity principal os recibirá neste parámetro.
:: Deberemos gardar dito dato nunha propiedade 'local' para poder facer uso del noutros métodos
+
:: Deberemos gardar dito dato nunha propiedade 'local' para poder facer uso del noutros métodos (se o necesitamos)
 
::<syntaxhighlight lang="java" line enclose="div" highlight="4,8-11">
 
::<syntaxhighlight lang="java" line enclose="div" highlight="4,8-11">
 
public class UD03_03_Dialogs extends AppCompatActivity implements View.OnClickListener,UD03_03_Dlg_Fragments.OnCompleteListener {
 
public class UD03_03_Dialogs extends AppCompatActivity implements View.OnClickListener,UD03_03_Dlg_Fragments.OnCompleteListener {
Línea 1813: Línea 1815:
 
     public void onComplete(Bundle bundle) {
 
     public void onComplete(Bundle bundle) {
 
         this.datosDialogFragment = bundle;
 
         this.datosDialogFragment = bundle;
 +
        Toast.makeText(this, Html.fromHtml("NOME:"+ datosDialogFragment.getString("NOME") + "<br/>PASSWORD:"+datosDialogFragment.getString("PASSWORD")),
 
     }
 
     }
  
Línea 1842: Línea 1845:
  
 
                 mOnCompleteListener = (OnCompleteListener) getActivity();
 
                 mOnCompleteListener = (OnCompleteListener) getActivity();
                 mOnCompleteListener.onComplete(datos);
+
                 mOnCompleteListener.onComplete(datos); // Agora xa chamamos a un método do Activity e podemos facer o que queiramos.
  
                 ((UD03_03_Dialogs)UD03_03_Dlg_Fragments.this.getActivity()).pecharDialogo();  // Poderíamos chamar a algún método da Activity que abriu o Dialog se queremos
+
                 //((UD03_02_Dialogs)getActivity()).pecharDialogo();  // Poderíamos chamar a algún método da Activity que abriu o Dialog se queremos
 
                 dismiss();
 
                 dismiss();
 
             }
 
             }
Línea 1853: Línea 1856:
  
  
 
:*'''4º PASO:''' Agora dende a Activity principal, cando se chame ao método 'pecharDialog()' xa ten os datos na propiedade 'datosDialogFragment'.
 
<syntaxhighlight lang="java" line enclose="div" highlight="">
 
    protected void pecharDialogo(){
 
        // O DialogFragment tamén pode chamar a métodos da activity que o invocou
 
        Toast.makeText(this, Html.fromHtml("NOME:"+ datosDialogFragment.getString("NOME") + "<br/>PASSWORD:"+datosDialogFragment.getString("PASSWORD")), Toast.LENGTH_LONG).show();
 
    }
 
  
 
</syntaxhighlight>     
 
</syntaxhighlight>     
Línea 1919: Línea 1915:
  
  
 +
 +
<br />
 +
===Titulos no DialogFragment===
 +
 +
* Como comentei na clase, a medida que van xurdindo novas versións de Android, pode variar o comportamento 'por defecto' dos compoñentes.
 +
: No caso das ventá de diálogo, a partires da versión API 23 (Android 6.0) o título non aparece por defecto.
 +
: Existen varias solucións posibles. Unha delas é a seguinte.
 +
 +
:* Necesitamos crear un style propio da forma seguinte:
 +
::'''Arquivo /res/values/styles.xml'''
 +
::<syntaxhighlight lang="xml" line enclose="div" highlight="" >
 +
    <style name="CustomDialog" parent="@style/Theme.AppCompat.Light.Dialog">
 +
        <item name="android:windowNoTitle">false</item>
 +
    </style>
 +
</syntaxhighlight>
 +
 +
 +
:* Agora aplicamos o estilo ao DialogFragment creado por nos:
 +
::'''Na Activity:'''
 +
::<syntaxhighlight lang="xml" line enclose="div" highlight="2" >
 +
                DialogoAltaEmpresa dialogoAltaEmpresa = new DialogoAltaEmpresa();
 +
                dialogoAltaEmpresa.setStyle(DialogFragment.STYLE_NORMAL,R.style.CustomDialog);
 +
</syntaxhighlight>
  
  

Revisión del 16:49 5 nov 2019

Introdución

  • Un diálogo é unha ventá pequena que lle pregunta ao usuario para tomar unha decisión, para informalo, ou para que o usuario introduza información.
  • Non cubre toda a pantalla
  • É usado para que o usuario tome algún tipo de acción antes de seguir coa aplicación.


00 dialogs w title.png

  • Hai catro tipos de ventás de diálogo:
    • AlertDialog: pode conter de cero a tres botóns, unha lista, RadioButtons, CheckBoxes, etc.
    • ProgressDialog: amosa unha barra de progreso. Herda de da clase AlertDialog. Verase na Unidade 5.
    • DatePickerDialog: este diálogo é para seleccionar unha fecha.
    • TimePickerDialog: este diálogo permite seleccionar unha hora.


  • O ProgressDialog está deprecated dende a API 26, isto quere dicir que nun futuro deixará de poder utilizarse dita clase.
PDM Dialogos 5.JPG
Como alternativas podemos empregar:
Veremos na UNIDADE 7: Threads e AsyncTask un exemplo de uso deste tipo de Dialog.
  • No caso de que teñades na vosa práctica que escoller un campo data ou un campo hora, deberedes facer uso do Dialogs comentados anteriormente.



  • Neste unidade imos centrarnos nos AlertDialog
    • Un diálogo baseado na clase AlertDialog ten 3 rexións:

00 dialogs regions.png


  • 1.-Título: é opcional.
  • 2.-Área de contido:pode amosar unha mensaxe, lista, un layout personalizado, etc.
  • 3.-Botóns de acción: Non debe haber máis de tres botóns.
  • Hai tres tipos de botóns:
    • Positivo: usarase para aceptar ou continuar unha acción.
    • Negativo: usarase cando se desexe cancelar unha acción.
    • Neutral: usarase cando non se sabe que facer coa acción.



  • Anteriormente a API 13, para amosar un diálogo chamábase ao método showDialog() indicando un parámetro enteiro, único na actividade.
Actualmente el uso dese método está deprecated.
Como alternativa se pode facer uso dos DialogFragment que fai engadido na versión API 22
PDM Dialogos 6.JPG
Esta forma de crear un diálogo tamén está deprecated dende a versión API 28, Android P
Polo tanto Android recomenda facer uso da biblioteca de compatibilidade com.android.support:support-v4:27.0.0 tanto para dar soporte a dispositivos anteriores a API 22 como os dispositivos posteriores a API 28.
Nota: Deberedes cambiar o número 27.0.0 pola versión compileSdkVersion do arquivo build.gradle.
Lembra que xa vimos como engadir unha biblioteca de compatibilidade nesta wiki




Dialogs anteriores a API 13

Nota: Opción deprecated. Utilizar DialogFragments (seguinte sección)
Se non o temos creado antes, crearemos un novo paquete de nome: Dialogs como un subpaquete do teu paquete principal.



  • Dentro do paquete Dialogs crear unha nova 'Empty Activity' de nome: UD03_01_Dialogs de tipo Launcher e sen compatibilidade.
Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.




  • As seguintes imaxes amosan o funcionamento da aplicación.
  • Todos os elementos dos diálogos teñen asociado un Toast como acción, aínda que só se amose na última imaxe da seguinte secuencia.



O XML do Layout

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:app="http://schemas.android.com/apk/res-auto"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     tools:context=".Dialogs.UD03_01_Dialogs">
 8 
 9     <TextView
10         android:id="@+id/tvTexto_UD03_01_Dialogs"
11         android:layout_width="wrap_content"
12         android:layout_height="wrap_content"
13         android:layout_marginStart="8dp"
14         android:layout_marginTop="8dp"
15         android:text="Preme nos botóns (ten scroll). Ventás de diálogo."
16         android:textSize="18sp"
17         app:layout_constraintStart_toStartOf="parent"
18         app:layout_constraintTop_toTopOf="parent" />
19 
20     <ScrollView
21         android:layout_width="0dp"
22         android:layout_height="240dp"
23         android:layout_marginStart="8dp"
24         android:layout_marginTop="28dp"
25         android:layout_marginEnd="8dp"
26         app:layout_constraintEnd_toEndOf="parent"
27         app:layout_constraintHorizontal_bias="1.0"
28         app:layout_constraintStart_toStartOf="parent"
29         app:layout_constraintTop_toBottomOf="@+id/tvTexto_UD03_01_Dialogs">
30 
31         <LinearLayout
32             android:id="@+id/linearLayout"
33             android:layout_width="match_parent"
34             android:layout_height="wrap_content"
35             android:orientation="vertical">
36 
37             <Button
38                 android:id="@+id/btnDlgMensaxe_UD03_01_Dialogs"
39                 android:layout_width="match_parent"
40                 android:layout_height="wrap_content"
41                 android:text="Ventá de diálogo con mensaxe" />
42 
43             <Button
44                 android:id="@+id/btnDlgBotons_UD03_01_Dialogs"
45                 android:layout_width="match_parent"
46                 android:layout_height="wrap_content"
47                 android:layout_marginTop="5dp"
48                 android:text="Ventá de diálogo con 3 botóns" />
49 
50             <Button
51                 android:id="@+id/btnDlgLista_UD03_01_Dialogs"
52                 android:layout_width="match_parent"
53                 android:layout_height="wrap_content"
54                 android:layout_marginTop="5dp"
55                 android:text="V.de diálogo con lista de selección " />
56 
57             <Button
58                 android:id="@+id/btnDlgUnicaSel_UD03_01_Dialogs"
59                 android:layout_width="match_parent"
60                 android:layout_height="wrap_content"
61                 android:layout_marginTop="5dp"
62                 android:text="V.de diálogo cunha única selección " />
63 
64             <Button
65                 android:id="@+id/btnDlgMulSelec_UD03_01_Dialogs"
66                 android:layout_width="match_parent"
67                 android:layout_height="wrap_content"
68                 android:layout_marginTop="5dp"
69                 android:text="V.de diálogo  con selección múltiple" />
70 
71             <Button
72                 android:id="@+id/btnDlgEntrada_UD03_01_Dialogs"
73                 android:layout_width="match_parent"
74                 android:layout_height="wrap_content"
75                 android:layout_marginTop="5dp"
76                 android:text="V.de diálogo con entrada de texto" />
77         </LinearLayout>
78     </ScrollView>
79 
80 </android.support.constraint.ConstraintLayout>



Definición de recursos tipo array en XML

  • Aproveitamos o ficheiro /res/values/strings.xml e definimos dous recursos de tipo Array, para a lista de selección e para a selección múltiple.


 1 <?xml version="1.0" encoding="utf-8"?>
 2 <resources>
 3     <string name="app_name">Aprendiendo</string>
 4 
 5 
 6     <string-array name="array_elem_seleccion1_ud03_01_dialogs">
 7         <item>Opción un</item>
 8         <item>Opción dous</item>
 9         <item>Opción tres</item>
10         <item>Opción catro</item>
11     </string-array>
12 
13     <string-array name="array_elem_seleccion2_ud03_01_dialogs">
14         <item>Coche</item>
15         <item>Moto</item>
16         <item>Bici</item>
17         <item>Metro</item>
18         <item>Tren</item>
19         <item>Autobús</item>
20         <item>Andando</item>
21     </string-array>
22 
23 
24 </resources>



Definición do recurso de tipo Layout usado polo diálogo con entrada de texto (o último)

Explicado posteriormente.

  • Ficheiro /res/layout/dlg_entrada_texto_ud03_01_dialogs.xml
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:app="http://schemas.android.com/apk/res-auto"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:theme="@android:style/Theme.Holo.Dialog">
 8 
 9     <EditText
10         android:id="@+id/etPass_Dlg_UD03_01_Dialogs"
11         android:layout_width="0dp"
12         android:layout_height="wrap_content"
13         android:layout_marginEnd="8dp"
14         android:inputType="textPassword"
15         android:contentDescription="Introduce o password"
16         android:textColor="@android:color/holo_blue_dark"
17         app:layout_constraintEnd_toEndOf="parent"
18         app:layout_constraintStart_toStartOf="@+id/guideline"
19         app:layout_constraintTop_toBottomOf="@+id/etNome_Dlg_UD03_01_Dialogs" />
20 
21     <TextView
22         android:id="@+id/tvNome_Dlg_UD03_01_Dialogs2"
23         android:layout_width="wrap_content"
24         android:layout_height="wrap_content"
25         android:layout_marginStart="8dp"
26         android:layout_marginTop="20dp"
27         android:text="Contrasinal:"
28         android:textSize="18sp"
29         app:layout_constraintStart_toStartOf="parent"
30         app:layout_constraintTop_toBottomOf="@+id/tvPass_Dlg_UD03_01_Dialogs" />
31 
32     <TextView
33         android:id="@+id/tvPass_Dlg_UD03_01_Dialogs"
34         android:layout_width="wrap_content"
35         android:layout_height="wrap_content"
36         android:layout_marginStart="8dp"
37         android:layout_marginTop="8dp"
38         android:text="Nome:"
39         android:textSize="18sp"
40         app:layout_constraintStart_toStartOf="parent"
41         app:layout_constraintTop_toTopOf="parent" />
42 
43     <android.support.constraint.Guideline
44         android:id="@+id/guideline"
45         android:layout_width="wrap_content"
46         android:layout_height="wrap_content"
47         android:orientation="vertical"
48         app:layout_constraintGuide_begin="103dp" />
49 
50     <EditText
51         android:id="@+id/etNome_Dlg_UD03_01_Dialogs"
52         android:layout_width="0dp"
53         android:layout_height="wrap_content"
54         android:layout_marginEnd="8dp"
55         android:focusedByDefault="true"
56         android:contentDescription="Introduce o nome"
57         android:textColor="@android:color/holo_blue_dark"
58         app:layout_constraintEnd_toEndOf="parent"
59         app:layout_constraintStart_toStartOf="@+id/guideline"
60         app:layout_constraintTop_toTopOf="parent" />
61 </android.support.constraint.ConstraintLayout>



Código Java

  1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Dialogs;
  2 
  3 import android.app.Activity;
  4 import android.app.AlertDialog;
  5 import android.app.Dialog;
  6 import android.content.Context;
  7 import android.content.DialogInterface;
  8 import android.content.res.Resources;
  9 import android.os.Bundle;
 10 import android.view.LayoutInflater;
 11 import android.view.View;
 12 import android.widget.TextView;
 13 import android.widget.Toast;
 14 
 15 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
 16 
 17 public class UD03_01_Dialogs extends Activity implements View.OnClickListener {
 18     private static final int DIALOGO_MENSAXE = 1;
 19     private static final int DIALOGO_TRES_BOTONS = 2;
 20     private static final int DIALOGO_LISTA = 3;
 21     private static final int DIALOGO_RADIO_BUTTON = 4;
 22     private static final int DIALOGO_CHECK_BOX = 5;
 23     private static final int DIALOGO_ENTRADA_TEXTO = 6;
 24 
 25     // Atributo para crear as ventás de diálogo
 26     private AlertDialog.Builder venta;
 27 
 28     protected Dialog onCreateDialog(int id) {
 29         switch (id) {
 30 
 31             case DIALOGO_MENSAXE:
 32                 venta = new AlertDialog.Builder(this);
 33                 venta.setTitle("Atención");
 34                 venta.setMessage("Nova amensaxe. Preme o botón 'Back' para volver á pantalla principal");
 35                 venta.setIcon(android.R.drawable.ic_dialog_email);
 36                 return venta.create();
 37 
 38 
 39 
 40             case DIALOGO_TRES_BOTONS:
 41                 venta = new AlertDialog.Builder(this);
 42                 venta.setIcon(android.R.drawable.ic_dialog_info);
 43                 venta.setTitle("Enquisa");
 44                 venta.setMessage("Compras sempre en grandes superficies?");
 45                 venta.setCancelable(false);
 46                 venta.setPositiveButton("Si", new DialogInterface.OnClickListener() {
 47                     public void onClick(DialogInterface dialog, int boton) {
 48                         /* Sentencias se o usuario preme Si */
 49                         Toast.makeText(getApplicationContext(), "Premeches 'Si'", 1).show();
 50                     }
 51                 });
 52                 venta.setNegativeButton("Non", new DialogInterface.OnClickListener() {
 53                     public void onClick(DialogInterface dialog, int boton) {
 54                         /* Sentencias se o usuario preme Non */
 55                         Toast.makeText(getApplicationContext(), "Premeches'Non'", 1).show();
 56                     }
 57                 });
 58                 venta.setNeutralButton("Ás veces", new DialogInterface.OnClickListener() {
 59                     public void onClick(DialogInterface dialog, int boton) {
 60                         /* Sentencias se o usuario preme Ás veces */
 61                         Toast.makeText(getApplicationContext(), "Premeches 'Ás veces'", 1).show();
 62                     }
 63                 });
 64                 return venta.create();
 65 
 66 
 67 
 68             case DIALOGO_LISTA:
 69                 venta = new AlertDialog.Builder(this);
 70                 venta.setIcon(android.R.drawable.ic_dialog_alert);
 71                 venta.setTitle("Escolle unha opción");
 72                 venta.setItems(R.array.array_elem_seleccion1_ud03_01_dialogs, new DialogInterface.OnClickListener() {
 73                     public void onClick(DialogInterface dialog, int posicion) {
 74                         // O usuario selecciona unha das opcións do listado
 75                         String[] opcions = getResources().getStringArray(R.array.array_elem_seleccion1_ud03_01_dialogs);
 76                         Toast.makeText(getApplicationContext(), "Seleccionaches: '" + opcions[posicion] + "'", Toast.LENGTH_LONG).show();
 77                     }
 78                 });
 79                 return venta.create();
 80 
 81 
 82 
 83             case DIALOGO_RADIO_BUTTON:
 84                 venta = new AlertDialog.Builder(this);
 85                 venta.setIcon(android.R.drawable.ic_dialog_info);
 86                 venta.setTitle("Selecciona un smartpohone");
 87                 // Non incluír mensaxe dentro de este tipo de diálogo!!!
 88                 final CharSequence[] smartphones = { "iPhone", "Blackberry", "Android" };
 89                 venta.setSingleChoiceItems(smartphones, 0, new DialogInterface.OnClickListener() {
 90                     public void onClick(DialogInterface dialog, int opcion) {
 91                         // Evento que ocorre cando o usuario selecciona una opción
 92                         Toast.makeText(getApplicationContext(), "Seleccionaches: " + smartphones[opcion], Toast.LENGTH_SHORT).show();
 93                     }
 94                 });
 95                 venta.setPositiveButton("Aceptar", new DialogInterface.OnClickListener() {
 96                     public void onClick(DialogInterface dialog, int boton) {
 97                         Toast.makeText(getApplicationContext(), "Premeches 'Aceptar'", 1).show();
 98                     }
 99                 });
100                 venta.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
101                     public void onClick(DialogInterface dialog, int boton) {
102                         Toast.makeText(getApplicationContext(), "Premeches 'Cancelar'", 1).show();
103                     }
104                 });
105                 return venta.create();
106 
107 
108 
109             case DIALOGO_CHECK_BOX:
110                 venta = new AlertDialog.Builder(this);
111                 venta.setIcon(android.R.drawable.ic_dialog_info);
112                 venta.setTitle("Selecciona modos de transporte");
113                 Resources res = getResources();
114                 final String[] matriz = res.getStringArray(R.array.array_elem_seleccion2_ud03_01_dialogs);
115                 // Non incluír mensaxe dentro de este tipo de diálogo!!!
116                 venta.setMultiChoiceItems(matriz, new boolean[] { false, true, false, true, false, false, false }, new DialogInterface.OnMultiChoiceClickListener() {
117                     public void onClick(DialogInterface dialog, int opcion, boolean isChecked) {
118                         // Evento que ocorre cando o usuario selecciona unha opción
119                         if (isChecked)
120                             Toast.makeText(getApplicationContext(), "Seleccionaches " + matriz[opcion], Toast.LENGTH_SHORT).show();
121                         else
122                             Toast.makeText(getApplicationContext(), "Deseleccionaches " + matriz[opcion], Toast.LENGTH_SHORT).show();
123                     }
124                 });
125                 venta.setPositiveButton("Aceptar", new DialogInterface.OnClickListener() {
126                     public void onClick(DialogInterface dialog, int boton) {
127                         Toast.makeText(getApplicationContext(), "Premeches 'Aceptar'", Toast.LENGTH_LONG).show();
128                     }
129                 });
130                 venta.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
131                     public void onClick(DialogInterface dialog, int boton) {
132                         Toast.makeText(getApplicationContext(), "Premeches 'Cancelar'", Toast.LENGTH_LONG).show();
133                     }
134                 });
135                 return venta.create();
136 
137 
138 
139             case DIALOGO_ENTRADA_TEXTO:
140                 // Primeiro preparamos o interior da ventá de diálogo inflando o seu
141                 // fichero XML
142                 String infService = Context.LAYOUT_INFLATER_SERVICE;
143                 LayoutInflater li = (LayoutInflater) getApplicationContext().getSystemService(infService);
144                 // Inflamos o compoñente composto definido no XML
145                 View inflador = li.inflate(R.layout.dlg_entrada_texto_ud03_01_dialogs, null);
146                 // Buscamos os compoñentes dentro do Diálogo
147                 final TextView etNome = (TextView) inflador.findViewById(R.id.etNome_Dlg_UD03_01_Dialogs);
148                 final TextView etContrasinal = (TextView) inflador.findViewById(R.id.etPass_Dlg_UD03_01_Dialogs);
149 
150                 venta = new AlertDialog.Builder(this);
151                 venta.setTitle("Indica usuario e contrasinal");
152                 // Asignamos o contido dentro do diálogo (o que inflamos antes)
153                 venta.setView(inflador);
154                 // Non se pode incluír unha mensaxe dentro deste tipo de diálogo!!!
155                 venta.setPositiveButton("Aceptar", new DialogInterface.OnClickListener() {
156                     public void onClick(DialogInterface dialog, int boton) {
157                         Toast.makeText(getApplicationContext(), "Escribiches nome: '" + etNome.getText().toString() + "'. Contrasinal: '" + etContrasinal.getText().toString() + "' e premeches 'Aceptar'",
158                                 Toast.LENGTH_LONG).show();
159                     }
160                 });
161                 venta.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
162                     public void onClick(DialogInterface dialog, int boton) {
163                         Toast.makeText(getApplicationContext(), "Premeches en 'Cancelar'", Toast.LENGTH_LONG).show();
164                     }
165                 });
166                 return venta.create();
167 
168         }
169         return null;
170     }
171 
172 
173     private void xestioarEventos(){
174 
175         findViewById(R.id.btnDlgBotons_UD03_01_Dialogs).setOnClickListener(this);
176         findViewById(R.id.btnDlgEntrada_UD03_01_Dialogs).setOnClickListener(this);
177         findViewById(R.id.btnDlgLista_UD03_01_Dialogs).setOnClickListener(this);
178         findViewById(R.id.btnDlgMensaxe_UD03_01_Dialogs).setOnClickListener(this);
179         findViewById(R.id.btnDlgMulSelec_UD03_01_Dialogs).setOnClickListener(this);
180         findViewById(R.id.btnDlgUnicaSel_UD03_01_Dialogs).setOnClickListener(this);
181     }
182 
183 
184     @Override
185     protected void onCreate(Bundle savedInstanceState) {
186         super.onCreate(savedInstanceState);
187         setContentView(R.layout.activity_ud03_01__dialogs);
188 
189         xestioarEventos();
190     }
191 
192     // A interface está implementada na Activity
193     @Override
194     public void onClick(View v) {
195         switch (v.getId()) {
196             case R.id.btnDlgMensaxe_UD03_01_Dialogs:
197                 showDialog(DIALOGO_MENSAXE);
198                 break;
199 
200             case R.id.btnDlgBotons_UD03_01_Dialogs:
201                 showDialog(DIALOGO_TRES_BOTONS);
202 
203                 break;
204 
205             case R.id.btnDlgLista_UD03_01_Dialogs:
206                 showDialog(DIALOGO_LISTA);
207 
208                 break;
209 
210             case R.id.btnDlgUnicaSel_UD03_01_Dialogs:
211                 showDialog(DIALOGO_RADIO_BUTTON);
212 
213                 break;
214 
215             case R.id.btnDlgMulSelec_UD03_01_Dialogs:
216                 showDialog(DIALOGO_CHECK_BOX);
217 
218                 break;
219 
220             case R.id.btnDlgEntrada_UD03_01_Dialogs:
221                 showDialog(DIALOGO_ENTRADA_TEXTO);
222 
223                 break;
224 
225             default:
226                 break;
227         }
228 
229     }
230 }
  • Liñas 17: Para a xestión dos eventos de click sobre os botóns implementamos a interface a nivel de Activity.
  • Liñas 18-23: Creamos constantes enteiras para cada tipo de dialogo que queremos crear.
  • Liñas 26: Esta propiedade vai servir para 'crear' os diferentes tipos de Dialogs.
  • Liñas 28-170: En función do código que lle chega (o código ven enviado dende as liñas 195-223) creamos os diferentes tipos de Dialogs.
  • Liñas 189: Rexistramos os eventos de click en cada botón.
  • Liñas 195-223: En función do botón premido mandamos crear un tipo de diálogo diferente enviando un código que o identifica (inventado por nos)


  • Métodos máis comúns para todos os tipos de diálogos:
    • setTitle(): establece o título da ventá de diálogo.
    • setMessage(): pon a mensaxe na área de contido da ventá de diálogo.
    • setIcon():establece a propiedade Icon cunha das imaxes predefinidas.


  • No caso dos cadros de diálogo que teñan botóns:
    • Indicamos para cada tipo de botón o Texto que debe ver o usuario
    • Indicamos a acción a realizar se se preme. Neste caso chámase ao Listener de DialogInterface asociado ao evento Click.


  • No método onBotonClick(View view) achamos que botón foi o que se pulsou e en función diso chamamos ao método showDialog() pasándolle a constante enteira asociada ao diálogo que queremos crear.
  • No método onCreateDialog() temos asociado un diálogo para cada unha das constantes enteiras. O método recibe o enteiro e crear o diálogo asociado a ese número enteiro.
  • Para cada novo diálogo crease un obxecto venta co construtor AlertDialog.Builder()

Ventás de diálogo personalizadas

  • O último diálogo (Liñas 139-172) ten asociado un Layout XML. Ficheiro /res/layout/dlg_entrada_texto_ud03_01_dialogs.xml (xa posto anteriormente).
  • Para visualizalo, no canto de utilizar setMessage() usamos o método setView() (liña 154 do código da activity) para amosar na área de contido do diálogo o XML inflado;
  • Ese ficheiro XML hai que instancialo nas súas correspondentes Vistas.
  • Ese proceso coñecese co nome de Inflar e é necesario facelo para poder visualizar o recurso xml.
  • Podemos ver como é dito proceso no código:
1      case DIALOGO_ENTRADA_TEXTO:
2          // Primeiro preparamos o interior da ventá de diálogo inflando o seu
3          // fichero XML
4          String infService = Context.LAYOUT_INFLATER_SERVICE;
5          LayoutInflater li = (LayoutInflater) getApplicationContext().getSystemService(infService);
6          // Inflamos o compoñente composto definido no XML
7          View inflador = li.inflate(R.layout.dlg_entrada_texto_ud03_01_dialogs, null);
8          ............
9          venta.setView(inflador);

Neste caso estamos a facer un 'inflate' explícito, pero aínda que non vos dades conta, tamén se fai un 'inflate' cando chamamos o método setContentView dentro do onCreate da activity. Lembrar que o que pasamos como dato nesa chamada é o layout que vai visualizar a activity. Isto se coñece como 'inflate' implícito e o fai o S.O. automaticamente.

  • Para nos (aínda que non sexa exactamente iso) o 'inflado' serve para pasar dun recurso de texto xml a un obxecto (View) onde se atopan todos os elementos gráficos que están definidos no arquivo xml. É importante sinalar que cando queiramos acceder a un compoñente do diálogo (por exemplo, no xogo das preguntas, cando engadimos unha pregunta nova aparece un diálogo deste tipo. Ao dar de alta a pregunta leva consigo acceder as caixas de texto) o temos que facer a través do view que obtemos do 'inflado'. Se isto o facemos dende dentro dunha clase anónima, teremos que definir o View como final.
    No exemplo, o que se define como final é o campo de texto (liñas 148 e 149), pero poderíamos definir como final o View da forma:


 1                 case DIALOGO_ENTRADA_TEXTO:
 2                         // Primeiro preparamos o interior da ventá de diálogo inflando o seu
 3                         // fichero XML
 4                         String infService = Context.LAYOUT_INFLATER_SERVICE;
 5                         LayoutInflater li = (LayoutInflater) getApplicationContext().getSystemService(infService);
 6                         // Inflamos o compoñente composto definido no XML
 7                         final View inflador = li.inflate(R.layout.dialogo_entrada_texto, null);
 8  
 9                         venta = new AlertDialog.Builder(this);
10                         venta.setTitle("Indica usuario e contrasinal");
11                         // Asignamos o contido dentro do diálogo (o que inflamos antes)
12                         venta.setView(inflador);
13                         // Non se pode incluír unha mensaxe dentro deste tipo de diálogo!!!
14                         venta.setPositiveButton("Aceptar", new DialogInterface.OnClickListener() {
15                                 public void onClick(DialogInterface dialog, int boton) {
16                                         // Buscamos os compoñentes dentro do Diálogo
17                                     	TextView etNome = (TextView) inflador.findViewById(R.id.etNome_Dlg_UD03_01_Dialogs);
18                                     	TextView etContrasinal = (TextView) inflador.findViewById(R.id.etPass_Dlg_UD03_01_Dialogs);
19                                     	
20                                         Toast.makeText(getApplicationContext(), "Escribiches nome: '" + etNome.getText().toString() + "'. Contrasinal: '" + etContrasinal.getText().toString() + "' e premeches 'Aceptar'",
21                                                         1).show();
22                                 }
23                         });
  • No inflate o segundo parámetro:
View inflador = li.inflate(R.layout.dialogo_entrada_texto, null);)

normalmente ponse null, pero podemos poñer un view que queiramos que sexa 'pai' do view que se xera a partires do arquivo de recursos xml.




Dialogs posteriores a API 13.DialogFragment (opción actual)

A partires da API 13 (Android 3.2) a forma de 'construír' os diálogos modificouse.

Se se usa a forma anteriormente explicada funcionará pero marcará no Compilador a liña como deprecated.

Android 2014 U3 15 Dialogos 1.JPG

Imos ver neste punto como poderíamos facer para construír os diálogos doutra forma.

Para explicalo teremos que falar antes dos DialogFragment e por extensión dos Fragment.

Información adicional:

Un fragment representa un 'trozo' da interface dun usuario. A idea dos fragment xurdiu polas dificultades que tiñan as aplicacións a adaptarse a tamaños grandes de pantalla (como as tablet´s).

Android 2014 U3 15 Dialogos 2.JPG
Imaxe obtida de [1]

Imaxinade que tedes unha aplicación que amosa unha lista de usuarios e que ó premer sobre un deles apareceran os seus datos completos.

Isto feito nun móbil cunha pantalla de 4 polgadas levaría consigo a creación de dúas activities, xa que na mesma non cabe toda a información (necesitaríamos usar scroll, bastante incómodo).

Esta mesma aplicación levada a unha tablet de 10 polgadas non tería problema en visualizar todo na mesma pantalla.

Os fragment vannos permitir dividir os elementos gráficos en 'anacos' que imos poder usar de forma independente nas activities. Así, no caso anterior podemos crear dous fragment, un coa lista e outro có detalle de cada usuario.

Agora dependendo do tamaño da pantalla podo facer que na pantalla pequena se amose un só fragment (a lista) é que o premer sobre un elemento da mesma apareza o outro fragment (o detalle).
Se o tamaño é grande (tablet) podo facer que aparezan os dous fragment na mesma activity.

O código que xestiona a pulsación dun elemento da lista e amosar os datos estará definido nun só sitio, o que modificamos é o sitio onde se visualiza o fragment en función do tamaño da pantalla.

Tendo claro o concepto de Fragment isto lévanos ao seguinte concepto: DialogFragment.



Creando os Dialogs

  • Imos facer a mesma práctica que no 'Caso pràctico 1' pero adaptándoa para non utilizar formas de chamar/crear a Dialogs 'deprecated'.
Se non o temos creado antes, crearemos un novo paquete de nome: Dialogs como un subpaquete do teu paquete principal.



  • Dentro do paquete Dialogs crear unha nova 'Empty Activity' de nome: UD03_02_Dialogs de tipo Launcher e sen compatibilidade.
Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.



  • Podemos facer uso de diferentes tipos de Dialogs:
  • Dialog cunha mensaxe
  • Dialog cunha mensaxe e un, dous botóns ou tres botóns.
  • Dialog cunha lista de selección na que aparece unha lista de opcións e escollemos unha.
  • Dialog cunha lista de selección na que aparece unha lista de opcións e escollemos unha pero graficamente diferenciase da anterior en que empregamos radiobuttons.
  • Dialog cunha lista de selección na que aparece unha lista de opcións e podemos escoller moitas (aparecen checkboxes)
  • Dialog definido por nos, no que teremos un layout e todos os controis que queiramos poñer.


O proceso de uso será o seguinte:
  • Crear un obxecto da clase anterior imos definir que botóns, texto,...vai ter (dentro das posibilidades que nos permita).
  • Chamar ao método create() da clase AlertDialog.Builder o cal devolverá un obxecto da clase AlertDialog.
  • Chamar ao método show() da clase AlertDialog.Builder o cal amosa o diálogo creado.


  • NOTA IMPORTANTE:
  • Se estamos a empregar unha Activity que deriva de AppCompactActivity debemos facer a importación do paquete: import android.support.v7.app.AlertDialog;
  • Se estamos a empregar unha Activity que deriva de Activity, debemos empregar o paquete: import android.app.AlertDialog;





O layout da activity

  • O layout é o mesmo que no caso práctico 1 polo que o cargaremos dende o método onCreate()
Nota: Teredes que crear o layout da activity UD03_01_Dialogs, que ten de nome:activity_ud03_01__dialogs, pero so o layout, non tedes por que facer a práctica enteira.
1     @Override
2     protected void onCreate(Bundle savedInstanceState) {
3         super.onCreate(savedInstanceState);
4         setContentView(R.layout.activity_ud03_01__dialogs);     // Poñemos o mesmo layout que na activity UD03_01_Dialogs
5 
6     }



O código da Activity

  • Primeiro imos rexistrar os eventos de click dos diferentes botóns, implementando a interface OnClickListener a nivel de Activity:
 1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Dialogs;
 2 
 3 import android.app.Activity;
 4 import android.content.DialogInterface;
 5 import android.os.Bundle;
 6 import android.app.AlertDialog;
 7 import android.view.View;
 8 import android.widget.Toast;
 9 
10 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
11 
12 public class UD03_02_Dialogs extends Activity implements View.OnClickListener {
13 
14     private void xestioarEventos(){
15 
16         findViewById(R.id.btnDlgBotons_UD03_01_Dialogs).setOnClickListener(this);
17         findViewById(R.id.btnDlgEntrada_UD03_01_Dialogs).setOnClickListener(this);
18         findViewById(R.id.btnDlgLista_UD03_01_Dialogs).setOnClickListener(this);
19         findViewById(R.id.btnDlgMensaxe_UD03_01_Dialogs).setOnClickListener(this);
20         findViewById(R.id.btnDlgMulSelec_UD03_01_Dialogs).setOnClickListener(this);
21         findViewById(R.id.btnDlgUnicaSel_UD03_01_Dialogs).setOnClickListener(this);
22     }
23 
24     @Override
25     protected void onCreate(Bundle savedInstanceState) {
26         super.onCreate(savedInstanceState);
27         setContentView(R.layout.activity_ud03_01__dialogs);     // Poñemos o mesmo layout que na activity UD03_01_Dialogs
28 
29         xestioarEventos();
30     }
31 
32     @Override
33     public void onClick(View v) {
34 
35         switch (v.getId()) {
36             case R.id.btnDlgMensaxe_UD03_01_Dialogs:
37 
38                 break;
39 
40             case R.id.btnDlgBotons_UD03_01_Dialogs:
41 
42                 break;
43 
44             case R.id.btnDlgLista_UD03_01_Dialogs:
45 
46                 break;
47 
48             case R.id.btnDlgUnicaSel_UD03_01_Dialogs:
49 
50                 break;
51 
52             case R.id.btnDlgMulSelec_UD03_01_Dialogs:
53 
54                 break;
55 
56             case R.id.btnDlgEntrada_UD03_01_Dialogs:
57 
58                 break;
59 
60             default:
61                 break;
62         }
63 
64 
65     }
66 }



Diálogo con mensaxe
PDM Dialogos 12.jpg
  • Teremos que engadir o seguinte código ao método onClick():
 1     @Override
 2     public void onClick(View v) {
 3         AlertDialog.Builder builder=null;   // Nos eventos de botón sempre imos 'construir' un Dialog
 4 
 5         switch (v.getId()) {
 6             case R.id.btnDlgMensaxe_UD03_01_Dialogs:
 7                 builder = new AlertDialog.Builder(this);
 8                 builder.setTitle("Atención");
 9                 builder.setMessage("Nova amensaxe. Preme o botón 'Back' para volver á pantalla principal");
10                 builder.setIcon(android.R.drawable.ic_dialog_email);
11                 builder.create();   // Devolve un Dialog, pero non o necesitamos polo de agora.
12                 builder.show();
13 
14                 break;
  • Liña 3: Para non ter que definir un obxecto da clase AlertDialog.Builder en cada caso do swith o definimos fora.
  • Liña 7: Instanciamos o obxecto.
  • Liña 8-10: Establecemos un título, a mensaxe e unha icona. Non son obrigatorios poñelos pero si aconsellable.
  • Liña 11: Chamamos ao método create() para que cre o Dialog.
  • Liña 12: Chamamos ao método show() para que amose o Dialog.


  • O código anterior tamén poderíamos escribilo así:
1                 builder = new AlertDialog.Builder(this)
2                     .setTitle("Atención")
3                     .setMessage("Nova amensaxe. Preme o botón 'Back' para volver á pantalla principal")
4                     .setIcon(android.R.drawable.ic_dialog_email);
5                 builder.create();   // Devolve un Dialog, pero non o necesitamos polo de agora.
6                 builder.show();
Fixarse que a liña do new non leva punto e coma, nen as seguintes ata a de setIcon.



Diálogo con botóns
PDM Dialogos 14.jpg


  • Como dixemos anteriormente podemos engadir ata 3 botóns e darlle a funcionalidade que queiramos. Normalmente teremos as opcións Aceptar/Cancelar.
A diferenza de xestionar o Click dos botóns vistos ata o de agora e que a interface que rexistra o evento é DialogInterface.OnClickListener.
A xestión de ditos botóns se fai con interface anónimas no mesmo sitio onde creamos o Dialog ou ven podemos facer como nos botóns e implementar a interface DialogInterface.OnClickListener a nivel de Activiry.
Ao igual que no resto de opcións non é obrigatorio poñer os tres botóns como no seguinte exemplo.


  • Engadimos o seguinte código ao método OnClick():
 1             case R.id.btnDlgBotons_UD03_01_Dialogs:
 2                         builder = new AlertDialog.Builder(this)
 3                         .setTitle("Caixa de diálogo").setIcon(R.drawable.ic_launcher)
 4                         .setMessage("QUE TE PARACE ESTE DIALOGO ?")
 5 
 6                         .setPositiveButton("Ben", new DialogInterface.OnClickListener() {
 7                             @Override
 8                             public void onClick(DialogInterface dialog, int which) {
 9                                 Toast.makeText(getApplicationContext(), "PULSADA OPCION BOA",Toast.LENGTH_LONG).show();
10                             }
11                         })
12 
13                         .setNegativeButton("MAL", new DialogInterface.OnClickListener() {
14                             @Override
15                             public void onClick(DialogInterface dialog, int which) {
16 
17                                 Toast.makeText(getApplicationContext(),"PULSADA OPCION MALA", Toast.LENGTH_LONG).show();
18                             }
19                         })
20 
21                         .setNeutralButton("NON SEI", new DialogInterface.OnClickListener() {
22                             @Override
23                             public void onClick(DialogInterface dialog, int which) {
24 
25                                 Toast.makeText(getApplicationContext(),"PULSADA OPCION NON SEI", Toast.LENGTH_LONG).show();
26                             }
27                         });
28 
29                 builder.create();
30                 builder.show();
31 
32                 break;


  • Como vemos o evento de click é moi parecido ao feito cos botóns.
Neste caso estamos implementando Interface Anónimas. Neste caso lembrar que 'this' fai referencia ao Dialog, non a Activity polo que se necesitades ter unha referencia ao Context podemos utilizar o método getApplicationContext().
Se necesitades acceder a algo da Activity dentro da interface, podemos facer como no caso dos botóns. Declarar a obxecto como final fora da forma:
 1             case R.id.btnDlgBotons_UD03_01_Dialogs:
 2                 final Button btnOpcion = findViewById(R.id.btnDlgBotons_UD03_01_Dialogs);
 3 
 4                 builder = new AlertDialog.Builder(this)
 5                 .setTitle("Caixa de diálogo").setIcon(R.drawable.ic_launcher)
 6                 .setMessage("QUE TE PARACE ESTE DIALOGO ?")
 7 
 8                 .setPositiveButton("Ben", new DialogInterface.OnClickListener() {
 9                     @Override
10                     public void onClick(DialogInterface dialog, int which) {
11                         Toast.makeText(getApplicationContext(), "PULSADA OPCION BOA",Toast.LENGTH_LONG).show();
12                         btnOpcion.setText(btnOpcion.getText().toString().concat("-OK"));
13                     }
14                 })
15                 .setNegativeButton("MAL", new DialogInterface.OnClickListener() {
16                     @Override
17                     public void onClick(DialogInterface dialog, int which) {
18                         //
19 
20                         Toast.makeText(getApplicationContext(),"PULSADA OPCION MALA", Toast.LENGTH_LONG).show();
21                     }
22                 })
23                 .setNeutralButton("NON SEI", new DialogInterface.OnClickListener() {
24                     @Override
25                     public void onClick(DialogInterface dialog, int which) {
26 
27                         Toast.makeText(getApplicationContext(),"PULSADA OPCION NON SEI", Toast.LENGTH_LONG).show();
28                     }
29                 });
30 
31                 builder.create();
32                 builder.show();
33 
34                 break;
  • Nesta imaxe podemos ver como o texto do botón se modifica cando se preme no botón 'Ben':
PDM Dialogos 24.jpg


  • No caso de implementar a Interface a nivel da Activity como xa vimos nesta Wiki, ao método onClick chegará como información o Diálog e o botón que foi premido. (ler nota ao final do exemplo)
  • No caso dos Dialog, se temos varios que van a mesma interface, teremos que telos definidos a nivel global, dentro da Activity da forma:
 1 public class UD03_02_Dialogs extends Activity implements View.OnClickListener, DialogInterface.OnClickListener {
 2 
 3     private Dialog dialog1,dialog2;
 4  
 5     ....
 6     @Override
 7     public void onClick(DialogInterface dialog, int which) {
 8         if (dialog==dialog1){
 9             if (which==DialogInterface.BUTTON_POSITIVE){
10 
11             }
12         }         
13     }
14 
15 
16     @Override
17     public void onClick(View v) {
18         AlertDialog.Builder builder=null;   // Nos eventos de botón sempre imos 'construir' un Dialog
19 
20         switch (v.getId()) {
21 
22             case R.id.btnDlgBotons_UD03_01_Dialogs:
23                 final Button btnOpcion = findViewById(R.id.btnDlgBotons_UD03_01_Dialogs);
24 
25                 builder = new AlertDialog.Builder(this)
26                 .setTitle("Caixa de diálogo").setIcon(R.drawable.ic_launcher)
27                 .setMessage("QUE TE PARACE ESTE DIALOGO ?")
28 
29                 .setPositiveButton("Ben", new DialogInterface.OnClickListener(this);
30 
31                 .setNegativeButton("MAL", new DialogInterface.OnClickListener(this);
32 
33                 dialog1 = builder.create();
34                 builder.show();
35 
36                 break;
Liña 1: Implementamos a interface DialogInterface.OnClickListener
Liña 3: Definimos os Dialog que imos a usar a nivel global para poder referencialos.
Liñas 6-13: Aquí xestionamos o evento OnClick de todos os botóns de todos os diálogos que rexistren o evento contra a interface da Activity.
Liña 33: Na liña 33 asociamos o diálogo creado para poder ter unha referencia ao mesmo fora do método.


Nota: Probado e parece que non funciona correctamente.
A referencia ao diálogo creado non se corresponde coa referencia recibida no método DialogInterface.onClick. Aparece un número identificativo decrementado sempre nunha unidade con respecto ao identificador do diálogo no DialogInterface.onClick.



  • Indicar que se queremos pechar o diálogo cando prememos uns dos botóns, o podemos facer chamando ao método dismiss do diálogo. A referencia ao diálogo a temos no método que implementa a interface de xestión de eventos do mesmo (aínda que neste caso xa non fai falla chamar a dismiss xa que se pecha ao premer o botón) ou tendo unha referencia a dito diálogo a través do método 'create'.
Cando vexamos os diálogos personalizados, podemos querer que cando se preme nunha imaxe do diálogo se peche. Nese caso teríamos que empregar este método.
1         builder.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
2             @Override
3             public void onClick(DialogInterface dialog, int which) {
4                 dialog.dismiss();
5             }
6         });




Diálogo Lista de Selección
PDM Dialogos 16.jpg


  • Neste tipo de diálogo van saír unha serie de opcións.
Neste exemplo imos obter esas opcións dun String-Array definido en /res/values, pero poderíamos empregar calquera fonte de datos, que gardaríamos nun array e o pasaríamos como parámetro.
Se xa fixeches a práctica 1 xa o tedes definido e non fai falla facelo.
Non podemos empregar o método setMessage() neste tipo de diálogo nin no seguinte.
  • Aproveitamos o ficheiro /res/values/strings.xml e definimos un recurso de tipo Array, para a lista de selección e para a selección múltiple.


 1 <?xml version="1.0" encoding="utf-8"?>
 2 <resources>
 3 <resources>
 4     <string name="app_name">Aprendiendo</string>
 5 
 6 
 7     <string-array name="array_elem_seleccion1_ud03_02_dialogs">
 8         <item>Opción un</item>
 9         <item>Opción dous</item>
10         <item>Opción tres</item>
11         <item>Opción catro</item>
12     </string-array>
13 
14 
15 </resources>



  • O código da Activity no método onClick(View v) quedaría así:
 1             case R.id.btnDlgLista_UD03_01_Dialogs:
 2                 builder = new AlertDialog.Builder(this);
 3                 builder.setIcon(android.R.drawable.ic_dialog_alert)
 4                     .setTitle("Escolle unha opción")
 5                     .setItems(R.array.array_elem_seleccion1_ud03_02_dialogs, new DialogInterface.OnClickListener() {
 6                     public void onClick(DialogInterface dialog, int posicion) {
 7                         // O usuario selecciona unha das opcións do listado
 8                         String[] opcions = getResources().getStringArray(R.array.array_elem_seleccion1_ud03_01_dialogs);
 9                         Toast.makeText(getApplicationContext(), "Seleccionaches: '" + opcions[posicion] + "'", Toast.LENGTH_LONG).show();
10                     }
11                 });
12                 builder.create();
13                 builder.show();
14 
15                 break;
  • Liña 5: Se fai uso do método setItems da clase AlertDialog.Builder (o cal está sobrecargado, podedes comprobalo no enlace). Na opción escollida espera recibir dous parámetros. No primeiro o id da clase R que fai referencia a un 'array-adapter' e o segundo un obxecto que implemente a interface DialogInterface.OnClickListener. No exemplo estamos a empregar unha interface anónima.
Ao evento onClick() chegará a posición do elemento seleccionado. Como temos unha referencia ao array con todos os datos, podemos saber cal foi a opción escollida.




Diálogo cunha única selección (radiobuttons)
PDM Dialogos 17.jpg


  • Neste tipo de diálogo van saír unha serie de opcións pero cunha aparencia de radiobuttons para que marquemos unha soa opción e despois premamos un botón de conformación de selección.



  • O código da Activity no método onClick(View v) quedaría así:
 1             case R.id.btnDlgUnicaSel_UD03_01_Dialogs:
 2                 builder = new AlertDialog.Builder(this)
 3                     .setIcon(android.R.drawable.ic_dialog_info)
 4                     .setTitle("Selecciona un smartpohone");
 5                 // Non incluír mensaxe dentro de este tipo de diálogo!!!
 6                 final CharSequence[] smartphones = { "iPhone", "Blackberry", "Android" };
 7                 
 8                 builder.setSingleChoiceItems(smartphones, 0, new DialogInterface.OnClickListener() {
 9                     public void onClick(DialogInterface dialog, int opcion) {
10                         // Evento que ocorre cando o usuario selecciona una opción
11                         Toast.makeText(getApplicationContext(), "Seleccionaches: " + smartphones[opcion], Toast.LENGTH_SHORT).show();
12                     }
13                 });
14                 
15                 builder.setPositiveButton("Aceptar", new DialogInterface.OnClickListener() {
16                     public void onClick(DialogInterface dialog, int boton) {
17                         Toast.makeText(getApplicationContext(), "Premeches 'Aceptar'", Toast.LENGTH_LONG).show();
18                     }
19                 });
20                 
21                 builder.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
22                     public void onClick(DialogInterface dialog, int boton) {
23                         Toast.makeText(getApplicationContext(), "Premeches 'Cancelar'", Toast.LENGTH_LONG).show();
24                     }
25                 });
26                 
27                 builder.create();
28                 builder.show();
29 
30 
31             break;
  • Liña 6: Definimos as opcións nun array CharSequence[].Poderíamos empregar igual que no caso anterior un array-string definido en /res/ pero poño este exemplo de uso para que vexades diferentes opcións.
  • Liña 8: Facendo uso do método setSingleChoiceItems() o cal está sobrecargado, enviamos o array cos datos, como segundo parámetro o elemento seleccionado da lista por defecto e como terceiro parámetro implementamos a interface DialogInterface.OnClickListener().



Diálogo cunha selección múltiple (checkboxes)
PDM Dialogos 19.jpg


  • Neste tipo de diálogo van saír unha serie de opcións pero cunha aparencia de radiobuttons para que marquemos unha soa opción e despois premamos un botón de conformación de selección.
Neste exemplo imos obter esas opcións dun String-Array definido en /res/values, pero poderíamos empregar calquera fonte de datos, que gardaríamos nun array e o pasaríamos como parámetro.
Se xa fixeches a práctica 1 xa o tedes definido e non fai falla facelo.
  • Aproveitamos o ficheiro /res/values/strings.xml e definimos un recurso de tipo Array, para a lista de selección e para a selección múltiple.


 1 <?xml version="1.0" encoding="utf-8"?>
 2 <resources>
 3 <resources>
 4 
 5     <string-array name="array_elem_seleccion2_ud03_02_dialogs">
 6         <item>Coche</item>
 7         <item>Moto</item>
 8         <item>Bici</item>
 9         <item>Metro</item>
10         <item>Tren</item>
11         <item>Autobús</item>
12         <item>Andando</item>
13     </string-array>
14 
15 
16 </resources>




  • O código da Activity no método onClick(View v) quedaría así:
 1             case R.id.btnDlgMulSelec_UD03_01_Dialogs:
 2 
 3                 builder = new AlertDialog.Builder(this)
 4                     .setIcon(android.R.drawable.ic_dialog_info)
 5                     .setTitle("Selecciona modos de transporte");
 6 
 7                 Resources res = getResources();
 8                 final String[] matriz = res.getStringArray(R.array.array_elem_seleccion2_ud03_02_dialogs);
 9 
10                 // Non incluír mensaxe dentro de este tipo de diálogo!!!
11                 builder.setMultiChoiceItems(matriz, new boolean[] { false, true, false, true, false, false, false }, new DialogInterface.OnMultiChoiceClickListener() {
12                     public void onClick(DialogInterface dialog, int opcion, boolean isChecked) {
13                         // Evento que ocorre cando o usuario selecciona unha opción
14                         if (isChecked)
15                             Toast.makeText(getApplicationContext(), "Seleccionaches " + matriz[opcion], Toast.LENGTH_SHORT).show();
16                         else
17                             Toast.makeText(getApplicationContext(), "Deseleccionaches " + matriz[opcion], Toast.LENGTH_SHORT).show();
18                     }
19                 });
20 
21                 builder.setPositiveButton("Aceptar", new DialogInterface.OnClickListener() {
22                     public void onClick(DialogInterface dialog, int boton) {
23                         Toast.makeText(getApplicationContext(), "Premeches 'Aceptar'", Toast.LENGTH_LONG).show();
24 
25                     }
26                 });
27                 builder.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
28                     public void onClick(DialogInterface dialog, int boton) {
29                         Toast.makeText(getApplicationContext(), "Premeches 'Cancelar'", Toast.LENGTH_LONG).show();
30                     }
31                 });
32 
33                 builder.create();
34                 builder.show();
35 
36             break;
  • Liña 7-8: Recuperamos o string-array de /res/. O declaramos final xa que imos referencial dentro da interface anónima.
  • Liña 11: Empregamos o método setMultiChoiceItems() o cal está sobrecargado. Neste caso, enviamos un array de strings como primeiro parámetro, como segundo parámetro leva un array de booleans indicando cales dos elementos da lista están chequeados ou non, e como terceiro parámetro implementamos a interface DialogInterface.OnMultiChoiceClickListener().
Se no segundo parámetro enviamos null, todos os elementos da lista estarán deseleccionados.

Dialog personalizado: DialogFragment

  • Un DialogFragment é un Fragment que amosa unha ventá de diálogo e situase por enriba da nosa Activity.
A vantaxe que ten con respecto aos díalogos 'predefinidos' é que podemos ter calquera deseño que queiramos xa que vai estar asociado a un Layout propio.
PDM Dialogos 21.jpg



PDM Dialogos 6.JPG


Esta forma de crear un diálogo tamén está deprecated dende a versión API 28, Android P
Android recomenda facer uso da biblioteca de compatibilidade com.android.support:support-v4:27.0.0 tanto para dar soporte a dispositivos anteriores a API 22 como con dispositivos posteriores a API 28.
Nota: Deberedes cambiar o número 27.0.0 pola versión compileSdkVersion do arquivo build.gradle.
Lembra que xa vimos como engadir unha biblioteca de compatibilidade nesta wiki


  • Ao facer uso da biblioteca de compatibilidade, cando cremos un DialogFragment teremos que importar a clase correcta, xa que teremos dúas opcións, a que ven coa biblioteca de compatibilidade e a 'orixinal'.
PDM Dialogos 10.jpg


Polo tanto na nosa activity terá que está importada a que provén da biblioteca de compatibilidade.
1 import android.support.v4.app.DialogFragment;


  • Ao empregar esta biblioteca Android Studio non deixará empregar unha Activity e teremos que facer uso da clase AppCompactActivity.
 1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Dialogs;
 2 
 3 import android.app.AlertDialog;
 4 import android.app.Dialog;
 5 import android.content.DialogInterface;
 6 import android.content.res.Resources;
 7 import android.os.Bundle;
 8 import android.support.v7.app.AppCompatActivity;
 9 import android.view.View;
10 import android.widget.Button;
11 import android.widget.Toast;
12 
13 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
14 
15 public class UD03_02_Dialogs extends AppCompatActivity implements View.OnClickListener {


  • Ao cambiar a activity o Theme por defecto non poderá ser empregado.
Como xa vimos nesta Wiki o theme por defecto a nivel do proxecto se atopa no arquivo styles.xml de /res/values/ e ten:
1 <resources>
2     <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
3         <!-- Customize your theme here. -->
4     </style>
5 </resources>
Agora, para que se vexa correctamente,debería ter isto:
1 <resources>
2     <style name="AppTheme" parent="android:Theme.AppCompat.Light.DarkActionBar">
3         <!-- Customize your theme here. -->
4     </style>
5 </resources>
Fixádevos que deriva de Theme.AppCompact.
Pero se o facemos a este nivel, afectará a todas as activities. Se tedes todos as activities derivando de AppCompatActivity non tedes problema, pero se non é o caso, deberedes de asinar o theme anterior pero o nivel desa Activity concreta.
Unha forma de facelo é modificando o arquivo AndroidManifiest.xml para esa Activity (outra forma sería no layout desa activity):
1         <activity android:name=".Dialogs.UD03_02_Dialogs" android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
2             android:label="UD03_02_Dialogs">




  • Un DialogFragment vai ter un layout asociado que vai compoñer o seu contido.
Definimos polo tanto o contido do noso diálogo.


O XML do DialogFragment

Código da clase fragment_ud03_02_layout_dialogo

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:app="http://schemas.android.com/apk/res-auto"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent">
 7 
 8     <EditText
 9         android:id="@+id/etPass_Dlg_UD03_02_Dialogs"
10         android:layout_width="0dp"
11         android:layout_height="wrap_content"
12         android:layout_marginEnd="8dp"
13         android:layout_marginStart="8dp"
14         android:contentDescription="Introduce o password"
15         android:inputType="textPassword"
16         android:textColor="@android:color/holo_blue_dark"
17         app:layout_constraintBottom_toBottomOf="@+id/tvNome_Dlg_UD03_02_Dialogs"
18         app:layout_constraintEnd_toEndOf="parent"
19         app:layout_constraintHorizontal_bias="0.0"
20         app:layout_constraintStart_toStartOf="@+id/guideline" />
21 
22     <TextView
23         android:id="@+id/tvNome_Dlg_UD03_02_Dialogs"
24         android:layout_width="wrap_content"
25         android:layout_height="0dp"
26         android:layout_marginStart="16dp"
27         android:layout_marginTop="28dp"
28         android:text="Contrasinal:"
29         android:textSize="18sp"
30         app:layout_constraintStart_toStartOf="parent"
31         app:layout_constraintTop_toBottomOf="@+id/tvPass_Dlg_UD03_02_Dialogs" />
32 
33     <TextView
34         android:id="@+id/tvPass_Dlg_UD03_02_Dialogs"
35         android:layout_width="wrap_content"
36         android:layout_height="wrap_content"
37         android:layout_marginStart="16dp"
38         android:layout_marginTop="16dp"
39         android:text="Nome:"
40         android:textSize="18sp"
41         app:layout_constraintStart_toStartOf="parent"
42         app:layout_constraintTop_toTopOf="parent" />
43 
44     <android.support.constraint.Guideline
45         android:id="@+id/guideline"
46         android:layout_width="wrap_content"
47         android:layout_height="wrap_content"
48         android:orientation="vertical"
49         app:layout_constraintGuide_begin="111dp" />
50 
51     <EditText
52         android:id="@+id/etNome_Dlg_UD03_02_Dialogs"
53         android:layout_width="0dp"
54         android:layout_height="wrap_content"
55         android:layout_marginEnd="8dp"
56         android:layout_marginStart="8dp"
57         android:contentDescription="Introduce o nome"
58         android:focusedByDefault="true"
59         android:textColor="@android:color/holo_blue_dark"
60         app:layout_constraintBottom_toBottomOf="@+id/tvPass_Dlg_UD03_02_Dialogs"
61         app:layout_constraintEnd_toEndOf="parent"
62         app:layout_constraintHorizontal_bias="0.0"
63         app:layout_constraintStart_toStartOf="@+id/guideline" />
64 
65     <Button
66         android:id="@+id/btnPechar_Frg_UD03_02_Dialogs"
67         android:layout_width="304dp"
68         android:layout_height="wrap_content"
69         android:layout_marginBottom="8dp"
70         android:layout_marginEnd="8dp"
71         android:layout_marginStart="8dp"
72         android:layout_marginTop="8dp"
73         android:text="Pecha o Diálogo"
74         app:layout_constraintBottom_toBottomOf="parent"
75         app:layout_constraintEnd_toEndOf="parent"
76         app:layout_constraintStart_toStartOf="parent"
77         app:layout_constraintTop_toBottomOf="@+id/etPass_Dlg_UD03_02_Dialogs" />
78 </android.support.constraint.ConstraintLayout>

Agora deberemos crear unha clase que vai representar o DialogFragment e que vai cargar o layout anterior. Esta clase será a que instanciaremos dende a nosa Activity.

O código Java do DialogFragment

  • Debemos ter en conta que este Dialog vai pedir unha información ao usuario (usuario-password)
Debemos implementar algunha forma de recuperar dita información por parte da Activity principal que chama a este Dialog.
Unha forma de facelo será crear no DialogFragment unha clase con campos que garden a información.
Dentro do DialogFragment crearemos un obxecto (neste caso public, pero poderíamos crear un método public getDato() e facer private ao obxecto) o cal imos poder acceder dende a Activity principal.


  • Se por algún motivo necesitamos acceder a métodos ou o contexto da Activity que chamou a este diálogo, podemos facer uso do método getActivity(), da forma:
  • Button btn = getActivity().findViewById(R.id.identificador); // Soamente podemos acceder a Views da Activity, non podemos referenciar as views do DialogFragment.
  • getActivity().getApplicationContext()


  • Se por algún motivo queremos acceder aos elementos gráficos (views) que se atopan dentro do layout do DialogFragment, dentro do código do mesmo, deberemos facer uso do método 'inflate' para obter unha referencia por programación e facer uso do método 'findVuewById()' do view que representa o layout:
 1 public class ExemploDialogo extends DialogFragment {
 2 
 3     private View rootView;
 4 
 5     @Override
 6     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 7 
 8         rootView = inflater.inflate(R.layout.fragment_ud03_02_layout_dialogo, container, false);
 9 
10         Button btn = (Button) rootView.findViewById(R.id.btnPechar_Frg_UD03_02_Dialogs);   // Exemplo de referencia a un view dentro do layout do DialogFragment
11  
12        
13         return rootView;
14     }
15 }
Como vemos, no caso do DialogFragment, o método onCreateView() deberá devolver o view que representa o layout do DialogFragment.
Desta forma poderíamos, por exemplo, sacar unha foto dentro dun DialogFragment poñendo o método onActivityResult() dentro do seu código para obter a foto sacada e cambiar o ImageView.



Nota: Ao poñer o código que ven a continuación vos dará un erro na liña 41. Isto é debido a que dita liña chama a un método da Activity principal que aínda non está creado. Está posto despois.

Código da clase UD3_15_DialogoFragmento
Obxectivo: Clase que representa ó DialogFragment

 1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Dialogs;
 2 
 3 import android.os.Bundle;
 4 import android.support.v4.app.DialogFragment;
 5 import android.view.LayoutInflater;
 6 import android.view.View;
 7 import android.view.ViewGroup;
 8 import android.widget.Button;
 9 import android.widget.EditText;
10 
11 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
12 
13 class DatosDialogFragment{
14     public String nome;
15     public String password;
16 }
17 
18 public class UD03_02_Dlg_Fragments extends DialogFragment {
19     public DatosDialogFragment datosDialogFragment;
20 
21 
22     @Override
23     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
24 
25         datosDialogFragment = new DatosDialogFragment();
26 
27         final View rootView = inflater.inflate(R.layout.fragment_ud03_02_layout_dialogo, container, false);
28         getDialog().setTitle(getTag());         // O Tag se envía dende a activiy có método show.
29 
30         Button btn = (Button) rootView.findViewById(R.id.btnPechar_Frg_UD03_02_Dialogs);
31         btn.setOnClickListener(new View.OnClickListener() {
32 
33             @Override
34             public void onClick(View v) {
35                 // TODO Auto-generated method stub
36                 EditText editNome = rootView.findViewById(R.id.etNome_Dlg_UD03_02_Dialogs);
37                 EditText editPassword = rootView.findViewById(R.id.etPass_Dlg_UD03_02_Dialogs);
38                 datosDialogFragment.nome = editNome.getText().toString();
39                 datosDialogFragment.password = editPassword.getText().toString();
40 
41                 ((UD03_02_Dialogs)getActivity()).pecharDialogo();  // Poderíamos chamar a algún método da Activity que abriu o Dialog se queremos
42                 dismiss();
43             }
44         });
45 
46         // Do something else
47         return rootView;
48     }
49 
50     /*
51     Se queremos darlle un tamaño específico ao layout do Dialog, podemos indicalo aquí, pero tendo en conta que se o tamaño é fixo non se adaptaría a diferentes tamaños da Activity (por exemplo cando rotamos)
52     @Override
53     public void onResume(){
54         super.onResume();
55 
56         int width = getResources().getDimensionPixelSize(R.dimen.dimen_width_fragment_03_02_dialogs);  // As medidas no arquivo de recursos tería o valor: XXXdp
57         int height = getResources().getDimensionPixelSize(R.dimen.dimen_height_fragment_03_02_dialogs);
58 
59         // Podemos empregar como medidas as constantes que indican o ancho ou alto do contenedor pai: 
60         //   ViewGroup.LayoutParams.MATCH_PARENT
61         //   ViewGroup.LayoutParams.MATCH_WRAP_CONTENT 
62         getDialog().getWindow().setLayout(width, height);
63     }
64     */
65 }

Analicemos o código.

  • Liña 4: Estamos a utilizar a librería de compatibilidade con versións anteriores de Android.
  • Liña 18: A nosa clase deriva de DialogFragment.
  • Liña 13-16: Esta é a clase que vai gardar os datos introducidos polo usuario no DialogFragment
  • Liña 23-48: O DialogFragment ten que devolver o View que conforma todo o diálogo. Sobreescribimos o método onCreateView() para facelo.
  • Liña 25: Instacimos o obxecto que vai gardar os datos introducidos no Dialog.
  • Liña 27,28: Veremos na activity principal, que cando instanciamos o DialogFragment, podemos pasarlle unha cadea de texto. Para recuperar esa cadea debemos facer uso do método getTag(). Non é obrigatorio pasala.
  • Liña 18: Buscamos dentro do layout do DialogFragment os botóns que queiramos xestionar. Neste caso soamente hai un.
  • Liña 36-39: Ao facer Click sobre o botón, buscamos os datos introducidos e os gardamos na propiedade 'datosDialogFragment' que será a cal accedamos dende a Activity principal.
  • Liña 41: Cando o DialogFragment se peche, necesitamos informar dalgunha maneira a Activity principal. Chamaremos por tanto a un método dela (é unha forma de facelo).
  • Liña 42: Pechamos o diálogo.



O código Java da Activity

Agora implantaremos a activity que vai facer uso do DialogFragment.

Aquí teremos dúas opcións:

  • Derivar a clase de Activity. Deberemos facer uso do método getFragmentManager().
  • Derivar a clase de FragmentActivity. Esta clase é unha subclase de Activity e está posta por compatibilidade coas versións anteriores.
No caso de utilizar esta clase deberemos facer uso do método getSupportFragmentManager. No noso exemplo imos facer uso deste método.

Código da clase UD03_02_Dialogs
Obxectivo: Amosar un diálogo baseado en Fragment.

  1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Dialogs;
  2 
  3 import android.app.AlertDialog;
  4 import android.content.DialogInterface;
  5 import android.content.res.Resources;
  6 import android.os.Bundle;
  7 import android.support.v4.app.FragmentManager;
  8 import android.support.v7.app.AppCompatActivity;
  9 import android.text.Html;
 10 import android.util.Log;
 11 import android.view.View;
 12 import android.widget.Button;
 13 import android.widget.Toast;
 14 
 15 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
 16 
 17 public class UD03_02_Dialogs extends AppCompatActivity implements View.OnClickListener {
 18 
 19     private UD03_02_Dlg_Fragments dialogoFragmento;
 20 
 21     private void xestioarEventos(){
 22 
 23         findViewById(R.id.btnDlgBotons_UD03_01_Dialogs).setOnClickListener(this);
 24         findViewById(R.id.btnDlgEntrada_UD03_01_Dialogs).setOnClickListener(this);
 25         findViewById(R.id.btnDlgLista_UD03_01_Dialogs).setOnClickListener(this);
 26         findViewById(R.id.btnDlgMensaxe_UD03_01_Dialogs).setOnClickListener(this);
 27         findViewById(R.id.btnDlgMulSelec_UD03_01_Dialogs).setOnClickListener(this);
 28         findViewById(R.id.btnDlgUnicaSel_UD03_01_Dialogs).setOnClickListener(this);
 29     }
 30 
 31     @Override
 32     protected void onCreate(Bundle savedInstanceState) {
 33         super.onCreate(savedInstanceState);
 34         setContentView(R.layout.activity_ud03_01__dialogs);     // Poñemos o mesmo layout que na activity UD03_01_Dialogs
 35 
 36         xestioarEventos();
 37         dialogoFragmento = new UD03_02_Dlg_Fragments();     // Deixamos instanciado o DialogFragment. Poderíamos facelo no intre que o creamos.
 38 
 39     }
 40 
 41     @Override
 42     public void onClick(View v) {
 43         AlertDialog.Builder builder=null;   // Nos eventos de botón sempre imos 'construir' un Dialog
 44 
 45         switch (v.getId()) {
 46             case R.id.btnDlgMensaxe_UD03_01_Dialogs:
 47                 builder = new AlertDialog.Builder(this)
 48                     .setTitle("Atención")
 49                     .setMessage("Nova amensaxe. Preme o botón 'Back' para volver á pantalla principal")
 50                     .setIcon(android.R.drawable.ic_dialog_email);
 51                 builder.create();   // Devolve un Dialog, pero non o necesitamos polo de agora.
 52                 builder.show();
 53 
 54                 break;
 55 
 56             case R.id.btnDlgBotons_UD03_01_Dialogs:
 57                 final Button btnOpcion = findViewById(R.id.btnDlgBotons_UD03_01_Dialogs);
 58 
 59                 builder = new AlertDialog.Builder(this)
 60                 .setTitle("Caixa de diálogo").setIcon(R.drawable.ic_launcher)
 61                 .setMessage("QUE TE PARACE ESTE DIALOGO ?")
 62 
 63                 .setPositiveButton("Ben", new DialogInterface.OnClickListener() {
 64                     @Override
 65                     public void onClick(DialogInterface dialog, int which) {
 66                         Toast.makeText(getApplicationContext(), "PULSADA OPCION BOA",Toast.LENGTH_LONG).show();
 67                         btnOpcion.setText(btnOpcion.getText().toString().concat("-OK"));
 68                     }
 69                 })
 70                 .setNegativeButton("MAL", new DialogInterface.OnClickListener() {
 71                     @Override
 72                     public void onClick(DialogInterface dialog, int which) {
 73 
 74                             Toast.makeText(getApplicationContext(),"PULSADA OPCION MALA", Toast.LENGTH_LONG).show();
 75 
 76                     }
 77                 })
 78                 .setNeutralButton("NON SEI", new DialogInterface.OnClickListener() {
 79                     @Override
 80                     public void onClick(DialogInterface dialog, int which) {
 81 
 82                         Toast.makeText(getApplicationContext(),"PULSADA OPCION NON SEI", Toast.LENGTH_LONG).show();
 83                     }
 84                 });
 85 
 86                 builder.create();
 87                 builder.show();
 88 
 89                 break;
 90 
 91             case R.id.btnDlgLista_UD03_01_Dialogs:
 92                 builder = new AlertDialog.Builder(this);
 93                 builder.setIcon(android.R.drawable.ic_dialog_alert)
 94                     .setTitle("Escolle unha opción")
 95                     .setItems(R.array.array_elem_seleccion1_ud03_01_dialogs, new DialogInterface.OnClickListener() {
 96                     public void onClick(DialogInterface dialog, int posicion) {
 97                         // O usuario selecciona unha das opcións do listado
 98                         String[] opcions = getResources().getStringArray(R.array.array_elem_seleccion1_ud03_01_dialogs);
 99                         Toast.makeText(getApplicationContext(), "Seleccionaches: '" + opcions[posicion] + "'", Toast.LENGTH_LONG).show();
100                     }
101                 });
102                 builder.create();
103                 builder.show();
104 
105                 break;
106 
107             case R.id.btnDlgUnicaSel_UD03_01_Dialogs:
108                 builder = new AlertDialog.Builder(this)
109                     .setIcon(android.R.drawable.ic_dialog_info)
110                     .setTitle("Selecciona un smartpohone");
111                 // Non incluír mensaxe dentro de este tipo de diálogo!!!
112                 final CharSequence[] smartphones = { "iPhone", "Blackberry", "Android" };
113 
114                 builder.setSingleChoiceItems(smartphones, 0, new DialogInterface.OnClickListener() {
115                     public void onClick(DialogInterface dialog, int opcion) {
116                         // Evento que ocorre cando o usuario selecciona una opción
117                         Toast.makeText(getApplicationContext(), "Seleccionaches: " + smartphones[opcion], Toast.LENGTH_SHORT).show();
118                     }
119                 });
120 
121                 builder.setPositiveButton("Aceptar", new DialogInterface.OnClickListener() {
122                     public void onClick(DialogInterface dialog, int boton) {
123                         Toast.makeText(getApplicationContext(), "Premeches 'Aceptar'", Toast.LENGTH_LONG).show();
124                     }
125                 });
126 
127                 builder.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
128                     public void onClick(DialogInterface dialog, int boton) {
129                         Toast.makeText(getApplicationContext(), "Premeches 'Cancelar'",  Toast.LENGTH_LONG).show();
130                     }
131                 });
132 
133                 builder.create();
134                 builder.show();
135 
136 
137             break;
138 
139             case R.id.btnDlgMulSelec_UD03_01_Dialogs:
140 
141                 builder = new AlertDialog.Builder(this)
142                     .setIcon(android.R.drawable.ic_dialog_info)
143                     .setTitle("Selecciona modos de transporte");
144 
145                 Resources res = getResources();
146                 final String[] matriz = res.getStringArray(R.array.array_elem_seleccion2_ud03_01_dialogs);
147 
148                 // Non incluír mensaxe dentro de este tipo de diálogo!!!
149                 builder.setMultiChoiceItems(matriz, new boolean[] { false, true, false, true, false, false, false }, new DialogInterface.OnMultiChoiceClickListener() {
150                     public void onClick(DialogInterface dialog, int opcion, boolean isChecked) {
151                         // Evento que ocorre cando o usuario selecciona unha opción
152                         if (isChecked)
153                             Toast.makeText(getApplicationContext(), "Seleccionaches " + matriz[opcion], Toast.LENGTH_SHORT).show();
154                         else
155                             Toast.makeText(getApplicationContext(), "Deseleccionaches " + matriz[opcion], Toast.LENGTH_SHORT).show();
156                     }
157                 });
158 
159                 builder.setPositiveButton("Aceptar", new DialogInterface.OnClickListener() {
160                     public void onClick(DialogInterface dialog, int boton) {
161                         Toast.makeText(getApplicationContext(), "Premeches 'Aceptar'", Toast.LENGTH_LONG).show();
162 
163                     }
164                 });
165                 builder.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
166                     public void onClick(DialogInterface dialog, int boton) {
167                         Toast.makeText(getApplicationContext(), "Premeches 'Cancelar'", Toast.LENGTH_LONG).show();
168                     }
169                 });
170 
171                 builder.create();
172                 builder.show();
173 
174             break;
175 
176             case R.id.btnDlgEntrada_UD03_01_Dialogs:
177                 FragmentManager fm = getSupportFragmentManager();
178                 dialogoFragmento.show(fm, "EXEMPLO DE DIALOGO!!!!");        // Enviamos no segundo parámetro información que vai recibir o DialogFragment có método getTag().
179                 break;
180 
181             default:
182                 break;
183         }
184 
185 
186     }
187 
188     protected void pecharDialogo(){
189         // O DialogFragment tamén pode chamar a métodos da activity que o invocou
190         Toast.makeText(this, Html.fromHtml("NOME:"+ dialogoFragmento.datosDialogFragment.nome + "<br/>PASSWORD:"+dialogoFragmento.datosDialogFragment.password), Toast.LENGTH_LONG).show();
191     }
192 
193 }

Analicemos o código.

  • Liñas 7,8,17: Por compatibilidade con versións anteriores de Android escollemos a opción de utilizar un FragmentActivity (v4) e unha AppCompacActivity(v7).
  • Liñas 19,37: Definimos e instaciamos o diálogo.
  • Liñas 177-178: Necesitamos un obxecto da clase FragmentManager para poder amosar o DialogFragment. Chamamos ao método show() no que no segundo parámetro podemos pasarlle unha cadea de texto ao DialogFragment que recollerá có método getTag().
  • Liñas 188-192: Este é o método que se chamará dende o DialogFragment para indicar que se pechou o diálogo. Podemos recoller os datos introducidos no mesmo accedendo á propiedade dialogoFragmento.datosDialogFragment.


Devolvendo información dunha forma máis elegante

  • No caso anterior vimos que para obter a información introducida no DialogFragment dende a Activity principal definimos unha propiedade public (public DatosDialogFragment datosDialogFragment;).
Podemos facelo dunha forma máis adecuada empregando interfaces. Podedes 'repasar' o uso das interfaces nesta entrada da Wiki.


  • Creamos unha nova clase DialogFragment de nome UD03_03_Dlg_Fragments cambiando as liñas
  • Onde aparece UD03_02_Dialogs por UD03_03_Dialogs:
  • Onde aparece UD03_02_Dlg_Fragments por UD03_03_Dlg_Fragments:


  • Creamos unha nova clase Activity de nome UD03_03_Dialogs co mesmo código que no caso anterior cambiando as liñas:
  • Onde aparece UD03_02_Dialogs por UD03_03_Dialogs:
  • Onde aparece UD03_02_Dlg_Fragments por UD03_03_Dlg_Fragments:



  • A idea é a seguinte:
  • 1º PASO: Definimos unha interface cos métodos que queiramos que sexan accesibles tanto dende a Activity como dende o DialogFragment. No caso que nos ocupa, teremos un único método que levará como parámetro un obxecto da clase Bundle, que nos vai servir para gardar a información do DialogFragment.
A definición da Interface podemos facela onde queiramos, xa que ao ser publica, poderemos acceder a ela dende calquera lugar do proxecto.
Eu vou definila na propia clase DialogFrament. Ademais vou definir un obxecto de dita clase (a Interface) que vai ser o que me vai servir de 'ponte' entre a activity principal e o DialogFragment.
 1 public class UD03_03_Dlg_Fragments extends DialogFragment {
 2 
 3     private OnCompleteListener mOnCompleteListener;
 4     /**
 5      * Interface que permite a la Activity padre recibir la información del diálogo
 6      */
 7     public interface OnCompleteListener {
 8         void onComplete (Bundle bundle);
 9     }
10 
11     ............


  • 2º PASO: Agora implementamos dita interface no Activity que vai chamar ao DialogFragment. Ao implementala teremos que implementar o su método (neste caso onComplete) o cal levará o obxecto da clase Bundle cos datos.
Polo tanto, cando dende o DialogFragment se chame a este método cos datos, a Activity principal os recibirá neste parámetro.
Deberemos gardar dito dato nunha propiedade 'local' para poder facer uso del noutros métodos (se o necesitamos)
 1 public class UD03_03_Dialogs extends AppCompatActivity implements View.OnClickListener,UD03_03_Dlg_Fragments.OnCompleteListener {
 2 
 3     private UD03_03_Dlg_Fragments dialogoFragmento=null;
 4     private Bundle datosDialogFragment=null;
 5 
 6     .....
 7 
 8     @Override
 9     public void onComplete(Bundle bundle) {
10         this.datosDialogFragment = bundle;
11         Toast.makeText(this, Html.fromHtml("NOME:"+ datosDialogFragment.getString("NOME") + "<br/>PASSWORD:"+datosDialogFragment.getString("PASSWORD")), 
12     }
Desta forma, cando se chame a este método a Acitivity principal xa terá os datos do DialogFrament na propiedade 'datosDialogFragment'.
  • 3º PASO: Debemos ter clara a seguinte idea: Cando se chama ao DialogFragment a activity principal é un obxecto da clase UD03_03_Dialogs e ao ter a interface UD03_03_Dlg_Fragments.OnCompleteListener implementada, en certa forma, tamén é un obxecto de dita clase. Quere isto dicir que podemos converter a Activity Principal nun obxecto da interface.
 1     @Override
 2     public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
 3 
 4 
 5         final View rootView = inflater.inflate(R.layout.fragment_ud03_02_layout_dialogo, container, false);
 6         getDialog().setTitle(getTag());         // O Tag se envía dende a activiy có método show.
 7 
 8         Button btn = (Button) rootView.findViewById(R.id.btnPechar_Frg_UD03_02_Dialogs);
 9         btn.setOnClickListener(new View.OnClickListener() {
10 
11             @Override
12             public void onClick(View v) {
13                 // TODO Auto-generated method stub
14                 EditText editNome = rootView.findViewById(R.id.etNome_Dlg_UD03_02_Dialogs);
15                 EditText editPassword = rootView.findViewById(R.id.etPass_Dlg_UD03_02_Dialogs);
16 
17                 Bundle datos = new Bundle();
18                 datos.putString("NOME",editNome.getText().toString());
19                 datos.putString("PASSWORD",editPassword.getText().toString());
20 
21                 mOnCompleteListener = (OnCompleteListener) getActivity();
22                 mOnCompleteListener.onComplete(datos);  // Agora xa chamamos a un método do Activity e podemos facer o que queiramos.
23 
24                 //((UD03_02_Dialogs)getActivity()).pecharDialogo();  // Poderíamos chamar a algún método da Activity que abriu o Dialog se queremos
25                 dismiss();
26             }
27         });
  • Liñas 21-22: Son estas liñas as que permiten 'enviar' os datos a activity principal. De todas formas necesitamos 'informar' a activity principal que xa se pechou a DialogFragment polo que chamamos ao método 'pecharDialog()' como no caso anterior.


</syntaxhighlight>



Unha variación. Devolvendo un AlertDialog.Builder

Esta é unha primeira aproximación os DialogFragment. Comentar que en vez de sobreescribir o método onCreateView do DialogFragment podemos sobreescribir o método onCreateDialog e devolver un diálogo construído por nos (coma un DatePickerDialog, AlertDialog.builder,....) Por exemplo:

Código da clase UD03_02_B_Dlg_Fragments
Obxectivo: Modificamos o código para amosar outra forma de crear un diálogo. Debemos comentar o código do método onCreateView.

 1 import android.app.AlertDialog;
 2 import android.app.Dialog;
 3 import android.content.DialogInterface;
 4 import android.content.DialogInterface.OnClickListener;
 5 import android.os.Bundle;
 6 import android.support.v4.app.DialogFragment;
 7 import android.widget.Toast;
 8 
 9 public class UD03_02_B_Dlg_Fragments extends DialogFragment{
10 
11 	
12 	@Override
13     public Dialog onCreateDialog(Bundle savedInstanceState) {
14 		AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
15 		.setTitle("Caixa de diálogo").setIcon(R.drawable.ic_launcher)
16 		.setMessage("QUE TE PARACE ESTE DIALOGO ?")
17 		.setPositiveButton("Ben", new OnClickListener() {
18 		@Override
19 		public void onClick(DialogInterface dialog, int which) {
20 			Toast.makeText(getActivity(), "PULSADA OPCION BOA",Toast.LENGTH_LONG).show();
21 		}
22 		}).setNegativeButton("MAL", new OnClickListener() {
23 		@Override
24 		public void onClick(DialogInterface dialog, int which) {
25 		//
26 
27 			Toast.makeText(getActivity(),"PULSADA OPCION MALA", Toast.LENGTH_LONG).show();
28 		}
29 		});
30 		return builder.create();
31 		
32 		
33 	}
34 	
35 }

Nota: Fixarse que estamos a importar a interface onClickListener do DialogInterface (liña 4).


Android 2014 U3 15 Dialogos 5.JPG



Titulos no DialogFragment

  • Como comentei na clase, a medida que van xurdindo novas versións de Android, pode variar o comportamento 'por defecto' dos compoñentes.
No caso das ventá de diálogo, a partires da versión API 23 (Android 6.0) o título non aparece por defecto.
Existen varias solucións posibles. Unha delas é a seguinte.
  • Necesitamos crear un style propio da forma seguinte:
Arquivo /res/values/styles.xml
1     <style name="CustomDialog" parent="@style/Theme.AppCompat.Light.Dialog">
2         <item name="android:windowNoTitle">false</item>
3     </style>


  • Agora aplicamos o estilo ao DialogFragment creado por nos:
Na Activity:
1                 DialogoAltaEmpresa dialogoAltaEmpresa = new DialogoAltaEmpresa();
2                 dialogoAltaEmpresa.setStyle(DialogFragment.STYLE_NORMAL,R.style.CustomDialog);




-- Ángel D. Fernández González e Carlos Carrión Álvarez -- (2015).