Использование закругленных углов

Существует хороший пост, сделанный популярным разработчиком Google Romain Guy, который показывает, как использовать закругленные углы, которые можно легко вырезать (называемый "StreamDrawable" в его код).

Сам образец очень хорошо работает на моей Galaxy S3 в портретном режиме, но у меня есть несколько проблем с ним:

  • если экран небольшой (например, на экранах qvga), показанные изображения обрезаются.

  • Если у меня есть бит-карта ввода, которая слишком мала, как я хочу ее показать, на выходном изображении будут размыты края. Даже на Galaxy S3, когда вы запускаете образец кода, и он на пейзаже, он выглядит ужасно:

    enter image description here

  • Я все еще не уверен в этом (так как я использую обходное решение для масштабирования изображения для использования примерного кода), но он считает, что даже это решение немного медленнее при использовании в listView. Может быть, для этого есть решение renderscript?

Не имеет значения, использую ли setImageDrawable или setBackgroundDrawable. Это должно быть что-то само по себе.

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

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

Как исправить эти проблемы и использовать этот отличный код?

Ответ 1

Я думаю, что решение, представленное на на этом веб-сайте, работает хорошо.

в отличие от других решений, он не вызывает утечки памяти, хотя он основан на решении Ромен Гай.

EDIT: теперь в библиотеке поддержки вы также можете использовать RoundedBitmapDrawable (используя RoundedBitmapDrawableFactory).

Ответ 2

У меня были некоторые проблемы с этим кодом, и я решил это.

Возможно, это тоже поможет:

1) в конструкторе хранят битмап в локальной переменной (например, private Bitmap bmp;)

2) переопределить еще два метода:

@Override
    public int getIntrinsicWidth() {
    return bmp.getWidth();
}

@Override
    public int getIntrinsicHeight() {
    return bmp.getHeight();
}

С уважением, DaRolla

Ответ 3

Основная проблема заключается в том, что у BitmapShader TileMode нет опции масштабирования. Вы заметили в источнике, что он установлен в Shader.TileMode.CLAMP, и документы описывают это как:

реплицируйте цвет края, если шейдер рисует вне своих исходных границ

Чтобы обойти это, есть три решения:

  • Ограничьте размер представления, в котором drawable используется для размера растрового изображения.
  • Ограничить область рисования; например, изменить:

    int width = bounds.width() - mMargin;
    int height = bounds.height() - mMargin;
    mRect.set(mMargin, mMargin, width, height);
    

    To:

    int width = Math.min(mBitmap.getWidth(), bounds.width()) - mMargin;
    int height = Math.min(mBitmap.getHeight(), bounds.height()) - mMargin;
    mRect.set(mMargin, mMargin, width, height);
    
  • Масштабируйте растровое изображение до размера извлекаемого. Я переместил создание шейдера в onBoundsChange() и решил создать новое растровое изображение здесь:

    bitmap = Bitmap.createScaledBitmap(mBitmap, width, height, true);
    mBitmapShader = new BitmapShader(bitmap,
            Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    

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