Работа с графической подсистемой
Олег Годовых
Поддерживаемые форматы
JPEG (без цветовых пространств)
PNG
GIF (только чтение, без анимации)
BMP (только чтение)
А мой любимый *назови формат по вкусу*?
2 Работа с графической подсистемой
Поддерживаемые форматы
Есть разные библиотеки
Есть C++ и NDK
Есть спецификации форматов
3 Работа с графической подсистемой
Как отображать
ImageView
Любому View можно назначить фон (android:background).
Можно загрузить во встроенный браузер (WebView).
Можно отрисовывать через OpenGL и SurfaceView.
Всегда можно отрисовывать вручную через Canvas.
4 Работа с графической подсистемой
Класс Bitmap
Представление картинки в памяти.
Может быть mutable и immutable.
Создаётся или напрямую статическим методом
createBitmap, или при чтении из источника данных (файл,
поток, ресурс и т. д.) статическими методами класса
BitmapFactory
До Android API 11 (Android 3.0+) нельзя было считать
картинку в mutable bitmap. Печалька
5 Работа с графической подсистемой
Класс Bitmap
Можно узнать размеры изображения.
Можно скопировать/отмасштабировать изображение.
Можно закрасить пиксель/всё изображение/часть
изображения.
Можно хапнуть горя с памятью.
6 Работа с графической подсистемой
Класс Bitmap
Память под Bitmap выделяется 2 кусками:
До Android 3.0:
Метаданные и прочая Java-обёртка
Собственно данные о пикселях в нативной куче (которой
Dalvik VM не управляет).
С Android 3.0:
Всё лежит в Dalvik heap.
7 Работа с графической подсистемой
Класс Bitmap
Занимает в памяти 4 * width * height
Можно использовать RGB-565 и лишиться прозрачности
Можно использовать ARGB-4444, который давно
deprecated, и картинка не будет радовать цветами.
Dalvik VM не дефрагментирует память, поэтому даже если
в куче хватает места, OutOfMemoryError следит за вами.
8 Работа с графической подсистемой
Класс Bitmap
Bitmap освобождает память в 2 случаях:
при сборке мусора и вызове finalize()
при явном вызове метода recycle()
После вызова recycle() картинка не может быть
использована — выбрасывается исключение.
В новых версиях не рекомендуется использовать recycle()
9 Работа с графической подсистемой
Класс Bitmap
Делаем recycle(), как только картинка становится не нужна.
Если нужно много изображений — выделяем память при
старте приложения, создаём пул картинок.
При создании через BitmapFactory ставим нужные флаги в
BitmapFactory .Options.
Bitmap bitmap = BitmapFactory.decodeFile(new File("sample.png"));
10 Работа с графической подсистемой
Класс Bitmap
Делаем recycle(), как только картинка становится не нужна.
Если нужно много изображений — выделяем память при
старте приложения, создаём пул картинок.
При создании через BitmapFactory ставим нужные флаги в
BitmapFactory .Options.
Bitmap bitmap = BitmapFactory.decodeFile(new File("sample.png"));
Проверить размер картинки
(BitmapOptions.inJustDecodeBounds)
Открыть картинку сразу с масштабированием.
Пробовать ловить OutOfMemoryError и в случае нехватки
памяти грузить картинку с другой цветовой палитрой или
ещё уменьшить размер.
11 Работа с графической подсистемой
Класс Drawable
Класс-обёртка для различных видов изображений. Может
содержать внутри:
Bitmap
Геометрическую фигуру с закраской
9-patch изображение
Анимацию
Несколько слоёв
Комбинацию разных Drawable
И кучу всего ещё (читайте про android.graphics.drawable)
12 Работа с графической подсистемой
Класс Drawable
BitmapDrawable создаётся «вокруг» обычного Bitmap.
Он создаётся неявно, когда мы ставим картинку в
ImageView через задание android:src.
Мы получаем весь тот же набор проблем с памятью.
Можно достать картинку через getBitmap() и удалить как
раньше.
Обязательно не забудьте установить перед удалением
callback для Drawable в null для сборки памяти (по
умолчанию ставится на вьюху-родитель).
13 Работа с графической подсистемой
Класс ImageView
Мы можем задать, как масштабировать изображение.
Можем применить матрицу преобразования, обрезать или
сжать/растянуть в зависимости от размеров.
Подробнее о том, как что преобразуется — здесь:
http://etcodehome.blogspot.com/2011/05/
android-imageview-scaletype-samples.html.
14 Работа с графической подсистемой
9-patch
Когда у нас есть кнопка/поле ввода/любой другой элемент, у
которого мы не знаем размер отображаемых данных — как
ставить фон?
Можем растянуть, но тогда будет некрасиво или появятся
артефакты по углам.
Можем замостить узором, но не всегда это приемлемо
15 Работа с графической подсистемой
9-patch
16 Работа с графической подсистемой
Ресурсы
Папкам для drawable мы можем ставить квалификаторы
по разрешению (-*dpi)
по размеру (-small, -normal, -large, -xlarge)
Комбинируя эти квалификаторы, можно сделать абсолютно
разный набор графики для телефонов и планшетов.
Если одна и та же картинка совпадает для разных размеров
экрана, кладём её в drawable-nodpi, а в соответствующих
папках ставим на неё ссылку через xml:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android=http://schemas.android.com/apk/res/android
android:src="@drawable/im_bkg_help_control_normal" />
17 Работа с графической подсистемой
State drawables
У кнопки есть несколько состояний: обычное, нажатое,
выделенное.
Возможно, понадобится отображать её разным цветом в
зависимости от ситуации.
Придётся вешать обработчики на все события и менять
фон/изображение?
18 Работа с графической подсистемой
State drawables
Нас спасёт State Drawable!
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/button_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/button_default"/>
</selector>
Такой же трюк можно провернуть с цветами, установив их для
текста.
19 Работа с графической подсистемой
Shape drawables
Простые графические примитивы не обязательно рисовать
руками в любимом фотошопе. Можно их задать через Shape
Drawable в xml.
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dip" />
<gradient
android:angle="270"
android:type="linear"
android:startColor="#000000"
android:endColor="#ffffff"/>
</shape>
20 Работа с графической подсистемой
Canvas
Наследуемся от View, переопределяем onDraw().
Можем рисовать геометрические примитивы напрямую
руками.
Не стоит забывать о буферизации и не делать слишком
часто перерисовку (быстрее 60 кадров в секунду не будет,
а вот батарею скушать можно бодро).
21 Работа с графической подсистемой
Canvas
.moveTo(), .lineTo() — и мы рисуем линии.
Используем класс Path, если нам надо нарисовать
сложную ломаную или много примитивов, тогда отрисовка
будет проходить быстрее.
Класс Picture позволяет кэшировать запросы к Canvas
(отрисовали раз, потом из него воспроизводим гораздо
быстрее) — но он не работает при аппаратном ускорении.
Класс Paint — настройки кисти. Не создавайте лишний раз,
иногда лучше создать статический объект или поле
экземпляра.
22 Работа с графической подсистемой
Canvas
Можно нарисовать тот же Bitmap.
Можно написать текст.
Можно «изогнуть» текст вдоль кривой или ломаной.
Можно применять матрицы преобразований.
Можно сохранять и восстанавливать матрицу — OpenGL
для бедных.
23 Работа с графической подсистемой
Загрузка из сети
https://github.com/nostra13/
Android-Universal-Image-Loader
http://square.github.io/picasso
В составе некоторых сетевых библиотек есть свои
загрузчики картинок (в Volley точно есть).
Есть в составе комбинированных библиотек (AQuery)
В конце концов, можно поставить URL в ImageView
(.setImageUrl())
24 Работа с графической подсистемой
Полезные ссылки
http://developer.android.com/guide/topics/
graphics/2d-graphics.html
http://developer.android.com/training/
displaying-bitmaps/index.html
http://androiddrawables.com
25 Работа с графической подсистемой

Android - 10 - Graphics

  • 1.
    Работа с графическойподсистемой Олег Годовых
  • 2.
    Поддерживаемые форматы JPEG (безцветовых пространств) PNG GIF (только чтение, без анимации) BMP (только чтение) А мой любимый *назови формат по вкусу*? 2 Работа с графической подсистемой
  • 3.
    Поддерживаемые форматы Есть разныебиблиотеки Есть C++ и NDK Есть спецификации форматов 3 Работа с графической подсистемой
  • 4.
    Как отображать ImageView Любому Viewможно назначить фон (android:background). Можно загрузить во встроенный браузер (WebView). Можно отрисовывать через OpenGL и SurfaceView. Всегда можно отрисовывать вручную через Canvas. 4 Работа с графической подсистемой
  • 5.
    Класс Bitmap Представление картинкив памяти. Может быть mutable и immutable. Создаётся или напрямую статическим методом createBitmap, или при чтении из источника данных (файл, поток, ресурс и т. д.) статическими методами класса BitmapFactory До Android API 11 (Android 3.0+) нельзя было считать картинку в mutable bitmap. Печалька 5 Работа с графической подсистемой
  • 6.
    Класс Bitmap Можно узнатьразмеры изображения. Можно скопировать/отмасштабировать изображение. Можно закрасить пиксель/всё изображение/часть изображения. Можно хапнуть горя с памятью. 6 Работа с графической подсистемой
  • 7.
    Класс Bitmap Память подBitmap выделяется 2 кусками: До Android 3.0: Метаданные и прочая Java-обёртка Собственно данные о пикселях в нативной куче (которой Dalvik VM не управляет). С Android 3.0: Всё лежит в Dalvik heap. 7 Работа с графической подсистемой
  • 8.
    Класс Bitmap Занимает впамяти 4 * width * height Можно использовать RGB-565 и лишиться прозрачности Можно использовать ARGB-4444, который давно deprecated, и картинка не будет радовать цветами. Dalvik VM не дефрагментирует память, поэтому даже если в куче хватает места, OutOfMemoryError следит за вами. 8 Работа с графической подсистемой
  • 9.
    Класс Bitmap Bitmap освобождаетпамять в 2 случаях: при сборке мусора и вызове finalize() при явном вызове метода recycle() После вызова recycle() картинка не может быть использована — выбрасывается исключение. В новых версиях не рекомендуется использовать recycle() 9 Работа с графической подсистемой
  • 10.
    Класс Bitmap Делаем recycle(),как только картинка становится не нужна. Если нужно много изображений — выделяем память при старте приложения, создаём пул картинок. При создании через BitmapFactory ставим нужные флаги в BitmapFactory .Options. Bitmap bitmap = BitmapFactory.decodeFile(new File("sample.png")); 10 Работа с графической подсистемой
  • 11.
    Класс Bitmap Делаем recycle(),как только картинка становится не нужна. Если нужно много изображений — выделяем память при старте приложения, создаём пул картинок. При создании через BitmapFactory ставим нужные флаги в BitmapFactory .Options. Bitmap bitmap = BitmapFactory.decodeFile(new File("sample.png")); Проверить размер картинки (BitmapOptions.inJustDecodeBounds) Открыть картинку сразу с масштабированием. Пробовать ловить OutOfMemoryError и в случае нехватки памяти грузить картинку с другой цветовой палитрой или ещё уменьшить размер. 11 Работа с графической подсистемой
  • 12.
    Класс Drawable Класс-обёртка дляразличных видов изображений. Может содержать внутри: Bitmap Геометрическую фигуру с закраской 9-patch изображение Анимацию Несколько слоёв Комбинацию разных Drawable И кучу всего ещё (читайте про android.graphics.drawable) 12 Работа с графической подсистемой
  • 13.
    Класс Drawable BitmapDrawable создаётся«вокруг» обычного Bitmap. Он создаётся неявно, когда мы ставим картинку в ImageView через задание android:src. Мы получаем весь тот же набор проблем с памятью. Можно достать картинку через getBitmap() и удалить как раньше. Обязательно не забудьте установить перед удалением callback для Drawable в null для сборки памяти (по умолчанию ставится на вьюху-родитель). 13 Работа с графической подсистемой
  • 14.
    Класс ImageView Мы можемзадать, как масштабировать изображение. Можем применить матрицу преобразования, обрезать или сжать/растянуть в зависимости от размеров. Подробнее о том, как что преобразуется — здесь: http://etcodehome.blogspot.com/2011/05/ android-imageview-scaletype-samples.html. 14 Работа с графической подсистемой
  • 15.
    9-patch Когда у насесть кнопка/поле ввода/любой другой элемент, у которого мы не знаем размер отображаемых данных — как ставить фон? Можем растянуть, но тогда будет некрасиво или появятся артефакты по углам. Можем замостить узором, но не всегда это приемлемо 15 Работа с графической подсистемой
  • 16.
    9-patch 16 Работа сграфической подсистемой
  • 17.
    Ресурсы Папкам для drawableмы можем ставить квалификаторы по разрешению (-*dpi) по размеру (-small, -normal, -large, -xlarge) Комбинируя эти квалификаторы, можно сделать абсолютно разный набор графики для телефонов и планшетов. Если одна и та же картинка совпадает для разных размеров экрана, кладём её в drawable-nodpi, а в соответствующих папках ставим на неё ссылку через xml: <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android=http://schemas.android.com/apk/res/android android:src="@drawable/im_bkg_help_control_normal" /> 17 Работа с графической подсистемой
  • 18.
    State drawables У кнопкиесть несколько состояний: обычное, нажатое, выделенное. Возможно, понадобится отображать её разным цветом в зависимости от ситуации. Придётся вешать обработчики на все события и менять фон/изображение? 18 Работа с графической подсистемой
  • 19.
    State drawables Нас спасётState Drawable! <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/button_pressed" android:state_pressed="true"/> <item android:drawable="@drawable/button_default"/> </selector> Такой же трюк можно провернуть с цветами, установив их для текста. 19 Работа с графической подсистемой
  • 20.
    Shape drawables Простые графическиепримитивы не обязательно рисовать руками в любимом фотошопе. Можно их задать через Shape Drawable в xml. <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="5dip" /> <gradient android:angle="270" android:type="linear" android:startColor="#000000" android:endColor="#ffffff"/> </shape> 20 Работа с графической подсистемой
  • 21.
    Canvas Наследуемся от View,переопределяем onDraw(). Можем рисовать геометрические примитивы напрямую руками. Не стоит забывать о буферизации и не делать слишком часто перерисовку (быстрее 60 кадров в секунду не будет, а вот батарею скушать можно бодро). 21 Работа с графической подсистемой
  • 22.
    Canvas .moveTo(), .lineTo() —и мы рисуем линии. Используем класс Path, если нам надо нарисовать сложную ломаную или много примитивов, тогда отрисовка будет проходить быстрее. Класс Picture позволяет кэшировать запросы к Canvas (отрисовали раз, потом из него воспроизводим гораздо быстрее) — но он не работает при аппаратном ускорении. Класс Paint — настройки кисти. Не создавайте лишний раз, иногда лучше создать статический объект или поле экземпляра. 22 Работа с графической подсистемой
  • 23.
    Canvas Можно нарисовать тотже Bitmap. Можно написать текст. Можно «изогнуть» текст вдоль кривой или ломаной. Можно применять матрицы преобразований. Можно сохранять и восстанавливать матрицу — OpenGL для бедных. 23 Работа с графической подсистемой
  • 24.
    Загрузка из сети https://github.com/nostra13/ Android-Universal-Image-Loader http://square.github.io/picasso Всоставе некоторых сетевых библиотек есть свои загрузчики картинок (в Volley точно есть). Есть в составе комбинированных библиотек (AQuery) В конце концов, можно поставить URL в ImageView (.setImageUrl()) 24 Работа с графической подсистемой
  • 25.