ImageView с закругленными углами и внутренней тенью - PullRequest
17 голосов
/ 27 февраля 2012

Мне нужно сделать эскиз с закругленными углами и внутренней тенью.Обычно я делаю кадры 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 ()пока идет, но у меня заканчиваются идеи, как это сделать.

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

Спасибо!

1 Ответ

11 голосов
/ 07 марта 2012

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

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

РЕДАКТИРОВАТЬ: Спасибо @mykola за ссылку yt

...