Понимание концепций Canvas и Surface
Я изо всех сил пытаюсь понять процесс рисования SurfaceView
и, следовательно, весь Surface
/Canvas
/Bitmap
система, которая используется в Android.
Я прочитал все статьи и страницы документации API, которые я смог найти на сайте разработчиков Android, несколько учебных пособий по графике Android, исходный код LunarLander и этот вопрос.
Скажите, пожалуйста, какие из этих утверждений верны, а какие нет, и почему.
Canvas
имеет свойBitmap
прикреплен к нему.Surface
имеет свойCanvas
прикреплен к нему.- Все
View
Окна делят то же самоеSurface
и таким образом делить то же самоеCanvas
, SurfaceView
это подклассView
, который, в отличие от другихView
подклассы иView
сам по себе, имеет свойSurface
рисовать.
Есть еще один дополнительный вопрос:
- Почему существует необходимость
Surface
класс, если уже естьCanvas
для высокоуровневых операций с растровым изображением. Приведите пример ситуации, когдаCanvas
не подходит для выполнения работы, котораяSurface
сможет сделать.
3 ответа
Вот несколько определений:
Поверхность - это объект, содержащий пиксели, которые компонуются на экране. Каждое окно, которое вы видите на экране (диалоговое окно, ваша полноэкранная активность, строка состояния), имеет свою собственную поверхность, к которой оно обращается, и Surface Flinger отображает их на конечном экране в правильном Z-порядке. Поверхность, как правило, имеет более одного буфера (обычно два) для рендеринга с двойной буферизацией: приложение может рисовать свое следующее состояние пользовательского интерфейса, в то время как бегунок поверхности создает экран, используя последний буфер, без необходимости ждать завершения приложения. Рисунок.
Окно в основном похоже на окно на рабочем столе. Он имеет единственную поверхность, в которой отображается содержимое окна. Приложение взаимодействует с диспетчером окон для создания окон; Менеджер окон создает поверхность для каждого окна и передает ее приложению для рисования. Приложение может рисовать все что угодно в Surface; для оконного менеджера это просто непрозрачный прямоугольник.
Вид - это интерактивный элемент пользовательского интерфейса внутри окна. К окну прикреплена единая иерархия представления, которая обеспечивает все поведение окна. Всякий раз, когда окно необходимо перерисовать (например, из-за того, что представление аннулировало себя), это делается в Поверхность окна. Поверхность заблокирована, что возвращает холст, который можно использовать для рисования в нем. Обход рисования выполняется по иерархии, передавая холст для каждого представления, чтобы нарисовать свою часть пользовательского интерфейса. После этого Поверхность разблокируется и размещается так, что только что нарисованный буфер переключается на передний план, чтобы затем скомпоновать его с экраном с помощью Surface Flinger.
SurfaceView - это специальная реализация View, которая также создает свою собственную выделенную поверхность для прямого рисования приложения (вне обычной иерархии представления, которая в противном случае должна совместно использовать одну поверхность для окна). Это работает проще, чем вы можете ожидать - все, что делает SurfaceView, - это просит оконный менеджер создать новое окно, сообщая ему Z-порядок того окна непосредственно позади или перед окном SurfaceView, и располагая его так, чтобы оно соответствовало где SurfaceView появляется в содержащем окне. Если поверхность размещается за главным окном (в Z-порядке), SurfaceView также заполняет свою часть главного окна прозрачностью, чтобы поверхность можно было видеть.
Растровое изображение - это просто интерфейс для некоторых пиксельных данных. Пиксели могут быть выделены самим растровым изображением, когда вы его непосредственно создаете, или оно может указывать на пиксели, которые ему не принадлежат, например, что происходит внутри с подключением Canvas к Surface для рисования. (Растровое изображение создается и указывает на текущий буфер рисования поверхности.)
Также имейте в виду, что, как это и подразумевается, SurfaceView является довольно тяжелым объектом. Если у вас есть несколько SurfaceViews в конкретном интерфейсе, остановитесь и подумайте, действительно ли это необходимо. Если у вас больше двух, у вас почти наверняка слишком много.
Вот очень простой и простой концептуальный обзор того, как происходит взаимодействие между Окном, Поверхностью, Холстом и Растровым изображением.
Иногда визуальное представление очень помогает в понимании искаженных концепций.
Я надеюсь, что этот рисунок может кому-то помочь.
Растровое изображение - это просто оболочка для коллекции пикселей. Думайте об этом как о массиве пикселей с некоторыми другими удобными функциями.
Canvas - это просто класс, содержащий все методы рисования. Он похож на класс Graphics в AWT/Swing, если вы знакомы с этим. Вся логика о том, как нарисовать круг, или прямоугольник, и т. Д. Содержится внутри Canvas. Холст рисует на растровом изображении или в открытом контейнере GL, но нет никаких причин, по которым в будущем он может быть расширен для рисования на другие типы растров.
SurfaceView - это представление, которое содержит поверхность. Поверхность похожа на растровое изображение (в ней хранится пиксель). Я не знаю, как это реализовано, но я представляю, что это своего рода обертка для растровых изображений с дополнительными методами для вещей, которые непосредственно связаны с отображением на экране (по этой причине поверхность является слишком общей). Вы можете получить Canvas из вашей Surface, который действительно связывает Canvas с базовым растровым изображением.
Ваши вопросы.
1. Канва имеет свой собственный растровое изображение, прикрепленное к нему. Поверхность имеет свой собственный холст, прикрепленный к нему.
Да, холст работает на растровом изображении (или на открытой панели GL). Поверхность дает вам Canvas, который работает с тем, что Surface использует для своего пиксельного хранилища в стиле Bitmap.
2.Все окна имеют одну и ту же поверхность и, следовательно, один и тот же холст.
Нет. Вы можете иметь столько поверхностей, сколько захотите.
3.SurfaceView - это подкласс View, который, в отличие от других подклассов View и самого View, имеет свою собственную поверхность для рисования.
Да. Так же, как ListView является подклассом View, который имеет свою собственную структуру данных List. Каждый подкласс View делает что-то свое.