Diferencia entre revisiones de «Ventás de Diálogos»
(No se muestra una edición intermedia del mismo usuario) | |||
Línea 698: | Línea 698: | ||
− | * '''<u> | + | * '''<u>NOTAS IMPORTANTES:</u>''' |
:* 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 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; | :* Se estamos a empregar unha Activity que deriva de Activity, debemos empregar o paquete: import android.app.AlertDialog; | ||
+ | |||
+ | :* Se estamos a empregar unha Activity que deriva de AppCompactActivity, e a creación do diálogo o facemos dentro dunha interface anónima (por exemplo, no evento Click dun botón) debemos <u>pasar o contexto da activity da forma Nome_Da_Activity.this</u>. | ||
+ | :: Por exemplo, se a miña activity se chama 'AmosandoDialogos', cando cremos o diálogo (o imos ver a continuación) teremos que empregar a forma: AlertDialog.Builder dialogo = new AlertDialog.Builder('''AmosandoDialogos.this'''); | ||
Revisión del 15:57 10 nov 2019
Sumario
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.
- Lembrar como xa vimos no ciclo de vida das activities que a aparición dun DialogBox implicará que a Activity pase ao estado Paused.
- 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.
- 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:
- 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
- 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
- Referencias:
Dialogs anteriores a API 13
- Nota: Opción deprecated. Utilizar DialogFragments (seguinte sección)
- Partimos que xa temos creado o proxecto inicial como xa indicamos anteriormente.
- 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.
- Esta aplicación está baseada no curso de Android da Aula Mentor: http://www.mentor.mec.es/
- 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.
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).
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, que vai ser o tipo de diálogo cando queiramos deseñar por nos o que vai amosar. O veremos na última opción do seguinte exercicio.
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'.
- Partimos que xa temos creado o proxecto inicial como xa indicamos anteriormente.
- 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.
- Todos os diálogos anteriores menos o último fanse facendo uso da clase AlertDialog.Builder.
- 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.
- NOTAS IMPORTANTES:
- 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;
- Se estamos a empregar unha Activity que deriva de AppCompactActivity, e a creación do diálogo o facemos dentro dunha interface anónima (por exemplo, no evento Click dun botón) debemos pasar o contexto da activity da forma Nome_Da_Activity.this.
- Por exemplo, se a miña activity se chama 'AmosandoDialogos', cando cremos o diálogo (o imos ver a continuación) teremos que empregar a forma: AlertDialog.Builder dialogo = new AlertDialog.Builder(AmosandoDialogos.this);
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
- 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 AlertDialog, 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
- 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':
- 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)
- Os botóns se poden identificar polas constantes definidas na clase DialogInterface
- 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
- 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)
- 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)
- 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>
- Neste tipo de diálogo varía a Interface que xestiona o Click sobre cada un dos elementos da lista e pasa a ser a Interface DialogInterface.OnMultiChoiceClickListener.
- 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.
- Os DialogFragment foron engadidos na versión API 22.
- 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'.
- 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).
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).