Visualizzazione delle finestre di dialogo di progettazione materiale in un'app Android

Il team di progettazione dei materiali di Google definisce la funzionalità dei dialoghi in Android come segue:

Le finestre di dialogo informano gli utenti su un'attività specifica e possono contenere informazioni critiche, richiedere decisioni o coinvolgere più attività.

Ora hai capito a cosa servono i dialoghi, ora è il momento di imparare a visualizzarli. In questo tutorial, ti illustrerò il processo di visualizzazione di diversi tipi di finestre di dialogo per la progettazione dei materiali in Android. Tratteremo le seguenti finestre di dialogo:

  • mettere in guardia
  • scelta singola e multipla 
  • selezionatore di data e ora
  • finestra di dialogo inferiore
  • finestra di dialogo a schermo intero

Un esempio di progetto per questo tutorial può essere trovato sul nostro repository GitHub per poter seguire facilmente.

1. Finestra di dialogo degli avvisi

Secondo la documentazione ufficiale di progettazione dei materiali di Google:

Gli avvisi sono interruzioni urgenti, che richiedono il riconoscimento, che informano l'utente di una situazione.

Creazione di una finestra di dialogo di avviso

Assicurati di includere l'ultimo appcompat artefatto nel tuo build.gradle file (modulo app). Il livello di API minimo supportato è Android 4.0 (livello API 14). 

dipendenze implementazione 'com.android.support:appcompat-v7:26.1.0'

La prossima cosa è creare un'istanza di AlertDialog.Builder

nuovo AlertDialog.Builder (this) .setTitle ("Nuke planet Jupiter?") .setMessage ("Notare che il pianeta Nuking Jupiter distruggerà tutto lì dentro.") .setPositiveButton ("Nuke", new DialogInterface.OnClickListener () @Override public void onClick (DialogInterface dialog, int which) Log.d ("MainActivity", "Invio di bombe atomiche a Jupiter");) .setNegativeButton ("Abort", new DialogInterface.OnClickListener () @ Override public void onClick (DialogInterface dialog, int which) Log.d ("MainActivity", "Aborting mission ...");) .show ();

Qui abbiamo creato un'istanza di AlertDialog.Builder e ha iniziato a configurare l'istanza chiamando su di esso alcuni metodi di setter. Si noti che stiamo usando il AlertDialog dall'artefatto di supporto Android.

import android.support.v7.app.AlertDialog;

Ecco i dettagli dei metodi di setter che abbiamo chiamato AlertDialog.Builder esempio. 

  • setTitle (): imposta il testo da mostrare nella barra del titolo della finestra di dialogo. 
  • setMessage (): imposta il messaggio da visualizzare nella finestra di dialogo. 
  • setPositiveButton (): il primo argomento fornito è il testo da mostrare nel pulsante positivo, mentre il secondo argomento è l'ascoltatore chiamato quando si fa clic sul pulsante positivo. 
  • setNegativeButton (): il primo argomento fornito è il testo da mostrare nel pulsante negativo, mentre il secondo argomento è il listener chiamato quando si fa clic sul pulsante negativo. 

Nota che AlertDialog.Builder ha un ImpostaVisualizzazione () per impostare la visualizzazione del layout personalizzato su di esso. 

Per mostrare la nostra finestra di dialogo sullo schermo, invochiamo mostrare().

C'è un altro metodo setter chiamato setNeutralButton (). Chiamando questo metodo si aggiungerà un altro pulsante sul lato sinistro della finestra di dialogo. Per chiamare questo metodo, dobbiamo passare a Stringa che servirà come testo del pulsante e anche un ascoltatore che viene chiamato quando viene toccato il pulsante. 

nuovo AlertDialog.Builder (this) // altri metodi setter .setNeutralButton ("Neutral", null) .show ()

Tieni presente che toccare fuori dalla finestra di dialogo lo ignorerà automaticamente. Per evitare che ciò accada, dovrai chiamare il setCanceledOnTouchOutside () sul AlertDialog istanza e passaggio falso come argomento. 

AlertDialog dialog = new AlertDialog.Builder (this) // dopo aver chiamato i metodi setter .create (); dialog.setCanceledOnTouchOutside (false); Dialog.Show ();

Per impedire ulteriormente la chiusura della finestra di dialogo premendo il tasto INDIETRO pulsante, devi quindi chiamare setCancelable () sul AlertDialog istanza e passaggio falso ad esso come una discussione. 

Styling di una finestra di dialogo di avviso

È abbastanza facile dare forma al nostro dialogo. Creiamo solo uno stile personalizzato nel stili.xml risorsa. Osserva che questo genitore di stile è Theme.AppCompat.Light.Dialog.Alert. In altre parole, questo stile eredita alcuni attributi di stile dal suo genitore. 

Iniziamo a personalizzare lo stile della finestra di dialogo impostando i valori degli attributi da applicare nella finestra di dialogo, ad esempio, possiamo cambiare il colore del pulsante di dialogo in modo che sia @android:colore/ holo_orange_dark e anche impostare lo sfondo della finestra di dialogo su un drawable personalizzato nella nostra cartella delle risorse estraibili (Android: windowBackground impostato @ Drawable / background_dialog).

Ecco il mio background_dialog.xml file di risorse. 

        

Qui abbiamo creato un'abitudine InsetDrawable che ci consente di aggiungere inserimenti su qualsiasi lato del ShapeDrawable. Abbiamo creato una forma rettangolare usando il etichetta. Abbiamo impostato il android: Forma attributo del  tag a rettangolo (altri valori possibili sono linea, ovale, squillare). Abbiamo un tag figlio che imposta il raggio degli angoli del rettangolo. Per un solido riempimento, abbiamo aggiunto il tag con un Android: il colore attributo che indica quale colore usare. Infine, abbiamo dato il nostro confine disegnabile usando il tag sul .

Per applicare questo stile alla finestra di dialogo, passiamo semplicemente lo stile personalizzato al secondo parametro nel AlertDialog.Builder costruttore. 

AlertDialog dialog = new AlertDialog.Builder (this, R.style.CustomDialogTheme)

2. Finestre di conferma

Secondo la documentazione di progettazione del materiale:

Le finestre di dialogo di conferma richiedono che gli utenti confermino esplicitamente la loro scelta prima che venga commessa un'opzione. Ad esempio, gli utenti possono ascoltare più suonerie, ma solo effettuare una selezione finale toccando "OK".

Sono disponibili i seguenti diversi tipi di finestre di conferma:

  • finestra di scelta multipla
  • finestra di scelta singola
  • date picker
  • selezionatore di tempo

Dialogo a scelta multipla 

Utilizziamo una finestra di dialogo a scelta multipla quando vogliamo che l'utente selezioni più di un elemento in una finestra di dialogo. In una finestra di dialogo a scelta multipla, viene visualizzato un elenco di scelte da cui l'utente può scegliere. 

String [] multiChoiceItems = getResources (). GetStringArray (R.array.dialog_multi_choice_array); final booleano [] checkedItems = false, false, false, false; nuovo AlertDialog.Builder (this) .setTitle ("Seleziona i tuoi film preferiti") .setMultiChoiceItems (multiChoiceItems, checkedItems, new DialogInterface.OnMultiChoiceClickListener () @Override public void onClick (DialogInterface dialog, int index, boolean isChecked) Log.d ("MainActivity", "indice oggetto selezionato" + indice);) .setPositiveButton ("Ok", null) .setNegativeButton ("Cancel", null) .show ();

Per creare una finestra di dialogo a scelta multipla, chiamiamo semplicemente il setMultiChoiceItems () metodo setter su AlertDialog.Builder esempio. All'interno di questo metodo, passiamo a schieramento di tipo Stringa come il primo parametro. Ecco il mio array, che si trova nel file delle risorse degli array /values/arrays.xml

   Il Cavaliere Oscuro La redenzione di Shawshank Salvate il soldato Ryan Il silenzio degli agnelli  

Il secondo parametro del metodo setMultiChoiceItems () accetta un array che contiene gli elementi che sono controllati. Il valore di ogni elemento nel CheckedItems matrice corrisponde a ciascun valore nel multiChoiceItems array. Abbiamo usato il nostro CheckedItems array (i cui valori sono tutti falso per impostazione predefinita) per rendere deselezionati tutti gli elementi per impostazione predefinita. In altre parole, il primo elemento "Cavaliere Oscuro" è deselezionato perché il primo elemento in CheckedItems l'array è falso, e così via. Se il primo elemento nel CheckedItems array era vero invece, allora "Cavaliere Oscuro" sarebbe controllato.

Si noti che questa matrice CheckedItems viene aggiornato quando selezioniamo o facciamo clic su qualsiasi elemento visualizzato, ad esempio, se l'utente deve selezionare "The Shawshank Redemption", chiamata CheckedItems [1] sarebbe tornato vero

L'ultimo parametro accetta un'istanza di OnMultiChoiceClickListener. Qui semplicemente creiamo una classe anonima e sostituiamo al clic(). Otteniamo un'istanza della finestra di dialogo mostrata nel primo parametro. Nel secondo parametro, otteniamo l'indice dell'articolo che è stato selezionato. Infine, nell'ultimo parametro, scopriamo se l'elemento selezionato è stato controllato o meno. 

Finestra di selezione singola 

In una finestra di scelta singola, a differenza della finestra di dialogo a scelta multipla, è possibile selezionare solo un elemento. 

String [] singleChoiceItems = getResources (). GetStringArray (R.array.dialog_single_choice_array); int itemSelected = 0; nuovo AlertDialog.Builder (this) .setTitle ("Seleziona il tuo sesso") .setSingleChoiceItems (singleChoiceItems, itemSelected, new DialogInterface.OnClickListener () @Override public void onClick (DialogInterface dialogInterface, int selectedIndex) ) .setPositiveButton (" Ok ", null) .setNegativeButton (" Cancel ", null) .show ();

Per creare una finestra di scelta singola, invochiamo semplicemente il setSingleChoiceItems () setter sul AlertDialog.Builder esempio. All'interno di questo metodo, passiamo anche a schieramento di tipo Stringa come il primo parametro. Ecco la matrice che abbiamo passato, che si trova nel file delle risorse degli array: /values/arrays.xml

    Maschio Femmina Altri  

Il secondo parametro del setSingleChoiceItems () viene utilizzato per determinare quale elemento è selezionato. L'ultimo parametro in al clic() ci dà l'indice dell'articolo che è stato selezionato, ad esempio, selezionando il Femmina articolo, il valore di selectedIndex sarà 1

Finestra di selezione data

Questo è un selettore di dialoghi che viene utilizzato per selezionare una singola data.

Per iniziare, creeremo a Calendario istanza di campo nel Attività principale e inizializzalo. 

public class MainActivity estende AppCompatActivity Calendar mCalendar = Calendar.getInstance (); // ... 

Qui abbiamo chiamato Calendar.getInstance () per ottenere l'ora corrente (nel fuso orario predefinito) e impostarla su mCalendar campo. 

DatePickerDialog datePickerDialog = new DatePickerDialog (questo, new DatePickerDialog.OnDateSetListener () @Override public void onDateSet (DatePicker view, int anno, int monthOfYear, int dayOfMonth) mCalendar.set (Calendar.YEAR, year); mCalendar.set (Calendar .MONTH, monthOfYear); mCalendar.set (Calendar.DAY_OF_MONTH, dayOfMonth); String date = DateFormat.getDateInstance (DateFormat.MEDIUM) .format (calendar.getTime ()); Log.d ("MainActivity", "La data selezionata è "+ data);, mCalendar.get (Calendar.YEAR), mCalendar.get (Calendar.MONTH), mCalendar.get (Calendar.DAY_OF_MONTH)); datePickerDialog.show ();

Per mostrare una finestra di dialogo di selezione data, creiamo un'istanza di DatePickerDialog. Ecco la spiegazione delle definizioni dei parametri durante la creazione di un'istanza di questo tipo. 

  • Il primo parametro accetta un contesto padre, ad esempio in un Attività, usate Questo, mentre in a Frammento, chiami getActivity ().  
  • Il secondo parametro accetta un listener di tipo OnDateSetListener. Questo ascoltatore onDateSet () viene chiamato quando l'utente imposta la data. All'interno di questo metodo, otteniamo l'anno selezionato, il mese selezionato dell'anno e anche il giorno selezionato del mese. 
  • Il terzo parametro è l'anno inizialmente selezionato. 
  • Il quarto parametro è il mese inizialmente selezionato (0-11). 
  • L'ultimo parametro è il giorno del mese inizialmente selezionato (1-31). 

Infine, chiamiamo il mostrare() metodo del DatePickerDialog istanza per visualizzarlo sullo schermo corrente. 

Impostazione di un tema personalizzato

È abbastanza facile personalizzare il tema della finestra di dialogo del selettore della data (simile a ciò che abbiamo fatto alla finestra di avviso). 

In breve, crei un drawable personalizzato, crei uno stile o un tema personalizzato e quindi applichi quel tema durante la creazione di un tema DatePickerDialog istanza nel secondo parametro.  

DatePickerDialog datePickerDialog = new DatePickerDialog (this, R.style.MyCustomDialogTheme, listener, 2017, 26, 11);

Finestra di selezione del tempo

La finestra di dialogo di selezione orari consente all'utente di selezionare un orario e di adattarsi all'impostazione preferita per l'orario dell'utente, ad esempio il formato di 12 ore o di 24 ore.

Come puoi vedere nel codice qui sotto, creando a TimePickerDialog è abbastanza simile alla creazione di a DatePickerDialog. Quando si crea un'istanza di TimePickerDialog, passiamo nei seguenti parametri:

  • Il primo parametro accetta un contesto genitore. 
  • Il secondo parametro accetta un OnTimeSetListener istanza che funge da ascoltatore.
  • Il terzo parametro è l'ora iniziale del giorno. 
  • Il quarto parametro è il minuto iniziale.
  • L'ultimo parametro è impostare se vogliamo la visualizzazione nel formato 24 ore o AM / PM. 
TimePickerDialog timePickerDialog = new TimePickerDialog (questo, new TimePickerDialog.OnTimeSetListener () @Override public void onTimeSet (TimePicker timePicker, int hourOfDay, int minute) mCalendar.set (Calendar.HOUR_OF_DAY, hourOfDay); mCalendar.set (Calendar.MINUTE, minuto); String time = DateFormat.getTimeInstance (DateFormat.SHORT) .format (calendar.getTime ()); Log.d ("MainActivity", "Ora selezionata" + ora);, mCalendar.get (Calendar. HOUR_OF_DAY), calendar.get (Calendar.MINUTE), true); timePickerDialog.show ();

Il onTimeSet () il metodo viene chiamato ogni volta che l'utente ha selezionato l'ora. All'interno di questo metodo, otteniamo un'istanza di TimePicker, l'ora selezionata del giorno scelto e anche il minuto selezionato. 

Per visualizzare questa finestra di dialogo, chiamiamo ancora il mostrare() metodo.

Il Time Picker può essere abbinato in modo simile alla finestra di selezione del data. 

3. Finestra di dialogo di foglio inferiore

Secondo la documentazione ufficiale di progettazione dei materiali di Google:

I fogli in basso scorrono verso l'alto dalla parte inferiore dello schermo per rivelare più contenuti.

Per iniziare a utilizzare la finestra di dialogo del foglio di sotto, devi importare l'artefatto del supporto alla progettazione, quindi visita i moduli dell'app build.gradle file per importarlo. 

dipendenze implementazione 'com.android.support:appcompat-v7:26.1.0' implementazione 'com.android.support:design:26.1.0'

Assicurati che compaia l'attività o il frammento per la finestra di dialogo del basso, il suo layout genitore è il CoordinatorLayout

   

Qui abbiamo anche un FrameLayout quello servirebbe da contenitore per il nostro foglio inferiore. Osserva quello di questo FrameLayoutGli attributi di app: layout_behavior, il cui valore è una risorsa stringa speciale associata a android.support.design.widget.BottomSheetBehavior. Ciò consentirà il nostro FrameLayout apparire come un foglio inferiore. Nota che se non includi questo attributo, la tua app si bloccherà. 

public class MainActivity estende AppCompatActivity // ... // ... private BottomSheetDialog mBottomSheetDialog; @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); // ... Visualizza bottomSheet = findViewById (R.id.framelayout_bottom_sheet); 

Qui abbiamo dichiarato un'istanza di BottomSheetDialog come un campo per il nostro MainActivity.java e inizializzato nel onCreate () metodo della nostra attività. 

final Visualizza bottomSheetLayout = getLayoutInflater (). gonfia (R.layout.bottom_sheet_dialog, null); (bottomSheetLayout.findViewById (R.id.button_close)). setOnClickListener (new View.OnClickListener () @Override public void onClick (Visualizza vista) mBottomSheetDialog.dismiss ();); (bottomSheetLayout.findViewById (R.id.button_ok)). setOnClickListener (new View.OnClickListener () @Override public void onClick (View v) Toast.makeText (getApplicationContext (), "Pulsante OK fatto clic", Toast.LENGTH_SHORT) .mostrare();  ); mBottomSheetDialog = new BottomSheetDialog (this); mBottomSheetDialog.setContentView (bottomSheetLayout); mBottomSheetDialog.show ();

Nel codice precedente, abbiamo gonfiato il layout del foglio inferiore R.layout.bottom_sheet_dialog. Impostiamo gli ascoltatori per il Annulla e Ok pulsanti nel bottom_sheet_dialog.xml. Quando il Annulla viene cliccato il pulsante, semplicemente ignoriamo la finestra di dialogo. 

Abbiamo quindi inizializzato il nostro mBottomSheetDialog campo e impostare la vista utilizzando setContentView (). Infine, chiamiamo il mostrare() metodo per visualizzarlo sullo schermo. 

Ecco il mio bottom_sheet_dialog.xml:

     

Assicurati di dare un'occhiata Come usare i fogli di fondo con la libreria di supporto del design di Paul Trebilcox-Ruiz qui su Envato Tuts + per saperne di più sui fogli di botttom.

4. Finestra di dialogo a schermo intero

Secondo la documentazione ufficiale di progettazione dei materiali di Google:

Le finestre di dialogo a schermo intero raggruppano una serie di attività (come la creazione di una voce del calendario) prima che possano essere impegnate o scartate. Nessuna selezione viene salvata fino a quando non viene toccato "Salva". Toccando la "X" scarta tutte le modifiche ed esce dalla finestra di dialogo.

Vediamo ora come creare una finestra di dialogo a schermo intero. Innanzitutto, assicurati di includere l'artefatto v4 per il supporto Android nel modulo della tua app build.gradle. Questo è necessario per supportare Android 4.0 (livello API 14) e superiore. 

implementazione 'com.android.support:support-v4:26.1.0'

Successivamente, creeremo un FullscreenDialogFragment che estende il DialogFragment super classe. 

public class FullscreenDialogFragment estende DialogFragment @Override public Visualizza onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) Visualizza rootView = inflater.inflate (R.layout.full_screen_dialog, container, false); (rootView.findViewById (R.id.button_close)). setOnClickListener (new View.OnClickListener () @Override public void onClick (View v) dismiss ();); return rootView;  @NonNull @Override public Dialog onCreateDialog (Bundle savedInstanceState) Dialog dialog = super.onCreateDialog (savedInstanceState); dialog.requestWindowFeature (Window.FEATURE_NO_TITLE); finestra di dialogo di ritorno; 

Qui sostituiamo il onCreateView () (proprio come faremmo con un ordinario Frammento). All'interno di questo metodo, semplicemente gonfiamo e restituiamo il layout (R.layout.full_screen_dialog) che fungerà da visualizzazione personalizzata per il dialogo. Abbiamo impostato un OnClickListener sul ImageButton (R.id.button_close) che chiuderà la finestra di dialogo quando si fa clic. 

Abbiamo anche l'override onCreateDialog () e restituire un Dialogo. All'interno di questo metodo, puoi anche restituire un AlertDialog creati utilizzando un AlertDialog.Builder

Nostro R.layout.full_screen_dialog consiste di un ImageButton, un Pulsante, e alcuni TextView etichette:

      

Nel ImageButton widget, vedrai un attributo app: srcCompat che fa riferimento a un'abitudine VectorDrawable (@ Drawable / ic_close). Questa usanza VectorDrawable crea il X pulsante, che chiude la finestra di dialogo a schermo intero quando viene toccato. 

  

Per poter usare questo app: srcCompat attributo, assicurati di includerlo nel tuo build.gradle file. Quindi, configura la tua app per utilizzare le librerie di supporto vettoriale e aggiungi il vectorDrawables elemento al tuo build.gradle file nel modulo dell'app.

android defaultConfig vectorDrawables.useSupportLibrary = true

Lo abbiamo fatto per poter supportare tutte le versioni della piattaforma Android su Android 2.1 (livello API 7+). 

Infine, per mostrare il FullscreenDialogFragment, noi semplicemente usiamo il FragmentTransaction per aggiungere il nostro frammento all'interfaccia utente. 

FragmentManager fragmentManager = getSupportFragmentManager (); FullscreenDialogFragment newFragment = new FullscreenDialogFragment (); FragmentTransaction transaction = fragmentManager.beginTransaction (); transaction.setTransition (FragmentTransaction.TRANSIT_FRAGMENT_OPEN); transaction.add (android.R.id.content, newFragment) .addToBackStack (null) .commit ();

5. Orientamento del dispositivo sopravvissuto

Tieni presente che tutte le finestre di dialogo illustrate qui, ad eccezione della finestra di dialogo a schermo intero, verranno automaticamente ignorate quando l'utente cambia l'orientamento dello schermo del dispositivo Android, da verticale a orizzontale (o viceversa). Questo perché il sistema Android ha distrutto e ricreato il Attività in modo da adattarsi al nuovo orientamento. 

Per sostenere la finestra di dialogo attraverso le modifiche all'orientamento dello schermo, dovremo creare un Frammento che estende il DialogFragment super classe (proprio come abbiamo fatto per l'esempio di finestra di dialogo a schermo intero). 

Vediamo un semplice esempio per una finestra di avviso. 

public class AlertDialogFragment estende DialogFragment implementa DialogInterface.OnClickListener @Override public Dialog onCreateDialog (Bundle savedInstanceState) AlertDialog.Builder builder = new AlertDialog.Builder (getActivity ()); return (builder.setTitle ("Attiva i superpoteri?"). setMessage ("Attivando i superpoteri, avrai più poteri per salvare il mondo.") .setPositiveButton ("Attiva", questo) .setNegativeButton ("Annulla", questo ) .creare());  @Override public void onCancel (DialogInterface dialog) super.onCancel (dialog);  @Override public void onDismiss (DialogInterface dialog) super.onDismiss (dialog);  @Override public void onClick (DialogInterface dialog, int which) Toast.makeText (getActivity (), "which is" + which, Toast.LENGTH_LONG) .show (); 

Qui, abbiamo creato una classe che estende il DialogFragment e implementa anche il DialogInterface.OnClickListener. Poiché abbiamo implementato questo listener, dobbiamo ignorare il al clic() metodo. Nota che se tocchiamo il pulsante positivo o negativo, questo al clic() il metodo sarà invocato. 

Dentro il nostro onCreateDialog (), creiamo e restituiamo un'istanza di AlertDialog

Abbiamo anche scavalcato:

  • onCancel (): questo è chiamato se l'utente preme il tasto INDIETRO pulsante per uscire dalla finestra di dialogo. 
  • onDismiss (): questo viene chiamato ogni volta che la finestra di dialogo viene forzata per qualsiasi motivo (INDIETRO o un clic del tasto). 

Per mostrare questo dialogo, chiamiamo semplicemente il mostrare() metodo su un'istanza del nostro AlertDialogFragment

nuovo AlertDialogFragment (). show (getSupportFragmentManager (), "alertdialog_sample");

Il primo parametro è un'istanza di FragmentManager. Il secondo parametro è un tag che può essere utilizzato per recuperare questo frammento di nuovo in seguito dal FragmentManager attraverso findFragmentByTag ().