Подтвердить что ты не робот

ImageView с закругленными углами и внутренней тенью

Мне нужно сделать эскиз с закругленными углами и внутренней тенью. Обычно я создаю кадры ImageView с 9 патчами, которые до сих пор хорошо меня обслуживали, но на этот раз для меня нужен внешний рисунок, а не только вокруг него. Это привело меня к расширению класса ImageView и переопределению метода onDraw().

public class ThumbnailImageView extends ImageView {

После многих учебников (спасибо StackOverflow!), я закончил с этим кодом для метода onDraw():

@Override
protected void onDraw(Canvas canvas) {
    if (mBitmap == null) {
        return;
    }

    int radius = 4;
    int padding = 2;
    int bleed = 2;
    RectF frame = new RectF(padding, padding, getWidth() - padding, getHeight() - padding);

    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setColor(0xFF000000);
    canvas.drawRoundRect(frame, radius, radius, mPaint);

    Shader bitmapShader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setColor(0xFF000000);
    mPaint.setMaskFilter(new BlurMaskFilter(bleed, Blur.INNER));
    mPaint.setShader(bitmapShader);
    canvas.drawRoundRect(frame, radius, radius, mPaint);
}

Что я в основном делаю, сначала рисует черный округлый прямоугольник, а затем рисует растровое изображение с закругленными углами с затухающими краями (с помощью BlurMaskFilter) поверх него. В результате я хочу: onDraw() result Значение mBitmap инициализируется в конструкторе ImageView следующим образом:

mDrawable = getDrawable();
if (mDrawable != null) {
    mBitmap = ((BitmapDrawable) mDrawable).getBitmap();
}

Проблема заключается в том, что я полностью переопределяю onDraw() (не вызывается super.onDraw()), поэтому я должен предварительно масштабировать все изображения до требуемого размера эскиза (например, 96x96), или только верхний левый угол изображения рисуется. То, что я хочу сделать, это воспользоваться всеми возможностями масштабирования, которые выполняет фреймворк, когда я назначаю следующие значения xml в ThumbnailImageView:

android:id="@+id/thumb"
android:layout_width="96dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"

Чтобы сделать это, я подумал, что должен каким-то образом вызвать super.onDraw(), одновременно получая нужные мне эффекты. Мне удалось получить закругленный прямоугольник, добавив путь обрезки к холсту, но я не могу найти способ добавить внутреннюю тень. Это новый код onDraw():

@Override
protected void onDraw(Canvas canvas) {
    int radius = 4;
    int padding = 4;        
    RectF frame = new RectF(padding, padding, getWidth() - padding, getHeight() - padding);
    Path clipPath = new Path();
    clipPath.addRoundRect(frame, radius, radius, Path.Direction.CW);
    canvas.clipPath(clipPath);
    super.onDraw(canvas);
    // add inner shadow
}

Я вижу две альтернативы:

1) Для правильного предварительного масштабирования растрового изображения ImageView. Но где это лучшее место? В нем конструктор? В методе onDraw(), где структура, похоже, делает это? Является ли каркас даже изменением размера любого растрового изображения или есть другой способ нарисовать масштабированное изображение на холсте, не будучи плохой для производительности?

2) Чтобы добавить внутренний теневой слой поверх того, что до сих пор рисует super.onDraw(), но у меня заканчиваются идеи о том, как это сделать.

Любая помощь будет оценена.

Спасибо!

4b9b3361

Ответ 1

Взгляните на презентационный материал Эрика (из квадрата) от конференции Oreilly AndoridOpen в прошлом году в его лекции под названием Красивый Android У этого есть тонна информации, которая должна помочь вам.

Мне жаль, что у них не было видео его презентации. Я не мог найти его. Извините.

EDIT: Спасибо @mykola за yt link