Добавить тень к пользовательской фигуре на Android
Можно ли добавить тень на пользовательскую фигуру в Android? Просматривая документацию, я вижу только способ применения тени для текста.
Я попробовал это без удачи:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#90ffffff"/>
<corners android:radius="12dp" />
<item name="android:shadowColor">#000000</item>
<item name="android:shadowRadius">5</item>
<item name="android:shadowDy">3</item>
</shape>
16 ответов
После долгих поисков, наконец, я получил это
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Bottom 2dp Shadow -->
<item>
<shape android:shape="rectangle">
<solid android:color="#d8d8d8" />
<corners android:radius="7dp" />
</shape>
</item>
<!-- White Top color -->
<item android:bottom="3px">
<shape android:shape="rectangle">
<solid android:color="#FFFFFF" />
<corners android:radius="7dp" />
</shape>
</item>
</layer-list>
Вот как я это делаю:
Код ниже для одной кнопки STATE:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- "background shadow" -->
<item>
<shape android:shape="rectangle" >
<solid android:color="#000000" />
<corners android:radius="15dp" />
</shape>
</item>
<!-- background color -->
<item
android:bottom="3px"
android:left="3px"
android:right="3px"
android:top="3px">
<shape android:shape="rectangle" >
<solid android:color="#cc2b2b" />
<corners android:radius="8dp" />
</shape>
</item>
<!-- over left shadow -->
<item>
<shape android:shape="rectangle" >
<gradient
android:angle="180"
android:centerColor="#00FF0000"
android:centerX="0.9"
android:endColor="#99000000"
android:startColor="#00FF0000" />
<corners android:radius="8dp" />
</shape>
</item>
<!-- over right shadow -->
<item>
<shape android:shape="rectangle" >
<gradient
android:angle="360"
android:centerColor="#00FF0000"
android:centerX="0.9"
android:endColor="#99000000"
android:startColor="#00FF0000" />
<corners android:radius="8dp" />
</shape>
</item>
<!-- over top shadow -->
<item>
<shape android:shape="rectangle" >
<gradient
android:angle="-90"
android:centerColor="#00FF0000"
android:centerY="0.9"
android:endColor="#00FF0000"
android:startColor="#99000000"
android:type="linear" />
<corners android:radius="8dp" />
</shape>
</item>
<!-- over bottom shadow -->
<item>
<shape android:shape="rectangle" >
<gradient
android:angle="90"
android:centerColor="#00FF0000"
android:centerY="0.9"
android:endColor="#00FF0000"
android:startColor="#99000000"
android:type="linear" />
<corners android:radius="8dp" />
</shape>
</item>
</layer-list>
Тогда у вас должен быть селектор с разными версиями кнопки, что-то вроде:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_button_red_pressed" android:state_pressed="true"/> <!-- pressed -->
<item android:drawable="@drawable/ic_button_red_selected" android:state_focused="true"/> <!-- focused -->
<item android:drawable="@drawable/ic_button_red_selected" android:state_selected="true"/> <!-- selected -->
<item android:drawable="@drawable/ic_button_red_default"/> <!-- default -->
</selector>
надеюсь, что это может помочь вам.. удачи
Это моя версия тени. Я искал смутную тень по всей фигуре и использовал этот ответ Joakim Lundborg качестве отправной точки. Что я изменил, так это добавление углов ко всем теневым элементам и увеличение радиуса угла для каждого последующего теневого элемента. Так вот xml
:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Drop Shadow Stack -->
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#02000000" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#05000000" />
<corners android:radius="7dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#10000000" />
<corners android:radius="6dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#15000000" />
<corners android:radius="5dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#20000000" />
<corners android:radius="4dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#25000000" />
<corners android:radius="3dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#30000000" />
<corners android:radius="3dp" />
</shape>
</item>
<!-- Background -->
<item>
<shape>
<solid android:color="#0099CC" />
<corners android:radius="3dp" />
</shape>
</item>
</layer-list>
Я думаю, что этот метод дает очень хорошие результаты:
<!-- Drop Shadow Stack -->
<item>
<shape>
<padding
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
android:left="1dp"/>
<solid android:color="#00CCCCCC"/>
</shape>
</item>
<item>
<shape>
<padding
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
android:left="1dp"/>
<solid android:color="#10CCCCCC"/>
</shape>
</item>
<item>
<shape>
<padding
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
android:left="1dp"/>
<solid android:color="#20CCCCCC"/>
</shape>
</item>
<item>
<shape>
<padding
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
android:left="1dp"/>
<solid android:color="#30CCCCCC"/>
</shape>
</item>
<item>
<shape>
<padding
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
android:left="1dp"/>
<solid android:color="#50CCCCCC"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<stroke android:color="#CCC" android:width="1dp"/>
<solid android:color="#FFF" />
<corners android:radius="2dp" />
</shape>
</item>
Я нашел это по адресу: http://www.uifuel.com/android-creating-a-drop-shadow-in-xml-layout/
У меня сработало следующее: Просто сохраните как custom_shape.xml.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- "shadow" -->
<item>
<shape android:shape="rectangle" >
<solid android:color="#000000"/>
<corners android:radius="12dp" />
</shape>
</item>
<item android:bottom="3px">
<shape android:shape="rectangle">
<solid android:color="#90ffffff"/>
<corners android:radius="12dp" />
</shape>
</item>
</layer-list>
Я бы предложил небольшое улучшение решения Брюса, которое состоит в том, чтобы предотвратить наложение одной и той же фигуры друг на друга и просто использовать штрих вместо твердого тела. Это будет выглядеть так:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Drop Shadow Stack -->
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke android:color="#02000000" android:width="1dp" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke android:color="#05000000" android:width="1dp" />
<corners android:radius="7dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke android:color="#10000000" android:width="1dp" />
<corners android:radius="6dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke android:color="#15000000" android:width="1dp" />
<corners android:radius="5dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke android:color="#20000000" android:width="1dp" />
<corners android:radius="4dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke android:color="#25000000" android:width="1dp" />
<corners android:radius="3dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<stroke android:color="#30000000" android:width="1dp" />
<corners android:radius="3dp" />
</shape>
</item>
<!-- Background -->
<item>
<shape>
<solid android:color="#FFF" />
<corners android:radius="3dp" />
</shape>
</item>
</layer-list>
Наконец, я хотел бы отметить для людей, которые хотели бы тень в определенном направлении, что все, что вам нужно сделать, это установить верхнюю, нижнюю, левую или правую на 0dp (для сплошной линии) или -1dp (для ничего)
Старый вопрос, но высота, доступная в Material Design, теперь создает тень для любых видов.
<TextView
android:id="@+id/myview"
...
android:elevation="2dp"
android:background="@drawable/myrect" />
См. Документы по адресу https://developer.android.com/training/material/shadows-clipping.html
Если вы не возражаете против рисования с помощью Canvas API, ознакомьтесь с ответом о тенях. Вот дополнительный вопрос к тому, который исправляет проблему в оригинале.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="@android:color/white" >
</solid>
<stroke
android:width="1dp"
android:color="@color/LightGrey" >
</stroke>
<padding
android:bottom="5dp"
android:left="2dp"
android:right="2dp"
android:top="5dp" >
</padding>
<corners
android:bottomLeftRadius="20dp"
android:bottomRightRadius="20dp"
android:radius="12dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp" />
<gradient
android:angle="90"
android:centerColor="@android:color/white"
android:centerY="0.2"
android:endColor="#99e0e0e0"
android:startColor="@android:color/white"
android:type="linear" />
</shape>
Этот вопрос может быть старым, но для любого в будущем, кто хочет простой способ достигнуть сложных эффектов тени, проверьте мою библиотеку здесь https://github.com/BluRe-CN/ComplexView
Используя библиотеку, вы можете изменять цвета теней, настраивать края и многое другое. Вот пример для достижения того, что вы ищете.
<com.blure.complexview.ComplexView
android:layout_width="400dp"
android:layout_height="600dp"
app:radius="10dp"
app:shadow="true"
app:shadowSpread="2">
<com.blure.complexview.ComplexView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:color="#fdfcfc"
app:radius="10dp" />
</com.blure.complexview.ComplexView>
Чтобы изменить цвет тени, используйте app:shadowColor="ваш цветовой код".
Я думаю, что это значение тени хорошо подходит для большинства случаев:
<solid android:color="#20000000" />
9 спешит на помощь, красивую тень можно легко получить, особенно с помощью этого замечательного инструмента -
Генератор теней с 9 патчами для Android
PS: если проект не может быть скомпилирован, вам нужно будет немного переместить черные линии в редакторе студии Android.
Просто установите высоту примерно на 10.https://developer.android.com/training/material/shadows-clipping
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="3dp"
android:left="5dp"
android:right="5dp"
android:top="5dp">
<shape android:shape="rectangle">
<gradient
android:startColor="@color/white"
android:endColor="@color/gray"
android:angle="270"
android:dither="false"/>
<corners android:radius="@dimen/_20dp" />
</shape>
</item>
<item
android:bottom="6dp"
android:left="6dp"
android:right="6dp"
android:top="6dp">
<shape android:shape="rectangle">
<solid android:color="@color/orange" />
<corners android:radius="@dimen/_20dp" />
</shape>
</item>
</layer-list>
По какой-то причине тени не работают, если вы установите
<solid>
А ТАКЖЕ
<stroke>
на вашем собственном фоне. Создание
<layer-list>
с отдельными слоями для заливки и границ устраняет проблему:
<?xml version="1.0" encoding="utf-8"?>
<!-- Separate layers for solid and stroke, because no shadows get drawn otherwise (using elevation) -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/card_default" />
<corners android:radius="@dimen/card_corner_radius" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<stroke android:color="@color/card_border" android:width="@dimen/card_border_width"/>
<corners android:radius="@dimen/card_corner_radius" />
</shape>
</item>
</layer-list>
Если вам нужна тень от прямой линии (как в нижней части панели инструментов), вы также можете использовать градиент xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:type="linear"
android:angle="-90"
android:startColor="#19000000" <!-- black transparent -->
android:endColor="#00000000" /> <!-- full transparent -->
</shape>
надеюсь, это поможет кому-то