Полный список
Продолжаем разбирать типы Drawable, которые можно описывать с помощью XML-разметки. Проектов в этом уроке создавать не будем. Я просто буду в своем проекте создавать XML-файлы в папке drawable и ставить их фоном для View. А в тексте урока приведу код и скрины. Иногда буду вешать дополнительно серый фон, чтобы был виден реальный размер View.
Чтобы программно добраться до Drawable, который вы для View повесили как фон, надо просто вызвать метод getBackground.
Level List
Тег позволяет отображать Drawable в зависимости от значения level. Рассмотрим пример, где будем отображать три разных Drawable: если level=0, то зеленый прямогуольник; если 1, то желтый; если 2, то красный. Создадим три Drawable
Level List, в котором мы указываем какой Drawable при каком максимальном уровне (maxLevel) отображать.
Менять уровень у Drawable мы можем методом setLevel. Ставим 0 (по умолчанию)
В соответствии с заданным уровнем отображается Drawable.
Кроме атрибута maxLevel можно также использовать атрибут minLevel для указания минимального значения.
Transition Drawable
XML выглядит так:
Также у item есть атрибуты left, top, right, bottom для задания отступа.
В коде, для переключения между Drawable используются методы startTransition и reverseTransition. Оба метода принимают на вход количество мсек, которое будет длиться переход.
Inset Drawable
Насколько я понял – это просто обертка Drawable, которая позволяет указать padding-отступы. Корневой тег – , атрибуты отступа insetLeft, insetTop, insetRight, insetBottom.
Clip Drawable
Тег позволяет обрезать Drawable по горизонтальной и (или) вертикальной оси. Какая часть картинки будет обрезана зависит от значения level. Используемый диапазон тут от 0 до 10000, где 0 — картинка полностью обрезана и не видна, 10000 — картинка видна полностью. Атрибут gravity позволяет указать направление урезания.
Рассмотрим несколько примеров.
Устанавливаем программно (методом setLevel) уровень в 7000. А XML рисуем такой:
Ось — горизонтальная, направление — влево. Т.е. картинка обрезается по горизонтали справа-налево до 70% (7000 от 10000).
Уровень установим в 2000, а xml делаем таким:
Картинка обрезается по вертикали снизу вверх до 20%
Уровень 5000, xml:
Картинка обрезается по обоим осям вправо и вниз до 50%
Уровень 6000, xml:
Картинка обрезается по горизонтали к центру до 60%
Scale Drawable
Тег позволяет сжать картинку по горизонтальной (scaleWidth) и (или) вертикальной (scaleHeight) оси и сместить полученное изображение в указанную часть (scaleGravity) доступного пространства.
У меня этот тип Drawable работал только, если установить ему level > 0.
Сжимаем на 30% по горизонтали и смещаем влево.
Сжимаем на 70% по вертикали и смещаем вниз.
Сжимаем на 50% по обоим сторонам и смещаем вправо-вниз.
Сжимаем на 40% по ширине и 60% по высоте, и смещаем в центр
Animation drawable
Список Drawable с указанием времени отображения для каждого. Атрибут oneShot установленный в true говорит системе о том, что воспроизведение нужно только один раз. Если поставить false, то анимация будет циклично повторяться.
Чтобы запустить процесс анимации, необходимо получить Drawable, привести его к типу AnimationDrawable и вызвать метод start.
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Полный список
— изучаем drawable теги: , ,
Продолжаем разбирать типы Drawable, которые можно описывать с помощью XML-разметки. Проектов в этом уроке создавать не будем. Я просто буду в своем проекте создавать XML-файлы в папке drawable и ставить их фоном для View. А в тексте урока приведу код и скрины. Иногда буду вешать дополнительно серый фон, чтобы был виден реальный размер View.
Чтобы программно добраться до Drawable, который вы для View повесили как фон, надо просто вызвать метод getBackground.
Bitmap
Тег позволяет получить Drawable обертку для Bitmap. У тега есть несколько атрибутов.
В атрибуте src указываем нужный нам файл-изображение.
Атрибут gravity указывает, как bitmap будет располагаться внутри Drawable. Можно использовать несколько значений, разделенных знаком | . Значения тут стандартные, и некоторые из них мы часто используем при работе с layout. Рассмотрим пример.
Значение атрибута gravity сдвигает изображение влево-вверх
Далее ставим следующие значение атрибута gravity:
fill_horizontal — растянуть по горизонтали
fill — растянуть (используется по умолчанию)
Насколько я понял, значения clip_vertical и clip_horizontal идентичны значениям fill_vertical и fill_horizontal в случае когда Bitmap по размеру больше, чем предоставляемое ему пространство. Т.е. clip_vertical сожмет его по вертикали, так чтобы он влез. А clip_horizontal — по горизонтали.
Атрибут tileMode — это режим «плитки». Позволяет замостить вашим изображением все доступное пространство. По умолчанию он имеет значение disabled.
Для примера я создам такой bitmap.
Четыре разных цвета, внутренние границы — сплошные, внешние — пунктиром.
Если tileMode = repeat, то Bitmap будет размножен и займет все доступное пространство
Далее меняем значение атрибута tileMode.
mirror – Bitmap также будет размножен, но при этом он будет чередоваться со своим отражением
clamp – растягивает края картинки на все свободное пространство
Прочие атрибуты тега :
antialias – сглаживание линий
dither – преобразование цветов, если текущей палитры недостаточно для отображения
filter – фильтр при сжатии или растягивании (пример результата использования есть в Уроке 158)
mipMap – использование mip-текстурирования. Про него можно почитать в википедии. Используйте этот режим, если планируете в процессе отображения уменьшать bitmap более чем в два раза.
Мы рассмотрели XML-описание, но вы всегда можете создать этот объект и программно. Java-реализация – класс BitmapDrawable.
Layer List
Мы можем описать Drawable, который будет состоять из нескольких Drawable-слоев. Для этого используется тег , а внутри него теги .
У нас 4 слоя. Три bitmap со стандартной иконкой и одна фигура. Атрибуты left, top, right, bottom позволяют указывать отступы. А в атрибуте id можно указать id этого Drawable-слоя.
Обратите внимание, что важен порядок тегов item. Каждый последующий слой рисуется поверх предыдущего. Например, на получившемся изображении видно, что прямоугольник проходит «над» верхней иконкой, но «под» нижней.
Мы можем в коде получать доступ к отдельным Drawable внутри LayerDrawable. Для этого сначала получаем LayerDrawable.
А затем вызываем метод findDrawableByLayerId(int id) и указываем id, который вы указывали в атрибуте id тега item. На выходе получим Drawable.
Также у LayerDrawable есть еще несколько интересных методов
getDrawable(int index) — возвращает Drawable по индексу, а не по id
getId(int index) — возвращает id по индексу
getNumberOfLayers() — возвращает кол-во Drawable-слоев
State List
Тег позволяет отображать Drawable в зависимости от состояния View. Возможные состояние View можно посмотреть в хелпе. Рассмотрим пример с двумя из них: checked и pressed. На экране будет ToogleButton. Эта кнопка переходит в состояние checked и обратно, если на нее нажимать. А во время нажатия, пока палец касается экрана, кнопка находится в состоянии pressed.
State List позволит нам использовать три разных Drawable для отображения кнопки в трех состояниях: обычное, checked, pressed. Для этого создадим три файла в папке drawable.
Прямоугольник темно-серого цвета. Этот Drawable будем отображать в обычном состоянии кнопки.
Прямоугольник темно-синего цвета. Этот Drawable будем отображать в нажатом состоянии кнопки.
Прямоугольник светло-синего цвета. Этот Drawable будем отображать когда кнопка находится в состоянии checked.
И еще один файл, button_selector.xml:
Этот последний Drawable является селектором. В нем мы используем теги item, в которых указываем для какого состояния какой Drawable использовать
В первом item мы указали state_pressed=true, а значит этот item будет выбран системой когда кнопка будет в состоянии pressed. И экране мы увидим Drawable из этого item, т.е. toogle_button_pressed.
В втором item мы указали state_checked=true, а значит этот item будет выбран системой когда кнопка будет в состоянии checked. И экране мы увидим toogle_button_checked.
В третьем item мы не указали никакого состояния, этот item будет выбран при обычном состоянии кнопки. И экране мы увидим toogle_button.
Учтите, что здесь важен порядок расположения item внутри selector. Т.е. система идет по ним по порядку и выбирает первый подходящий. Если вы третий item, который без явного указания состояния, поставите первым, то система всегда будет останавливаться на нем.
Состояния можно комбинировать, т.е. в одном item вы можете указать несколько разных состояний.
Ставим этот Drawable, как фон для ToogleButton:
В результате, сначала видим обычное состояние
Нажимаем и держим, т.е. состояние pressed
Отпускаем – включился checked
Еще раз нажмем-отпустим — выключится checked и будет снова обычное состояние. Для каждого состояния отображается свой Drawable.
У View, кстати, есть методы, которые позволяют программно управлять состоянием. Это, например: setPressed и setSelected.
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Полный список
— изучаем drawable-тег shape
Подробно ознакомившись с Bitmap, переходим к другому ключевому объекту графики – Drawable.
Drawable – это абстрактный контейнер для графического объекта. Его главное абстрактное умение – он может нарисовать свое содержимое на предоставленной ему канве. А вот что конкретно он нарисует, зависит уже от реализации. Это может быть, например, тот же Bitmap, если мы используем BitmapDrawable объект. Или это может быть простая геометрическая фигура, если мы используем ShapeDrawable.
Drawable-объекты мы можем создавать сами напрямую в коде. Но для некоторых из них мы можем создать описание в xml-файлах, в папке res/drawable. И когда он нам понадобится, мы укажем id файла, система сама распарсит его и создаст нам нужный объект.
Самое распространенное использование Drawable – это свойство background, которое есть у каждого View. В качестве значения вы можете указать там RGB-цвет или id ресурса из папки res/drawable. Далее система сама по этому значению определит тип и далее:
— если это цвет, то создаст ColorDrawable,
— если это id картинки в res/drawable, то создаст BitmapDrawable
— если это id xml-файла в res/drawable, то распарсит его и вернет соответствующего ему наследника Drawable: StateListDrawable, AnimationDrawable или какой-то другой.
В итоге View получит свой Drawable-объект и сможет его нарисовать.
В общем, как вы поняли, у абстрактного Drawable есть несколько наследников-реализаций и в ближайших уроках мы их рассмотрим. Начнем с тех, которые можно описать в xml. По ним есть отдельная статья в хелпе. Там, правда, есть пара ошибок копипаста, но в остальном все верно.
В этом уроке рассмотрим тег
Project name: P1621_DrawableShape
Build Target: Android 4.4
Application name: DrawableShape
Package name: ru.startandroid.develop.p1621drawableshape
Create Activity: MainActivity
Корневой тег shape и у него же есть одноименный атрибут shape, в котором мы указываем тип фигуры. Мы указали rectangle – это прямоугольник.
Далее, внутри тега shape, идет тег stroke, который позволяет задать нам характеристики линии контура (периметра) фигуры. Мы задаем толщину (width) в 1dp и черный цвет (color).
В ImageView пока ничего не отображаем.
Видим ImageView с серым фоном
Перепишем метод setDrawable:
В качестве drawable будем передавать наш файл shape
ImageView теперь отображает прямоугольник с черным контуром.
Посмотрим, какие еще фигуры нам доступны.
Значение атрибута shape = oval, это эллипс
В нашем случае получился круг, т.к. ImageView квадратный.
Значение line даст нам горизонтальную линию
Есть еще фигура кольцо (ring), но о нем чуть позже.
Вернемся к тегу stroke. Добавим в него параметров.
Ширина – 4dp, цвет – синий. Параметры dashWidth и dashGap сделают линию контура пунктирной. dashWidth задает длину пунктирной черточки, а dashGap – расстояние между черточками
Добавим заливку, для этого используется тег solid
Тег solid имеет атрибут color, который позволяет указать цвет заливки фигуры. Мы указали в нем зеленый цвет.
По умолчанию фигура занимает все доступное ей пространство, но мы можем явно указать ее размер с помощью тега size.
Используем тег size с атрибутами width и height
Фигура теперь размером 100х100 и уже не занимает всю доступную ей площадь.
Учтите, что режим отображения зависит от scaleType y ImageView.
Тег padding позволяет нам задать величину отступа внутри фигуры. Это актуально, например, для TextView. Отступ будет учтен при размещении текста.
Мы указали различные отступы со всех 4 сторон.
Если мы теперь повесим эту фигуру в качестве background для TextView, результат будет таким
В качестве заливки мы можем использовать не один цвет, а градиент из двух или трех. Для этого используется тег gradient.
В теге gradient указываем два атрибута-цвета: startColor и endColor.
В результате получится градиент, переходящий из первого цвета во второй.
Градиент вовсе необязательно должен идти слева-направо. Мы можем указать угол направления. Для этого у тега gradient есть атрибут angle
В angle указываем угол 225. Угол 0 означает направление слева-направо, 90 – снизу вверх и т.д. Угол должен быть кратным 45.
В результате видим угол справа-сверху налево-вниз.
Тег gradient позволяет указать третий цвет, который вклинится между start- и end- цветами.
В атрибуте centerColor укажем синий цвет, и он в градиенте будет между красным и зеленым.
Градиент может быть разных типов. Мы рассмотрели тип linear, который используется по умолчанию. Есть еще два типа: radial и sweep.
Тип radial даст нам круговой градиент, а в параметре gradientRadius мы должны указать радиус круга.
Мы можем указать точку центра кругового градиента атрибутами centerX и centerY. Значения этих атрибутов должны быть от 0 до 1.
Центра градиента будет в точке (0.2, 0.2), если принять размеры фигуры за единицу.
Теперь посмотрим, как выглядит градиент sweep.
Для этого типа градиента также можно использовать атрибуты centerColor, centerX и centerY.
Для фигуры прямоугольника мы можем сгладить углы. За это отвечает тег corners.
Атрибут radius позволяет задать радиус закругления сразу для всех углов.
Есть возможность задать свой радиус для каждого угла отдельно.
Кольцо
Нам осталось рассмотреть четвертую фигуру — кольцо. Чтобы его получить, надо в атрибуте shape указать значение ring. Для кольца мы можем настроить два параметра: размер внутреннего радиуса и толщина кольца. Причем, эти два параметра мы можем указывать в абсолютном и относительном выражении.
innerRadius – позволяет указать внутренний радиус, а thickness – толщину кольца. Атрибут useLevel, который нам пока неизвестен, должен быть false, иначе эта фигура у меня не отображалась.
Отобразился круг с внутренним радиусом = 50dp и толщиной = 40dp.
Попробуем указать толщину кольца в относительном значении. Для этого вместо thickness используем thicknessRatio. В этом атрибуте мы указываем во сколько раз толщина кольца будет меньше его ширины.
Ширина кольца = 200 dp, это указано в теге size. thicknessRatio =10, значит толщина кольца = 200 dp / 10 = 20dp.
Теперь укажем внутренний радиус в относительном выражении. Для этого вместо innerRadius используем innerRadiusRatio. В атрибуте innerRadiusRatio указываем во сколько раз внутренний радиус меньше ширины кольца.
Ширина кольца = 200 dp. innerRadiusRatio = 3, значит внутренний радиус кольца = 200 dp / 3 = 67dp.
Как видите, кольцо может занимать не весь свой размер. Это зависит от значений, которые мы задаем для внутреннего радиуса и толщины.
У атрибутов относительного размера есть значения по умолчанию. Т.е. если мы явно не укажем значение для innerRadiusRatio, то по умолчанию он будет равен 3, а thicknessRatio по умолчанию равен 9. Посмотрим, как это выглядит
Мы указали только внутренний радиус. А размер толщины будет вычислен исходя из значения thicknessRatio по умолчанию, т.е. 9.
Теперь не будем указывать инфу о внутреннем радиусе.
Мы указали только толщину кольца, а внутренний радиус будет вычислен исходя из значения innerRadiusRatio по умолчанию = 3.
Давайте теперь попробуем вообще не указывать размеры внутреннего радиуса и толщины, и посмотрим, что получится.
Видим, что кольцо заняло не все 200 dp по высоте, которые мы ему задали в теге size. Почему? Давайте считать исходя из значения по умолчанию.
Внутренний радиус = 200 / 3 = 67. Толщина = 200 / 9 = 22. Т.е. диаметр кольца получается = 22 + 67 * 2 + 22 = 178.
Попробуем подогнать размер кольца под все выделенное ему пространство.
Теперь радиус будет равен 200 / 2.5 = 80, а толщина = 200 / 10 = 20. Диаметр кольца = 20 + 80 * 2 + 20 = 200.
Это видно и на скрине. Кольцо теперь по размеру равно ImageView, т.е. = 200.
Атрибуты абсолютных значений (innerRadius и thickness) имеют приоритет перед относительными (innerRadiusRatio и thicknessRatio).
GradientDrawable
Хоть корневой тег и называется shape, но когда система его распарсит, она создает не ShapeDrawable, а GradientDrawable.
Также, этот объект мы можем сами создать программно.
Перепишем метод setDrawable:
Методы set* позволяют нам установить почти все те же параметры, что и в xml-файле.
Но есть и отличия. Например, я не нашел как для GradientDrawable установить значения размеров для кольца. С другой стороны, мы в GradientDrawable можем указать больше трех цветов для градиента.
Т.е. в основном — xml- и java-создание равноценны, но есть некоторые нюансы.
На следующем уроке:
— изучаем drawable теги: , ,
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник