Как добавить тень в android studio
Перейти к содержимому

Как добавить тень в android studio

Как создать тень кнопки в стиле дизайна материалов Android

Изображение 80017

В новых руководствах по дизайну материалов представлены кнопки с повышенными возможностями, которые снижают хорошую тень. Согласно документации предварительного просмотра SDK в новом SDK будет доступен атрибут elevation . Однако есть ли какой-либо способ добиться подобного эффекта?

milano 18 авг. 2014, в 02:14
Поделиться

В этом ответе подробно описано, как это сделать с 9-образным патчем: stackoverflow.com/questions/4406524/…

Brittany 18 авг. 2014, в 00:45
@milano Вы уже решили это? setElevation или ViewCompat.setElevation ?
Jared Burrows 14 фев. 2015, в 05:14
Поделиться:
material-design

3 ответа

Лучший ответ

Это сработало для меня.

Макет с кнопкой

drawble/button_selector.xml

Anim/button_elevation.xml

Если у вас есть кнопка в прямоугольной форме, вы делаете это здесь. Но если у вас круглая или овальная кнопка, тогда это будет выглядеть,

Изображение 160469

Чтобы удалить углы из круглой или овальной формы, добавьте этот код в свой .java файл.

@Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); . int buttonSize = (int) getResources().getDimension(R.dimen.button_size); Outline circularOutline = new Outline(); circularOutline.setOval(0, 0, buttonSize, buttonSize); for (int i = 0; i < MAX_BUTTONS; i++) < Button button = . . button.setOutline(circularOutline); . >. > 

Angular форма удален!! Теперь он будет выглядеть точно как

Как сделать цветные тени в Android с градиентом и анимацией

На презентации новых макбуков обратил внимание на картинку процессора:

Переливающиеся цветные тени на темном фоне, выглядит классно.

Вот дошли руки, решил попробовать нарисовать на андроиде так же. Вот что получилось:

Сразу оговорюсь, что стандартным способом это сделать нельзя, до api 28 есть поддержка только черных elevation, после api 28 добавили поддержку цветных теней, но градиент сделать не получится. Поэтому мы будет рисовать drawable, устанавливать его в виде background и применять padding на целевой вьюхе, чтобы контент был внутри тени.

Напишем функцию создания Drawable с тенью:

/** * Создание drawable с градиентом-тенью */ private fun createShadowDrawable( @ColorInt colors: IntArray, cornerRadius: Float, elevation: Float, centerX: Float, centerY: Float ): ShapeDrawable < val shadowDrawable = ShapeDrawable() // Устанавливаем черную тень по умолчанию shadowDrawable.paint.setShadowLayer( elevation, // размер тени 0f, // смещение тени по оси Х 0f, // по У Color.BLACK // цвет тени ) /** * Применяем покраску градиентом * * @param centerX - Центр SweepGradient по оси Х. Берем центр вьюхи * @param centerY - Центр по оси У * @param colors - Цвета градиента. Последний цвет должен быть равен первому, * иначе между ними не будет плавного перехода * @param position - позиции смещения градиента одного цвета относительно другого от 0 до 1. * В нашем случае null т.к. нам нужен равномерный градиент */ shadowDrawable.paint.shader = SweepGradient( centerX, centerY, colors, null ) // Делаем закугление углов val outerRadius = FloatArray(8) < cornerRadius >shadowDrawable.shape = RoundRectShape(outerRadius, null, null) return shadowDrawable >

Поскольку у этого drawable фон представлен в виде радуги тех цветов, что мы передали в параметрах, нам нужен нормальный одноцветный фон. Для этого создаем вторую drawable:

/** * Создание цветного drawable с закругленными углами * Это будет основной цвет нашего контейнера */ private fun createColorDrawable( @ColorInt backgroundColor: Int, cornerRadius: Float ) = GradientDrawable().apply

Функция установки бэкграунда на вьюху-контейнер. У нас будет LayerDrawable с двумя слоями. 1 — тень, 2 — просто цвет с закругленными углами.

/** * Устанавливаем бэкграунд с тенью на вьюху, учитывая padding */ private fun View.setColorShadowBackground( shadowDrawable: ShapeDrawable, colorDrawable: Drawable, padding: Int )

Применяем на вьюхе:

// ждем когда вьюха отрисуется чтобы узнать ее размеры targetView.doOnNextLayout < val colors = intArrayOf( Color.WHITE, Color.RED, Color.WHITE ) val cornerRadius = 16f.dp val padding = 30.dp val centerX = it.width.toFloat() / 2 - padding val centerY = it.height.toFloat() / 2 - padding val shadowDrawable = createShadowDrawable( colors = colors, cornerRadius = cornerRadius, elevation = padding / 2f, centerX = centerX, centerY = centerY ) val colorDrawable = createColorDrawable( backgroundColor = Color.DKGRAY, cornerRadius = cornerRadius ) it.setColorShadowBackground( shadowDrawable = shadowDrawable, colorDrawable = colorDrawable, padding = 30.dp ) >

Теперь проанимируем изменение с одного набора цветов на другие. Зациклим.

/** * Анимация drawable-градиента */ private fun animateShadow( shapeDrawable: ShapeDrawable, @ColorInt startColors: IntArray, @ColorInt endColors: IntArray, duration: Long, centerX: Float, centerY: Float ) < /** * Меняем значение с 0f до 1f для применения плавного изменения * цвета с помощью [ColorUtils.blendARGB] */ ValueAnimator.ofFloat(0f, 1f).apply < // Задержка перерисовки тени. Грубо говоря, фпс анимации val invalidateDelay = 100 var deltaTime = System.currentTimeMillis() // Новый массив со смешанными цветами val mixedColors = IntArray(startColors.size) addUpdateListener < animation ->if (System.currentTimeMillis() - deltaTime > invalidateDelay) < val animatedFraction = animation.animatedValue as Float deltaTime = System.currentTimeMillis() // Смешиваем цвета for (i in 0..mixedColors.lastIndex) < mixedColors[i] = ColorUtils.blendARGB(startColors[i], endColors[i], animatedFraction) >// Устанавливаем новую тень shapeDrawable.paint.shader = SweepGradient( centerX, centerY, mixedColors, null ) shapeDrawable.invalidateSelf() > > repeatMode = ValueAnimator.REVERSE repeatCount = Animation.INFINITE setDuration(duration) start() > >
// Второй массив с цветами. Размер массивов должен быть одинаковый. val endColors = intArrayOf( Color.RED, Color.WHITE, Color.RED ) animateShadow( shapeDrawable = shadowDrawable, startColors = colors, endColors = endColors, duration = 2000, centerX = centerX, centerY = centerY )

Все. Если это будет кнопкой, нужно применить ripple эффект для foreground вьюхи и так же прописать там отступ, чтобы у нас отображалась анимация нажатия.

  • Разработка под Android
  • Kotlin

Drawable. Изображения, фигуры и градиенты

Android генерирует идентификаторы ресурсов для файлов изображений, расположенных в подкаталоге /res/drawable. Поддерживаются файлы PNG (самый предпочтительный), GIF, JPG. Для каждого файла изображения, который находится в этом каталоге, генерируется уникальный идентификатор на основе имени файла без расширения. Например, если у файла имя «cat.jpg», то для него будет создан идентификатор ресурса R.drawable.cat. Нужно следить за уникальностью имён, так как если у вас будут два файла «cat.jpg» и «cat.png», то возникнет ошибка. Кроме того, не нужно создавать дополнительных подкаталогов в папке res/drawable, так как файлы оттуда не будут считываться.

Можно адаптировать картинки для разных разрешений и размеров экранов. Для этого нужно создать специальные папки и складывать там нужные картинки. Например, для различных разрешений экрана используются папки drawable-hdpi, drawable-mdpi, drawable-ldpi и пр.. Существует аналогичное деление для размеров экрана: drawable-normal, drawable-large и т.д.. Можно совмещать эти способы и создавать папки типа drawable-normal-hdpi. Для изображений, которые должны оставаться неизменными вне зависимости от разрешения экрана, следует создать папку drawable-nodpi.

Для памятки приведу используемые размеры изображений для значков и фона экрана:

  • res/drawable-ldpi — (120 DPI) (QVGA):
    ic_launcher.png (значок), 36 × 36 background.png (фон), 320 × 240 pixels
  • res/drawable-mdpi — (160 DPI) (HVGA):
    background.png, 320 × 480
  • res/drawable-hdpi — (240 DPI) (WVGA):
    ic_launcher.png, 72 × 72
    background.png, 800 × 480
  • res/drawable-xhdpi (320 DPI) (WSVGA or HDTV):
    ic_launcher.png, 96 × 96
    background.png, 1024 × 600 или 1280 × 720 pixels

Чтобы сослаться на изображение из res/drawable в XML-файлах разметки, используйте следующий синтаксис:

Обратите внимание, что в любом случае мы обращаемся к ресурсу как drawable, а не drawable-hdpi или как-то еще.

Программным способом можно достучаться до изображения следующим образом:

 // вызываем getDrawable для получения изображения BitmapDrawable bd = activity.getResources().getDrawable(R.drawable.cat); // Затем можно использовать полученный объект, чтобы установить фон button.setBackgroundDrawable(bd); // или можно установить фон непосредственно по идентификатору ресурса button.setBackgroundResource(R.drawable.icon); 

Android включает простые ресурсы для рисования, которые можно полностью описать в формате XML. Это касается классов ColorDrawable, ShapeDrawable и GradientDrawable. Данные ресурсы хранятся в каталоге res/drawable и могут быть идентифицированы в коде приложения по именам файлов, записанным в нижнем регистре.

Если описывать эти ресурсы в формате XML и указывать атрибуты для них с помощью аппаратно-независимых пикселей (density-independent pixels), система сможет их плавно масштабировать. Как и в случае с векторной графикой, эти ресурсы могут динамически масштабироваться, отображаясь корректно и без артефактов при любых размерах и разрешениях экрана, независимо от плотности пикселов. Исключение — ресурс GradientDrawable, радиус для которого должен быть указан в пикселях.

Получить имя ресурса

Иногда нужно получить не сам идентификатор, а его имя в виде R.drawable.cat, что сохранить его, скажем, в базе данных. Воспользуйтесь следующим приёмом:

 getResources().getIdentifier("image_name","drawable", getPackageName()) getResources().getIdentifier("your.full.package.name:drawable/image_name", null, null); 

Бывает и обратная задача — из имени ресурса получить идентификатор. Тот же принцип.

 String mDrawableName = "cat1"; // файл cat1.png в папке drawable int resID = getResources().getIdentifier(mDrawableName , "drawable", getPackageName()); 

Строго говоря это относится не только к типу drawable, но обычно приходится встречаться с проблемой именно для них.

(класс AnimatedRotateDrawable)

Ресурсы для создания эффекта вращения.

Атрибут Тип Значение по умолчанию Описание
visible boolean parent|true Determines if drawable is visible.
frameDuration integer 150 The duration of each frame, in milliseconds.
framesCount integer 12 Number of frames of rotation to animate.
pivotX float|fraction .5 The pivot point, as a fraction of the width.
pivotY float|fraction .5 The pivot point, as a fraction of the height.
drawable reference null The drawable to use for this item. Either this must be present or a drawable subelement must exist.

(класс AnimationDrawable)

Вращение по кадрам. Нужно подготовить несколько похожих изображений, которые будут сменять друг друга.

Атрибут Тип Значение по умолчанию Описание
visible boolean parent|true Determines if drawable is visible.
variablePadding boolean false If true, allows the drawable’s padding to change based on the current state that is selected.
oneshot boolean false If true, the animation will only run a single time and then stop.

Если у нас имеется несколько изображений одного ProgressBar

(класс BitmapDrawable)

Позволяет использовать растровые изображения и проделывать с ними различные операции: растягивать, размножать, выравнивать. Часто используется в составе других ресурсов. Смотри примеры ниже.

Основной атрибут src, в котором указывается файл изображения.

Атрибут gravity позволяет управлять размещением картинки внутри контейнера. Можно использовать несколько значений, разделенных знаком |: top, left, center, fill и др.

У него также есть интересный атрибут tileMode, позволяющий замостить изображением всё доступное пространство. Можно использовать значения repeat, mirror, clamp. Пример есть выше по ссылке.

Другие атрибуты: antialias (сглаживание), dither (преобразование цветов, если текущей палитры недостаточно для отображения), filter (фильтр при сжатии или растягивании), mipMap.

В Android 5.0 (API 21) у bitmap появился новый атрибут android:tint, позволяющий задавать оттенки.

(класс ClipDrawable)

Данный вид ресурсов часто используется для создания индикаторов прогресса.

Тег clip позволяет обрезать Drawable по горизонтальной или по вертикальной оси через атрибут clipOrientation.

Атрибут gravity позволяет указать направление обрезания. Значения атрибута можно комбинировать. Например, если у clipOrientation значение равно vertical, а у gravitytop, то отрежется нижняя часть изображения.

Создадим файл res/drawable/clipping.xml

Присвоим созданный ресурс компоненту ImageView:

Сама обрезка производится программно через метод setLevel() с диапазоном значений от 0 до 10000, где 0 — картинка полностью обрезана и не видна, 10000 — картинка видна полностью.

 public void onClick(View view)

В примере обрезается правая часть по центру, оставляя видимой левую часть картинки.

ClipDrawable

Чтобы оставить только четвертинку (левую верхнюю часть), изменим атрибуты

ClipDrawable

Следующая комбинация отрежет лишнее слева и справа, оставив только центральную часть изображения.

(класс ColorDrawable)

Цветовые ресурсы используются в виде значений в папке res/values, например, в файле colors.xml. Но можно обращаться к цвету, как drawable-ресурсу.

 android:drawable="@color/green" 

(Класс InsetDrawable)

Пример создания объёмной панели с помощью inset.

(класс LayerDrawable)

Можно задавать не только простые формы, но и их комбинации. Для этого служит класс LayerDrawable, позволяющий накладывать несколько объектов Drawable один поверх другого. Описав массив полупрозрачных объектов Drawable, вы можете создать сложную комбинацию динамических фигур и преобразований.

LayerDrawable описывается с помощью тега , внутри которого для каждого дочернего узла используется атрибут drawable, указывающий на ресурс для наложения.

Каждый объект Drawable будет накладываться в соответствии со своим индексом — первый элемент массива размещается в самом низу.

Переделаем пример программного использования LayerDrawable на пример с использованием XML. Создадим в папке res/drawable файл layerdrawable.xml:

Осталось применить к макету, при этом нам не нужен метод из примера по ссылке.

 LinearLayout linear = (LinearLayout)findViewById(R.id.linear); //linear.setBackground(createLayerDrawable()); linear.setBackgroundResource(R.drawable.layerdrawable); // с помощью XML 

Кнопка с бликом

Рассмотрим другие примеры. Например, можно создать такую кнопку с бликом.

Layer List

Марка

Можно даже создать изображение марки.

Марка

Тени

Создав два похожих объекта и сместив их относительно друг друга, вы можете реализовать эффект тени.

Тень

Кнопка-треугольник

Создадим кнопку треугольной формы. Файл res/drawable/arrow_up.xml.

Применим стиль к кнопке. Текст задавать не будем.

Если понадобится такая же кнопка с направлением вниз, то достаточно добавить атрибут android:rotation=»180″.

(класс TransitionDrawable)

Является расширением предыдущего layer-list и позволяет использовать наложение.

В теге transition указываются два объекта Drawable, между которыми можно переключаться с fade-эффектом и указанием продолжительности перехода.

(класс LevelListDrawable)

Используя LevelListDrawable, вы можете эффективно размещать ресурсы Drawable один поверх другого, указывая целочисленный индекс для каждого слоя.

Чтобы вывести на экран определенное изображение, вызовите метод setImageLevel() из представления, которому назначен ресурс LevelListDrawable, передавая в качестве параметра индекс объекта Drawable, который вы хотите отобразить.

 imageView.setImageLevel(5); 

Представление отобразит ресурс с соответствующим (или большим) индексом. Ресурс LevelListDrawable нужен при компоновке виджетов.

(класс NinePatchDrawable)

(класс RotateDrawable)

Данный ресурс позволяет повернуть изображение на нужный градус. Допустим, у вас есть стрелки в разные стороны. Совсем не обязательно создавать копии стрелок. Достаточно нарисовать одну стрелку, а в файлах прописать нужные повороты. Например, повернём значок приложения вверх тормашками в файле drawable/rotate_up.xml:

Присвойте атрибуту src компонента ImageView и вы увидите значок перевёрнутым.

  • drawable — изображение для поворота
  • fromDegrees — начальный угол поворота, в градусах. По умолчанию 0.0
  • toDegrees — конечный угол поворота, в градусах. По умолчанию 360.0
  • pivotX — опорная точка по X
  • pivotY — опорная точка по Y

Опорная точка — это место для виртуальной булавки, вокруг которой будет вращаться пришпиленный листок. Для центра мы указали половину по высоте и ширине. Для неподвижной картинки углы поворота можно указать одинаковыми.

Тег rotate также используется в анимационных ресурсах, не путайте их.

(класс ScaleDrawable)

Позволяет масшабировать (сжать или расширить) изображение по горизонтальной (scaleWidth) и/или вертикальной (scaleHeight) оси и сместить полученное изображение в указанную часть (scaleGravity) доступного пространства.

(класс StateListDrawable)

У некоторых элементов управления есть различные состояния: нажато, выбрано и т.д.. Вы можете задавать изображения для любого из таких состояний.

Чтобы описать StateListDrawable, создайте файл в формате XML, в котором указываются разные ресурсы Drawable для каждого состояния компонента. Каждый атрибут вида android:state_* может принимать одно из двух значений: true или false.

Доступны следующие состояния:

  • state_focused — в фокусе или нет
  • state_window_focused — имеет ли фокус родительское окно
  • state_enabled — доступен или нет
  • state_checkable — может ли быть отмечен или нет
  • state_checked — отмечен или нет
  • state_selected — выделен или нет
  • state_activated — активирован или нет
  • state_pressed — нажат или не нажат
  • state_hovered — находится ли курсор над компонентом или нет (API 11 и выше)

Для списков есть также:

  • state_single
  • state_first
  • state_middle
  • state_last

Рассмотрим примеры. Нас не устраивает внешний вид кнопки. Хочется, чтобы она выглядела так (Да еще и чтобы подсвечивалась при нажатии):

Custom Button

Сделать это просто. Добавляем в ресурсы изображения нормального (button_up.png) и нажатого (button_down.png) состояний кнопки. И создаём в папке drawables XML-файл со следующим содержанием (states_button.xml):

Важный момент: в списке состояний нужно сначала указывать специализированные состояния, а последним должно следовать состояние по умолчанию (без атрибутов state-* вообще).

Ещё один момент. Кнопка может одновременно находиться в состоянии pressed и focused, поэтому сначала указывайте state_pressed, а затем state_focused. Иначе, если кнопка будет в состоянии focused, то состояние pressed не применится.

Теперь осталось у атрибута background для кнопки прописать созданный ресурс.

Можно обойтись без использования изображений для кнопки, а воспользоваться фигурами (states_shapes.xml).

Custom Button

А можно использовать просто цвета:

Попробуйте применить файл не к атрибуту background, а к атрибуту android:textColor, чтобы цвет влиял на текст кнопки, а не на саму кнопку.

Можно использовать как шпаргалку следующую картинку.

RadioBox, CheckBox и др.

Похожим образом можно задавать стили для RadioButtom, CheckBox и т.п.. Но тут мало того, что можно отдельным ресурсом задавать фон, так отдельным же ресурсом можно задавать саму пиктограмму через атрибут button (states_compound.xml).

Разметка с созданными стилями

Custom CheckBox

-nodpi, -anydpi

Есть очень интересная статья о папках с квалификаторами -nodpi, -anydpi — The CommonsBlog — -nodpi, -anydpi, and WTF?

Вкратце, nodpi для исключительных случаев, когда картинка нужного разрешения не найдётся. Например, у нас есть res/drawable-nodpi/foo.xml и res/drawable-xxhdpi/foo.png. Устройство с -xxhdpi должно использовать PNG; остальные — XML-версию.

Изображения в res/drawable-anydpi/ также подойдут для любого разрешения экрана, но работают по другому принципу. Например, у нас есть res/drawable-anydpi/foo.xml и res/drawable-xxhdpi/foo.png. Все устройства должны использовать XML, даже устройства с разрешением -xxhdpi. Поэтому квалификатор удобно использовать совместно с другими квалификаторами. В частности, с -v21, что полезно при работе с вектором.

Допустим, у нас есть res/drawable-anydpi-v21/foo.xml и res/drawable-xxhdpi/foo.png. В этом случае, все устройства 5.0+ будут использовать XML. Все xxhdpi-устройства на Android 4.4 и ниже будут использовать PNG. И все остальные устройства на Android 4.4 и ниже также будут использовать PNG, подгоняя картинку под своё разрешение.

Векторные файлы нельзя размещать в папке -nodpi, если minSdkVersion меньше 21.

Папка res/drawable/ по сути является синонимом для res/drawable-mdpi/ и была оставлена в целях совместимости, когда на первых устройствах ещё не было деления на разрешения экрана. Никто же не предполагал, что Android так разовьётся. Сейчас эту папку используют для xml-файлов, которые ведут себя достаточно независимо то разрешения экранов при правильном использовании.

Дополнительное чтение

О градиентах в отдельной статье

Заполнение и тени кнопок в Android

Эта платформа Android определяет, используют ли Xamarin.Forms кнопки значения заполнения и тени по умолчанию для кнопок Android. Он потребляется в XAML путем установки значений Button.UseDefaultPadding для присоединенных свойств boolean и Button.UseDefaultShadow :

Кроме того, его можно использовать из C# с помощью текучих API:

using Xamarin.Forms.PlatformConfiguration; using Xamarin.Forms.PlatformConfiguration.AndroidSpecific; . button.On().SetUseDefaultPadding(true).SetUseDefaultShadow(true); 

Метод Button.On указывает, что эта платформа будет работать только на Android. Методы Button.SetUseDefaultPadding и Button.SetUseDefaultShadow в Xamarin.Forms.PlatformConfiguration.AndroidSpecific пространстве имен используются для управления тем, используются ли Xamarin.Forms для кнопок значения заполнения и тени кнопок Android по умолчанию. Кроме того, методы и Button.UseDefaultShadow можно использовать для возврата того, Button.UseDefaultPadding использует ли кнопка значение заполнения по умолчанию и значение тени по умолчанию соответственно.

В результате Xamarin.Forms кнопки могут использовать значения заполнения и тени по умолчанию для кнопок Android:

Значения заполнения и тени по умолчанию на кнопках Android

Обратите внимание, что на снимке экрана выше каждое из них Button имеет одинаковые определения, за исключением того, что в правой части Button используются значения заполнения и тени кнопок Android.

Связанные ссылки

  • PlatformSpecifics (пример)
  • Создание особенностей платформы
  • AndroidSpecific API
  • AndroidSpecific.AppCompat API

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *