Android Drop Shadow при просмотре

Я провел обширный поиск примеров кода по этому вопросу, но ничего не нашел.

В частности, я хочу добавить тень к рисунку png, который я использую в ImageView. Этот png-рисунок представляет собой закругленный прямоугольник с прозрачными углами.

Может ли кто-нибудь предоставить пример кода, как добавить приличную тень к представлению либо в коде, либо в XML?


person coneybeare    schedule 25.08.2010    source источник
comment
вы можете легко создать тень с девятью патчами, используя этот инструмент inloop.github.io/shadow4android   -  person Yuraj    schedule 13.12.2014


Ответы (5)


Вы можете использовать комбинацию Bitmap.extractAlpha и BlurMaskFilter, чтобы вручную создать тень для любого изображения, которое вам нужно отобразить, но это сработает только в том случае, если ваше изображение загружается/отображается только время от времени, поскольку этот процесс является дорогостоящим.

Псевдокод (может даже компилироваться!):

BlurMaskFilter blurFilter = new BlurMaskFilter(5, BlurMaskFilter.Blur.OUTER);
Paint shadowPaint = new Paint();
shadowPaint.setMaskFilter(blurFilter);

int[] offsetXY = new int[2];
Bitmap shadowImage = originalBitmap.extractAlpha(shadowPaint, offsetXY);

/* Might need to convert shadowImage from 8-bit to ARGB here, can't remember. */

Canvas c = new Canvas(shadowImage);
c.drawBitmap(originalBitmap, offsetXY[0], offsetXY[1], null);

Затем поместите shadowImage в свой ImageView. Если это изображение никогда не меняется, но часто отображается, вы можете создать его и кэшировать в onCreate, чтобы обойти дорогостоящую обработку изображения.

Даже если это не работает как есть, этого должно быть достаточно, чтобы вы двигались в правильном направлении.

person Josh    schedule 25.08.2010
comment
Это вроде сработало… Как только я изменил offsetXY[[0] и [1] в drawBitmap, чтобы они были отрицательными для тех значений, которые выровнялись правильно. Однако исходное растровое изображение отображается как сплошное черное изображение. cl.ly/77e6b7839c1ffc94c1e0 Как исправить? - person coneybeare; 26.08.2010
comment
Не уверен, не видя кода. Попробуйте проверить разрядность исходного и целевого растровых изображений. Проблема может заключаться в том, что вы рисуете 32-битное изображение (оригинал) на 8-битном изображении (извлеченное теневое изображение). Если это так, сделайте что-нибудь вроде Bitmap shadowImage32 = shadowImage.copy(ARGB_8888, true) вверху, где у меня есть комментарий convert, и нарисуйте этого парня вместо 8-битного shadowImage. - person Josh; 27.08.2010
comment
Привет @ Джош, я использую твой код. Это работает, но как мы можем изменить цвет тени? - person Hardik Joshi; 09.05.2013
comment
Замените нуль в этой последней строке drawBitmap на Paint, который использует ColorFilter. См. stackoverflow.com /questions/3499095/ для примера. - person Josh; 09.05.2013
comment
просто хочу отметить, что размытие выполняется для всего shadowImage, просто чтобы получить градиент тени по краям, это не очень эффективно. - person Helin Wang; 10.12.2014
comment
У вас есть лучшее предложение по созданию тени на произвольном изображении, Хелин? - person Josh; 10.12.2014

Для тени используйте код ниже

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
  <gradient
    android:startColor="#ffffff"
    android:centerColor="#d3d7cf"
    android:endColor="#2e3436"
    android:angle="90" />
</shape>

Используйте вышеприведенный рисунок для фона представления

<View 
    android:id="@+id/divider" 
    android:background="@drawable/black_white_gradient"
    android:layout_width="match_parent" 
    android:layout_height="10sp"
    android:layout_below="@+id/buildingsList"/>
person om252345    schedule 05.12.2011
comment
Это объясняется не так хорошо, как могло бы быть, но это не совсем плохой подход. Ключевым моментом является то, что вид с градиентом в качестве фона — это отдельный вид, который должен располагаться непосредственно под видом, на котором вы хотите, чтобы появилась тень. Лучше всего это работает, когда затеняемый вид занимает всю ширину экрана, иначе углы будут выглядеть неправильно. - person Tim Martin; 26.05.2012
comment
Это подход для декларативных ситуаций, но в моем случае я создаю динамическое количество кнопок в коде в зависимости от прочитанных данных, поэтому в моем случае это не очень полезно. - person jrichview; 11.04.2016

Это помогло мне заставить тень работать, поэтому я хотел поделиться рабочим кодом:

private Bitmap createShadowBitmap(Bitmap originalBitmap) {
    BlurMaskFilter blurFilter = new BlurMaskFilter(5, BlurMaskFilter.Blur.OUTER);
    Paint shadowPaint = new Paint();
    shadowPaint.setMaskFilter(blurFilter);

    int[] offsetXY = new int[2];
    Bitmap shadowImage = originalBitmap.extractAlpha(shadowPaint, offsetXY);

    /* Need to convert shadowImage from 8-bit to ARGB here. */
    Bitmap shadowImage32 = shadowImage.copy(Bitmap.Config.ARGB_8888, true);
    Canvas c = new Canvas(shadowImage32);
    c.drawBitmap(originalBitmap, -offsetXY[0], -offsetXY[1], null);

    return shadowImage32;
}
person PeterE    schedule 06.05.2014
comment
Работает блестяще! - person waseefakhtar; 18.02.2019

Для API 21(5.0)+ добавьте android:elevation="4dp" или android:translationZ="4dp" для просмотра описания. Документация

Атрибут высоты

person Artyom    schedule 01.07.2016

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

shadow.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
  <gradient
    android:startColor="#002e3436"
    android:endColor="#992e3436"
    android:angle="90" />
</shape>

И в поле зрения

<View 
    android:id="@+id/divider" 
    android:background="@drawable/shadow"
    android:layout_width="match_parent" 
    android:layout_height="5dp"/>
person Pradeep Kumar Kushwaha    schedule 14.03.2017