Android offre un modello a componenti sofisticato e potente per creare la tua UI, basato su
le classi di layout di base
View
e
ViewGroup
. La piattaforma include
varietà di sottoclassi View
e ViewGroup
predefinite, chiamate widget e
layout, che puoi utilizzare per creare la tua UI.
Un elenco parziale dei widget disponibili include Button
,
TextView
,
EditText
,
ListView
,
CheckBox
,
RadioButton
,
Gallery
,
Spinner
e lo scopo più speciale
AutoCompleteTextView
,
ImageSwitcher
e
TextSwitcher
.
Tra i layout disponibili ci sono
LinearLayout
,
FrameLayout
,
RelativeLayout
,
e altri. Per altri esempi, vedi
Layout comuni.
Se nessuno dei widget o dei layout predefiniti soddisfa le tue esigenze, puoi crearne uno personalizzato
View
sottoclasse. Se devi apportare solo piccole modifiche a un widget esistente o
layout, puoi creare sottoclassi del widget o del layout e sostituire i relativi metodi.
La creazione di sottoclassi View
personalizzate ti offre un controllo preciso sull'aspetto e
di un elemento dello schermo. Per dare un'idea del controllo che ottieni con le visualizzazioni personalizzate, ecco
alcuni esempi di cosa puoi fare con questi strumenti:
-
Puoi creare un tipo di
View
con rendering completamente personalizzato, ad esempio un "volume controllo" , visualizzata con grafica 2D, che ricorda un controllo elettronico analogico. -
Puoi combinare un gruppo di
View
componenti in un nuovo singolo componente, ad esempio per creare qualcosa come una casella combinata (una combinazione di elenco popup e campo di testo a immissione libera), una controllo selettore a doppio riquadro (un riquadro sinistro e destro con un elenco in cui è possibile riassegnare quale elemento è in un elenco) e così via. -
Puoi eseguire l'override del modo in cui un componente
EditText
viene visualizzato sullo schermo. La L'app di esempio Blocco note utilizza questa funzionalità per creare una pagina Blocco note a righe. - Puoi acquisire altri eventi, come le pressioni dei tasti, e gestirli in modo personalizzato, come come per un gioco.
Le sezioni seguenti spiegano come creare viste personalizzate e utilizzarle nella tua applicazione. Per
informazioni di riferimento dettagliate, consulta
View
corso.
Approccio di base
Ecco una panoramica generale di ciò che devi sapere per creare il tuo View
componenti:
-
Estendi una classe o una sottoclasse
View
esistente con il tuo corso. -
Sostituire alcuni metodi dalla superclasse. I metodi della superclasse da sostituire iniziano con
on
, ad esempioonDraw()
,onMeasure()
, eonKeyDown()
. Questo evento è simile agli evention
inActivity
oListActivity
che per il ciclo di vita e altri hook di funzionalità. - Utilizza la nuova classe di estensione. Al termine, potrai utilizzare la nuova classe di estensione al posto di la vista su cui si basava.
Componenti completamente personalizzati
Puoi creare componenti grafici completamente personalizzati che vengono visualizzati comunque desiderato. Magari vuoi un VU meter grafico che assomiglia a un vecchio indicatore analogico o una visualizzazione testo da cantare in cui una palla che rimbalza lungo le parole mentre canti insieme a un apparecchio per il karaoke. Potresti volere un'operazione impossibile dai componenti integrati, indipendentemente da come li combini.
Fortunatamente, puoi creare componenti con aspetto e comportamento come preferisci, ma limitati in base all'immaginazione, alle dimensioni dello schermo e alla potenza di elaborazione disponibile, tenendo presente che potrebbe dover essere eseguita su un sistema con una potenza notevolmente inferiore a quella del desktop la workstation.
Per creare un componente completamente personalizzato, considera quanto segue:
-
La visualizzazione più generica che puoi estendere è
View
, quindi in genere inizi con l'estensione questo per creare il nuovo supercomponente. - Puoi fornire un costruttore, che può prendere attributi e parametri dal file XML, utilizzare i propri attributi e parametri, come il colore e l'intervallo del VU meter o la larghezza e lo smorzamento dell'ago.
- Probabilmente vorrai creare listener di eventi, funzioni di accesso alle proprietà e modificatori personalizzati, nonché un comportamento più sofisticato nella classe del componente.
-
Quasi certamente vorrai eseguire l'override di
onMeasure()
e probabilmente dovrai anche sostituiscionDraw()
se vuoi che il componente mostri qualcosa. Sebbene entrambi abbiano comportamento predefinito, il valore predefinitoonDraw()
non fa nulla e il comportamento predefinitoonMeasure()
imposta sempre una dimensione di 100 x 100, cosa che probabilmente non vuoi utilizzare. -
Puoi anche sostituire altri metodi di
on
, se necessario.
Estendi onDraw() e onMeasurement()
Il metodo onDraw()
invia una
Canvas
su cui puoi
implementare tutto ciò che si desidera: grafiche 2D, altri componenti standard o personalizzati, testo con stili applicati o
qualsiasi altra idea ti venga in mente.
onMeasure()
è un po' più coinvolto. onMeasure()
è un elemento fondamentale
del contratto di rendering tra il tuo componente e il relativo contenitore. onMeasure()
deve essere
sovrascritto per un report efficiente e accurato le misurazioni delle parti che contiene. Questo è
resi leggermente più complessi dai requisiti limite previsti dall'elemento principale, che vengono trasferiti
onMeasure()
e in base al requisito di chiamare il metodo
Metodo setMeasuredDimension()
con la larghezza e l'altezza misurate, una volta che sono
calcolato. Se non chiami questo metodo da un metodo onMeasure()
con override,
genera un'eccezione al momento della misurazione.
A livello generale, l'implementazione di onMeasure()
ha un aspetto simile al seguente:
-
Il metodo
onMeasure()
sostituito viene richiamato con larghezza e altezza specifiche, che vengono trattate come requisiti per i limiti di larghezza e altezza le misurazioni che produci.widthMeasureSpec
eheightMeasureSpec
sono entrambi codici interi che rappresentano le dimensioni. Un riferimento completo al tipo di restrizioni che queste specifiche possono richiedere sono disponibili nella documentazione di riferimento alla paginaView.onMeasure(int, int)
Questa documentazione di riferimento spiega anche l'intera operazione di misurazione. -
Il metodo
onMeasure()
del componente calcola la larghezza e l'altezza delle misurazioni, necessari per il rendering del componente. Deve cercare di rimanere entro le specifiche superate anche se possono superarli. In questo caso, il genitore può scegliere cosa fare, incluse ritagliare, scorrere, generare un'eccezione o chiedere all'onMeasure()
di riprovare. magari con specifiche di misurazione diverse. -
Quando vengono calcolate la larghezza e l'altezza, richiama il metodo
setMeasuredDimension(int width, int height)
con il valore calcolato le misurazioni. In caso contrario, verrà applicata un'eccezione.
Ecco un riepilogo degli altri metodi standard richiamati dal framework:
Categoria | Metodi | Descrizione |
---|---|---|
Creazione | Costruttori | Esiste un tipo di costruttore che viene chiamato quando la vista viene creata dal codice e un modulo che viene chiamato quando la visualizzazione è aumentata in modo artificioso da un file di layout. Il secondo modulo analizza e applica gli attributi definiti nel file di layout. |
|
Viene chiamato dopo una visualizzazione e tutti i relativi elementi figlio vengono gonfiati in modo artificioso da XML. | |
Layout |
|
Chiamato per determinare i requisiti di dimensioni per questa vista e tutte dei suoi figli. |
|
Richiamato se questa vista deve assegnare dimensioni e posizione a tutti gli elementi secondari. | |
|
Richiamato se vengono modificate le dimensioni di questa visualizzazione. | |
Disegno |
|
Richiamato quando la visualizzazione deve eseguire il rendering dei propri contenuti. |
Elaborazione degli eventi |
|
Richiamato quando si verifica un evento di disattivazione della chiave. |
|
Richiamato quando si verifica un evento di key-up. | |
|
Richiamato quando si verifica un evento di movimento trackball. | |
|
Richiamato quando si verifica un evento di movimento del touchscreen. | |
Messa a fuoco |
|
Richiamato se la visualizzazione acquisisce o perde l'attenzione. |
|
Richiamato quando la finestra contenente la visualizzazione acquisisce o perde lo stato attivo. | |
Caricamento in corso... |
|
Richiamato quando la vista è collegata a una finestra. |
|
Richiamato quando la visualizzazione viene scollegata dalla finestra. | |
|
Richiamato se viene modificata la visibilità della finestra contenente la visualizzazione. |
Controlli composti
Se non desideri creare un componente completamente personalizzato, ma vuoi utilizzare
un componente riutilizzabile composto da un gruppo di controlli esistenti, per poi creare un
(o controllo composto) potrebbe essere la soluzione migliore. Riassumendo, questa presentazione riunisce molti altri
o viste atomiche, in un gruppo logico di elementi che possono essere trattati come un'unica cosa.
Ad esempio, una casella combinata può essere una combinazione di un campo EditText
a riga singola
e un pulsante adiacente con un elenco popup allegato. Se l'utente tocca il pulsante e seleziona un elemento
l'elenco, compila il campo EditText
, ma gli utenti possono anche digitare
direttamente nel EditText
, se lo preferiscono.
In Android, sono disponibili altre due visualizzazioni per farlo: Spinner
e
AutoCompleteTextView
. Indipendentemente da ciò, questo concetto di casella combinata è un buon esempio.
Per creare un componente composto, segui questi passaggi:
-
Come nel caso di un
Activity
, utilizza l'approccio dichiarativo (basato su XML) per creare i componenti contenuti o nidificarli in modo programmatico dal codice. La il solito punto di partenza è unaLayout
di qualche tipo, quindi crea una classe che ampliaLayout
. Nel caso di una casella combinata, potresti usareLinearLayout
con orientamento orizzontale. Puoi nidificare altri layout all'interno, in modo che il componente composto possa arbitrariamente complessa e strutturata. -
Nel costruttore della nuova classe, prendi i parametri previsti dalla superclasse e passali
prima di tutto al costruttore della superclasse. Poi puoi impostare le altre viste da utilizzare
all'interno del nuovo componente. Qui puoi creare il campo
EditText
e elenco popup. Puoi introdurre i tuoi attributi e parametri nel file XML costruttore può eseguire il pull e utilizzare. -
Facoltativamente, crea listener per gli eventi che potrebbero essere generati dalle viste contenute. Un esempio è un
il metodo listener per il listener dei clic sugli elementi dell'elenco che aggiorna i contenuti del
EditText
se viene effettuata una selezione da un elenco. -
Se vuoi, puoi creare le tue proprietà con le funzioni di accesso e i modificatori. Ad esempio, lascia che
Il valore
EditText
viene impostato inizialmente nel componente e nella query per i suoi contenuti quando necessaria. -
Se vuoi, esegui l'override di
onDraw()
eonMeasure()
. Generalmente questa operazione non è necessaria estendere unLayout
, poiché il layout ha un comportamento predefinito che probabilmente funziona correttamente. -
Se vuoi, sostituisci altri metodi di
on
, comeonKeyDown()
, ad esempio per scegliere determinati valori predefiniti dall'elenco popup di una casella combinata quando viene toccato un determinato tasto.
L'utilizzo di un Layout
come base per un controllo personalizzato offre vantaggi,
tra cui:
- Puoi specificare il layout utilizzando i file XML dichiarativi, proprio come con una schermata di attività. oppure creare viste in modo programmatico e nidificarle nel layout partendo dal codice.
-
I metodi
onDraw()
eonMeasure()
, più la maggior parte degli altrion
hanno un comportamento adatto, quindi non è necessario sostituirli. - È possibile costruire rapidamente viste composte complesse e riutilizzarle come se fossero è un singolo componente.
Modificare un tipo di visualizzazione esistente
Se esiste un componente simile, puoi estenderlo ed eseguire l'override
il comportamento che vuoi modificare. Puoi fare tutto ciò che fai con un piano
ma iniziando con una classe più specializzata nella gerarchia View
, puoi
adotta un comportamento che faccia quello che vuoi,
senza costi.
Ad esempio,
Blocco note
app di esempio che mostra molti aspetti dell'utilizzo della piattaforma Android. Tra questi c'è l'estensione di
Visualizzazione EditText
per creare un blocco note allineato. Questo non è un esempio perfetto e le API per
fare questo potrebbe cambiare, ma dimostra i principi.
Se non l'hai ancora fatto, importa l'esempio di Blocco note in Android Studio o consulta l'
utilizzando il link fornito. In particolare, consulta la definizione di LinedEditText
nel
NoteEditor.java
.
Ecco alcuni aspetti da considerare per questo file:
-
Definizione
La classe è definita con la seguente riga:
public static class LinedEditText extends EditText
LinedEditText
è una classe interna all'interno diNoteEditor
ma è pubblica, quindi è possibile accedervi comeNoteEditor.LinedEditText
persone che non rientrano nel corsoNoteEditor
.Inoltre,
LinedEditText
èstatic
, il che significa che non genera i cosiddetti "metodi sintetici" che le consentono di accedere ai dati della classe principale. Ciò significa si comporta come una classe separata anziché con qualcosa di strettamente correlato aNoteEditor
. Si tratta di un modo più semplice per creare classi interne se non hanno bisogno dell'accesso allo stato una classe esterna. La classe generata rimane piccola e può essere utilizzata facilmente da altri .LinedEditText
estendeEditText
, che è la visualizzazione da personalizzare in questo caso. Al termine, il nuovo corso può sostituire un normaleEditText
vista. -
Inizializzazione dei corsi
Come sempre, la super è la prima chiamata. Questo non è un costruttore predefinito, ma è un con parametri. Il parametro
EditText
viene creato con questi parametri quando da un file di layout XML. Il costruttore deve quindi prenderli e trasmetterli anche il costruttore della superclasse. -
Metodi sostituiti
In questo esempio viene eseguito solo l'override del metodo
onDraw()
, ma potrebbe essere necessario eseguire l'override altri quando crei i tuoi componenti personalizzati.Per questo esempio, se esegui l'override del metodo
onDraw()
puoi colorare le linee blu nel canvas della vistaEditText
. Il canvas viene trasferito nell'istanzaonDraw()
. Il metodosuper.onDraw()
viene chiamato prima di viene terminato. Il metodo della superclasse deve essere richiamato. In questo caso, richiamalo alla fine dopo dipingi le linee che vuoi includere. -
Componente personalizzato
Ora hai un componente personalizzato, ma come puoi utilizzarlo? Nell'esempio del Blocco note, componente personalizzato viene utilizzato direttamente dal layout dichiarativo, quindi guarda
note_editor.xml
inres/layout
cartella:<view xmlns:android="http://schemas.android.com/apk/res/android" class="com.example.android.notepad.NoteEditor$LinedEditText" android:id="@+id/note" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent" android:padding="5dp" android:scrollbars="vertical" android:fadingEdge="vertical" android:gravity="top" android:textSize="22sp" android:capitalize="sentences" />
Il componente personalizzato viene creato come visualizzazione generica nel file XML e la classe viene specificata utilizzando il pacchetto completo. Alla classe interna che definisci viene fatto riferimento utilizzando
NoteEditor$LinedEditText
, che è un modo standard per fare riferimento alla definizione nel linguaggio di programmazione Java.Se il componente di visualizzazione personalizzata non è definito come una classe interna, puoi dichiarare la vista con il nome dell'elemento XML ed escludi l'attributo
class
. Per esempio:<com.example.android.notepad.LinedEditText id="@+id/note" ... />
Nota che ora il corso
LinedEditText
è un file di classe separato. Quando è nidificata nella classeNoteEditor
, questa tecnica non funziona.Gli altri attributi e parametri nella definizione sono quelli trasferiti all'account di servizio personalizzato costruttore del componente e quindi passata al costruttore
EditText
, sono gli stessi parametri che utilizzi per una vistaEditText
. È possibile aggiungere i tuoi parametri.
Creare componenti personalizzati è complicato solo se necessario.
Un componente più sofisticato può sostituire ancora più metodi on
e introdurre i suoi
proprio metodi helper, personalizzando sostanzialmente le sue proprietà e il suo comportamento. L'unico limite è
l'immaginazione e cosa deve fare il componente.