Memahami konsep Canvas dan Surface

114

Saya berjuang untuk memahami proses menggambar SurfaceViewdan karenanya seluruh Surface/ Canvas/ Bitmapsistem, yang digunakan di Android.

Saya telah membaca semua artikel dan halaman dokumentasi API, yang dapat saya temukan di situs pengembang android, beberapa tutorial grafis android, kode sumber LunarLander dan pertanyaan ini .

Tolong beritahu saya, mana dari pernyataan ini yang benar, mana yang tidak, dan mengapa.

  1. Canvasmemiliki Bitmapketerikatannya sendiri padanya. Surfacememiliki Canvasketerikatannya sendiri padanya.
  2. Semua Viewjendela berbagi sama Surfacedan karenanya berbagi sama Canvas.
  3. SurfaceViewadalah subkelas View, yang, tidak seperti Viewsubkelas lain dan subkelas Viewitu sendiri, memiliki kelebihan tersendiri Surface.

Ada juga satu pertanyaan tambahan:

  • Mengapa ada kebutuhan untuk Surfacekelas, jika sudah ada Canvasuntuk operasi tingkat tinggi dengan bitmap. Berikan contoh situasi di mana Canvastidak cocok untuk melakukan pekerjaan yang Surfacebisa dilakukan.
fyodorananiev.dll
sumber
2
Dokumen
fadden

Jawaban:

223

Berikut beberapa definisi:

  • Surface adalah objek yang menahan piksel yang sedang digabungkan ke layar. Setiap jendela yang Anda lihat di layar (dialog, aktivitas layar penuh Anda, status bar) memiliki permukaannya sendiri yang menariknya, dan Surface Flinger menampilkannya ke tampilan akhir dalam urutan Z yang benar. Permukaan biasanya memiliki lebih dari satu buffer (biasanya dua) untuk melakukan rendering buffer ganda: aplikasi dapat menggambar status UI berikutnya sementara flinger permukaan menyusun layar menggunakan buffer terakhir, tanpa perlu menunggu aplikasi selesai gambar.

  • Jendela pada dasarnya seperti yang Anda pikirkan tentang jendela di desktop. Ini memiliki permukaan tunggal di mana konten jendela ditampilkan. Sebuah aplikasi berinteraksi dengan Manajer Jendela untuk membuat jendela; Manajer Jendela membuat Permukaan untuk setiap jendela dan memberikannya ke aplikasi untuk menggambar. Aplikasi dapat menggambar apa pun yang diinginkannya di Surface; bagi Pengelola Jendela, ini hanyalah persegi panjang buram.

  • Tampilan adalah elemen UI interaktif di dalam jendela. Jendela memiliki hierarki tampilan tunggal yang menyertainya, yang menyediakan semua perilaku jendela. Kapan pun jendela perlu digambar ulang (seperti karena tampilan telah menjadi tidak valid sendiri), ini dilakukan ke dalam Surface jendela. Surface dikunci, yang mengembalikan Canvas yang dapat digunakan untuk menggambar ke dalamnya. Draw traversal dilakukan di bawah hierarki, menurunkan Canvas untuk setiap tampilan guna menggambar bagian UI-nya. Setelah selesai, Surface dibuka kuncinya dan diposting sehingga buffer yang baru saja ditarik ditukar ke latar depan untuk kemudian digabungkan ke layar oleh Surface Flinger.

  • SurfaceView adalah implementasi khusus View yang juga membuat Surface khusus untuk digambar langsung oleh aplikasi (di luar hierarki tampilan normal, yang sebaliknya harus berbagi satu Surface untuk jendela). Cara kerjanya lebih sederhana dari yang Anda perkirakan - semua yang dilakukan SurfaceView adalah meminta pengelola jendela untuk membuat jendela baru, memberitahukannya ke Z-order jendela tersebut tepat di belakang atau di depan jendela SurfaceView, dan memposisikannya agar sesuai di mana SurfaceView muncul di jendela penampung. Jika permukaan ditempatkan di belakang jendela utama (dalam urutan Z), SurfaceView juga mengisi bagian jendela utama dengan transparansi sehingga permukaan tersebut dapat terlihat.

  • Bitmap hanyalah antarmuka ke beberapa data piksel. Piksel dapat dialokasikan oleh Bitmap itu sendiri saat Anda membuatnya secara langsung, atau mungkin mengarah ke piksel yang tidak dimilikinya seperti yang secara internal terjadi saat mengaitkan Canvas ke Surface untuk menggambar. (Bitmap dibuat dan diarahkan ke buffer gambar Surface saat ini.)

Juga harap diingat bahwa, karena ini menyiratkan, SurfaceView adalah objek yang cukup berat. Jika Anda memiliki beberapa SurfaceView dalam UI tertentu, berhenti sejenak dan pikirkan apakah ini benar-benar diperlukan. Jika Anda memiliki lebih dari dua, Anda hampir pasti memiliki terlalu banyak.

hackbod
sumber
Terima kasih banyak! Jawaban membuat segalanya lebih jelas. Bagian tentang menghubungkan Canvas ke Surface tidak jelas. Tidak bisa membayangkan di mana operasi semacam itu dibutuhkan. Bisakah selanjutnya menjadi contoh operasi itu: menggambar Bitmap di atas Kanvas, diperoleh dari SurfaceHolder dengan metode lockCanvas ()?
fyodorananiev
1
Begitulah cara menggambar. Kanvas adalah API gambar 2d. Jika Anda akan menggambar o ke permukaan, Anda perlu membuat Canvas yang mengarah ke buffernya untuk menggunakan API gambar Canvas 2d untuk menggambarnya.
hackbod
6
Selain #hackbod'smenjawab, SurfaceViewjuga dapat diberikan dari utas sekunder yang tidak mungkin untuk Viewobjek
Mohanraj Balasubramaniam
47

Tinjauan konseptual Window, Surface, Canvas, dan Bitmap

Berikut adalah gambaran umum konseptual yang sangat mendasar dan sederhana tentang bagaimana interaksi terjadi antara Window, Surface, Canvas, dan Bitmap.
Kadang-kadang, representasi visual banyak membantu dalam memahami konsep-konsep yang menyimpang.
Saya harap grafik ini dapat membantu seseorang.

Sabeeh
sumber
4
Gambar Visual lebih baik daripada teks: D
Maveň ツ
18

Bitmap hanyalah pembungkus untuk kumpulan piksel. Anggap saja sebagai array piksel dengan beberapa fungsi praktis lainnya.

Canvas adalah kelas yang berisi semua metode menggambar. Ini mirip dengan kelas Grafik di AWT / Swing jika Anda sudah terbiasa dengannya. Semua logika tentang cara menggambar lingkaran, atau kotak, dll ada di dalam kanvas. Kanvas menggambar pada Bitmap atau wadah GL terbuka tetapi tidak ada alasan mengapa di masa depan kanvas dapat diperluas untuk digambar ke jenis raster lain.

SurfaceView adalah Tampilan yang berisi Surface. Sebuah permukaan mirip dengan bitmap (memiliki penyimpanan piksel). Saya tidak tahu bagaimana penerapannya tetapi saya membayangkan itu adalah semacam pembungkus Bitmap dengan metode tambahan untuk hal-hal yang berhubungan langsung dengan tampilan layar (Itulah alasan untuk sebuah permukaan, Bitmap terlalu umum). Anda bisa mendapatkan Canvas dari Surface Anda yang benar-benar mendapatkan Canvas yang terkait dengan Bitmap yang mendasarinya.

Pertanyaan Anda.

1. Canvas memiliki Bitmap sendiri yang menyertainya. Surface memiliki kanvasnya sendiri yang melekat padanya.

Ya, kanvas beroperasi pada Bitmap (atau panel GL terbuka). Surface memberi Anda Canvas yang beroperasi pada apa pun yang digunakan Surface untuk penyimpanan piksel gaya Bitmap-nya.

2. Semua Tampilan jendela berbagi Permukaan yang sama dan dengan demikian berbagi Kanvas yang sama.

Tidak. Anda dapat memiliki tampilan permukaan sebanyak yang Anda inginkan.

3.SurfaceView adalah subkelas View, yang, tidak seperti subkelas View lain dan View itu sendiri, memiliki Surface sendiri untuk digambar.

Iya. Sama seperti ListView adalah subclass View yang memiliki struktur data List sendiri. Setiap subclass View melakukan sesuatu yang berbeda.

sksamuel.dll
sumber
1
Jadi, Bitmapdan Surfaceapakah hanya spesies berbeda dari penyimpanan piksel dan Canvasdapat membungkus salah satunya?
fyodorananiev
2
Pada dasarnya ya. Kecuali Canvas tidak dapat menulis ke permukaan, ia beroperasi pada apa pun yang digunakan Surface sebagai penyimpanan pikselnya sendiri (tanpa melihat sumber android saya tidak dapat mengatakan dengan pasti apa itu). Ini mungkin semacam ekstensi Bitmap karena Canvas hanya menyediakan konstruktor untuk Bitmap dan GL.
sksamuel
Sangat membantu, terima kasih! Tentang jawaban 2. Dalam pertanyaan saya, yang saya maksud adalah tampilan standar, bukan SurfaceViews. Misalkan saya memiliki RelativeLayout dengan banyak bidang dan tombol. Dalam kasus ini, apakah Surface terpasang ke seluruh jendela dan dibagikan oleh semua Tampilan dalam hierarki tampilan?
fyodorananiev
1
Ingat Surface hanyalah kumpulan piksel. Jadi, setiap tampilan permukaan memiliki permukaannya sendiri dan masing-masing dapat ditampilkan di bagian layar yang berbeda. Mereka tidak perlu mengisi layar (meskipun itu adalah penggunaan umum, untuk membuat grafik pada game layar penuh).
sksamuel
1
Saya benar-benar tidak akan menganggap Bitmap dan Surface setara. Surface adalah objek yang diketahui oleh penyusun permukaan, pembuat jendela. Artinya, ini adalah sesuatu yang langsung terlihat di layar, memiliki urutan Z di layar, dll.
hackbod