Comprensione dei concetti di Canvas e Surface


114

Faccio fatica a capire il processo di disegno SurfaceViewe quindi l'intero sistema Surface/ Canvas/ Bitmap, che viene utilizzato in Android.

Ho letto tutti gli articoli e le pagine di documentazione delle API, che sono riuscito a trovare sul sito degli sviluppatori Android, alcuni tutorial sulla grafica Android, il codice sorgente di LunarLander e questa domanda .

Per favore dimmi quali di queste affermazioni sono vere, quali non lo sono e perché.

  1. Canvasha il suo Bitmapallegato ad esso. Surfaceha il suo Canvasallegato ad esso.
  2. Tutte Viewle finestre condividono lo stesso Surfacee quindi condividono lo stesso Canvas.
  3. SurfaceViewè una sottoclasse di View, che, a differenza delle altre Viewsottoclassi e di Viewse stessa, ha le sue proprie Surfacea cui attirare.

C'è anche un'altra domanda:

  • Perché c'è bisogno di una Surfaceclasse, se esiste già una Canvasper operazioni di alto livello con bitmap. Fornisci un esempio di una situazione in cui Canvasnon è adatto per fare un lavoro che Surfacepuò fare.

Risposte:


223

Ecco alcune definizioni:

  • Una superficie è un oggetto che contiene pixel che vengono composti sullo schermo. Ogni finestra che vedi sullo schermo (una finestra di dialogo, la tua attività a schermo intero, la barra di stato) ha la sua superficie a cui attinge e Surface Flinger le restituisce alla visualizzazione finale nel loro corretto ordine Z. Una superficie in genere ha più di un buffer (di solito due) per eseguire il rendering a doppio buffer: l'applicazione può disegnare il suo successivo stato dell'interfaccia utente mentre il flinger di superficie sta componendo lo schermo utilizzando l'ultimo buffer, senza dover attendere che l'applicazione termini disegno.

  • Una finestra è fondamentalmente come pensi a una finestra sul desktop. Ha un'unica superficie in cui viene eseguito il rendering del contenuto della finestra. Un'applicazione interagisce con il Window Manager per creare finestre; il Window Manager crea una Superficie per ogni finestra e la consegna all'applicazione per il disegno. L'applicazione può disegnare quello che vuole in Surface; per il Window Manager è solo un rettangolo opaco.

  • Una vista è un elemento dell'interfaccia utente interattiva all'interno di una finestra. A una finestra è collegata una singola gerarchia di visualizzazione, che fornisce tutto il comportamento della finestra. Ogni volta che la finestra deve essere ridisegnata (ad esempio perché una vista si è invalidata), questo viene fatto nella superficie della finestra. La superficie è bloccata, il che restituisce una tela che può essere utilizzata per disegnare al suo interno. Viene eseguito un percorso di disegno lungo la gerarchia, consegnando il Canvas a ciascuna vista per disegnare la sua parte dell'interfaccia utente. Una volta terminato, Surface viene sbloccato e pubblicato in modo che il buffer appena disegnato venga spostato in primo piano per essere quindi composto sullo schermo da Surface Flinger.

  • Un SurfaceView è un'implementazione speciale di View che crea anche una propria Surface dedicata in cui l'applicazione può disegnare direttamente (al di fuori della normale gerarchia di visualizzazione, che altrimenti deve condividere la singola Surface per la finestra). Il modo in cui funziona è più semplice di quanto ci si potrebbe aspettare: tutto ciò che SurfaceView fa è chiedere al gestore delle finestre di creare una nuova finestra, dicendogli di ordinare a Z quella finestra immediatamente dietro o davanti alla finestra di SurfaceView e posizionarla in modo che corrisponda dove viene visualizzato SurfaceView nella finestra contenitore. Se la superficie viene posizionata dietro la finestra principale (in ordine Z), SurfaceView riempie anche la sua parte della finestra principale con trasparenza in modo che la superficie possa essere vista.

  • Una bitmap è solo un'interfaccia per alcuni dati pixel. I pixel possono essere allocati dalla Bitmap stessa quando ne stai creando uno direttamente, oppure potrebbe puntare a pixel che non possiede, come quello che accade internamente per collegare una tela a una superficie per il disegno. (Viene creata una bitmap che punta al buffer di disegno corrente della superficie.)

Inoltre, tieni presente che, come questo implica, un SurfaceView è un oggetto piuttosto pesante. Se hai più SurfaceView in una particolare interfaccia utente, fermati e pensa se è davvero necessario. Se ne hai più di due, quasi sicuramente ne hai troppi.


Grazie mille! La risposta ha reso le cose più chiare. Tuttavia, parte dell'aggancio di Canvas a Surface non è chiara. Non riesco a immaginare dove sia necessaria tale operazione. Può essere il prossimo esempio di tale operazione: disegnare Bitmap su una tela, acquisita da SurfaceHolder con il metodo lockCanvas ()?
fyodorananiev

1
Ecco come avviene il disegno Canvas è l'API di disegno 2d. Se stai per disegnare su una superficie, devi creare una tela che punti al suo buffer per utilizzare l'API di disegno di Canvas 2d per disegnare su di essa.
hackbod

6
Oltre alla #hackbod'srisposta, SurfaceViewpuò anche essere reso dal thread secondario che non è possibile per gli Viewoggetti
Mohanraj Balasubramaniam

47

Una panoramica concettuale di Window, Surface, Canvas e Bitmap

Ecco una panoramica concettuale molto semplice e di base di come avviene l'interazione tra Finestra, Superficie, Tela e Bitmap.
A volte, una rappresentazione visiva aiuta molto nella comprensione di concetti contorti.
Spero che questa grafica possa aiutare qualcuno.


4
Visivamente Le immagini sono migliori del testo: D
Maveň ツ

18

Una bitmap è semplicemente un wrapper per una raccolta di pixel. Consideralo come un array di pixel con alcune altre utili funzioni.

Il Canvas è semplicemente la classe che contiene tutti i metodi di disegno. È simile alla classe Graphics in AWT / Swing, se lo conosci. Tutta la logica su come disegnare un cerchio, o una scatola, ecc. È contenuta all'interno di Canvas. Una tela disegna su una bitmap o un contenitore GL aperto, ma non c'è motivo per cui in futuro potrebbe essere estesa per disegnare su altri tipi di raster.

SurfaceView è una vista che contiene una superficie. Una superficie è simile a una bitmap (ha un archivio di pixel). Non so come sia implementato, ma immagino che sia una sorta di wrapper bitmap con metodi extra per cose che sono direttamente correlate alle visualizzazioni dello schermo (questo è il motivo per una superficie, una bitmap è troppo generica). Puoi ottenere una tela dalla tua superficie che sta effettivamente ottenendo la tela associata alla bitmap sottostante.

Le tue domande.

1.Canvas ha la propria Bitmap allegata. A Surface è collegata la propria tela.

Sì, una tela opera su una bitmap (o un pannello GL aperto). Surface offre una tela che funziona su qualsiasi superficie utilizzata per il suo archivio di pixel in stile bitmap.

2.Tutte le viste della finestra condividono la stessa superficie e quindi condividono la stessa tela.

No. Puoi avere tutte le viste superficiali che desideri.

3.SurfaceView è una sottoclasse di View, che, a differenza delle altre sottoclassi di View e della View stessa, ha la propria superficie in cui disegnare.

Sì. Proprio come ListView è una sottoclasse di View che ha la propria struttura dati List. Ogni sottoclasse di View fa qualcosa di diverso.


1
Quindi, Bitmape Surfacesono solo diverse specie di pixel store e Canvaspossono avvolgere uno di loro?
fyodorananiev

2
Fondamentalmente sì. Tranne che Canvas non può scrivere su una superficie, funziona su qualsiasi Surface stia utilizzando come proprio archivio di pixel (senza guardare la fonte Android non posso dire con certezza di cosa si tratta). Probabilmente è una sorta di estensione Bitmap poiché Canvas fornisce solo costruttori per Bitmap e GL.
sksamuel

Grande aiuto, grazie! Informazioni sulla risposta 2. Nella mia domanda intendevo visualizzazioni standard, non SurfaceViews. Supponiamo di avere RelativeLayout con molti campi e pulsanti. In questo caso, Surface è collegato all'intera finestra e condiviso da tutte le viste nella gerarchia delle viste?
fyodorananiev

1
Ricorda che Surface è solo una raccolta di pixel. Quindi ogni vista di superficie ha la sua superficie e ognuna può essere renderizzata su una parte diversa dello schermo. Non è necessario che riempiano lo schermo (sebbene questo sia l'uso comune, per il rendering della grafica su un gioco a schermo intero).
sksamuel

1
Non penserei davvero a Bitmap e Surface come equivalenti. Una superficie è un oggetto che surface flinger, il compositore di finestre, conosce. Cioè, è qualcosa direttamente visibile sullo schermo, ha un ordine Z sullo schermo, ecc.
hackbod
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.