public abstract class

RoundedBitmapDrawable

extends Drawable

 java.lang.Object

↳Drawable

↳androidx.core.graphics.drawable.RoundedBitmapDrawable

Gradle dependencies

compile group: 'androidx.core', name: 'core', version: '1.15.0-alpha02'

  • groupId: androidx.core
  • artifactId: core
  • version: 1.15.0-alpha02

Artifact androidx.core:core:1.15.0-alpha02 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.core:core com.android.support:support-compat

Androidx class mapping:

androidx.core.graphics.drawable.RoundedBitmapDrawable android.support.v4.graphics.drawable.RoundedBitmapDrawable

Overview

A Drawable that wraps a bitmap and can be drawn with rounded corners. You can create a RoundedBitmapDrawable from a file path, an input stream, or from a android.graphics.Bitmap object.

Also see the android.graphics.Bitmap class, which handles the management and transformation of raw bitmap graphics, and should be used when drawing to a .

Summary

Methods
public voiddraw(Canvas canvas)

public intgetAlpha()

public final BitmapgetBitmap()

Returns the bitmap used by this drawable to render.

public ColorFiltergetColorFilter()

public floatgetCornerRadius()

public intgetGravity()

Get the gravity used to position/stretch the bitmap within its bounds.

public intgetIntrinsicHeight()

public intgetIntrinsicWidth()

public intgetOpacity()

public final PaintgetPaint()

Returns the paint used to render this drawable.

public booleanhasAntiAlias()

Indicates whether anti-aliasing is enabled for this drawable.

public booleanhasMipMap()

Indicates whether the mipmap hint is enabled on this drawable's bitmap.

public booleanisCircular()

protected voidonBoundsChange(Rect bounds)

public voidsetAlpha(int alpha)

public voidsetAntiAlias(boolean aa)

Enables or disables anti-aliasing for this drawable.

public voidsetCircular(boolean circular)

Sets the image shape to circular.

public voidsetColorFilter(ColorFilter cf)

public voidsetCornerRadius(float cornerRadius)

Sets the corner radius to be applied when drawing the bitmap.

public voidsetDither(boolean dither)

public voidsetFilterBitmap(boolean filter)

public voidsetGravity(int gravity)

Set the gravity used to position/stretch the bitmap within its bounds.

public voidsetMipMap(boolean mipMap)

Enables or disables the mipmap hint for this drawable's bitmap.

public voidsetTargetDensity(Canvas canvas)

Set the density scale at which this drawable will be rendered.

public voidsetTargetDensity(DisplayMetrics metrics)

Set the density scale at which this drawable will be rendered.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Methods

public final Paint getPaint()

Returns the paint used to render this drawable.

public final Bitmap getBitmap()

Returns the bitmap used by this drawable to render. May be null.

public void setTargetDensity(Canvas canvas)

Set the density scale at which this drawable will be rendered. This method assumes the drawable will be rendered at the same density as the specified canvas.

Parameters:

canvas: The Canvas from which the density scale must be obtained.

See also: android.graphics.Bitmap, android.graphics.Bitmap

public void setTargetDensity(DisplayMetrics metrics)

Set the density scale at which this drawable will be rendered.

Parameters:

metrics: The DisplayMetrics indicating the density scale for this drawable.

See also: android.graphics.Bitmap, android.graphics.Bitmap

public int getGravity()

Get the gravity used to position/stretch the bitmap within its bounds.

Returns:

the gravity applied to the bitmap

See also:

public void setGravity(int gravity)

Set the gravity used to position/stretch the bitmap within its bounds.

Parameters:

gravity: the gravity

See also:

public void setMipMap(boolean mipMap)

Enables or disables the mipmap hint for this drawable's bitmap. See Bitmap for more information. If the bitmap is null, or the current API version does not support setting a mipmap hint, calling this method has no effect.

Parameters:

mipMap: True if the bitmap should use mipmaps, false otherwise.

See also: RoundedBitmapDrawable.hasMipMap()

public boolean hasMipMap()

Indicates whether the mipmap hint is enabled on this drawable's bitmap.

Returns:

True if the mipmap hint is set, false otherwise. If the bitmap is null, this method always returns false.

See also: RoundedBitmapDrawable.setMipMap(boolean)

public void setAntiAlias(boolean aa)

Enables or disables anti-aliasing for this drawable. Anti-aliasing affects the edges of the bitmap only so it applies only when the drawable is rotated.

Parameters:

aa: True if the bitmap should be anti-aliased, false otherwise.

See also: RoundedBitmapDrawable.hasAntiAlias()

public boolean hasAntiAlias()

Indicates whether anti-aliasing is enabled for this drawable.

Returns:

True if anti-aliasing is enabled, false otherwise.

See also: RoundedBitmapDrawable.setAntiAlias(boolean)

public void setFilterBitmap(boolean filter)

public void setDither(boolean dither)

public void draw(Canvas canvas)

public void setAlpha(int alpha)

public int getAlpha()

public void setColorFilter(ColorFilter cf)

public ColorFilter getColorFilter()

public void setCircular(boolean circular)

Sets the image shape to circular.

This overwrites any calls made to RoundedBitmapDrawable.setCornerRadius(float) so far.

public boolean isCircular()

Returns:

true if the image is circular, else false.

public void setCornerRadius(float cornerRadius)

Sets the corner radius to be applied when drawing the bitmap.

protected void onBoundsChange(Rect bounds)

public float getCornerRadius()

Returns:

The corner radius applied when drawing the bitmap.

public int getIntrinsicWidth()

public int getIntrinsicHeight()

public int getOpacity()

Source

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package androidx.core.graphics.drawable;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.view.Gravity;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * A Drawable that wraps a bitmap and can be drawn with rounded corners. You can create a
 * RoundedBitmapDrawable from a file path, an input stream, or from a
 * {@link android.graphics.Bitmap} object.
 * <p>
 * Also see the {@link android.graphics.Bitmap} class, which handles the management and
 * transformation of raw bitmap graphics, and should be used when drawing to a
 * {@link android.graphics.Canvas}.
 * </p>
 */
public abstract class RoundedBitmapDrawable extends Drawable {
    private static final int DEFAULT_PAINT_FLAGS =
            Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG;
    final Bitmap mBitmap;
    private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
    private int mGravity = Gravity.FILL;
    private final Paint mPaint = new Paint(DEFAULT_PAINT_FLAGS);
    private final BitmapShader mBitmapShader;
    private final Matrix mShaderMatrix = new Matrix();
    private float mCornerRadius;

    final Rect mDstRect = new Rect();   // Gravity.apply() sets this
    private final RectF mDstRectF = new RectF();

    private boolean mApplyGravity = true;
    private boolean mIsCircular;

    // These are scaled to match the target density.
    private int mBitmapWidth;
    private int mBitmapHeight;

    /**
     * Returns the paint used to render this drawable.
     */
    @NonNull
    public final Paint getPaint() {
        return mPaint;
    }

    /**
     * Returns the bitmap used by this drawable to render. May be null.
     */
    @Nullable
    public final Bitmap getBitmap() {
        return mBitmap;
    }

    private void computeBitmapSize() {
        mBitmapWidth = mBitmap.getScaledWidth(mTargetDensity);
        mBitmapHeight = mBitmap.getScaledHeight(mTargetDensity);
    }

    /**
     * Set the density scale at which this drawable will be rendered. This
     * method assumes the drawable will be rendered at the same density as the
     * specified canvas.
     *
     * @param canvas The Canvas from which the density scale must be obtained.
     *
     * @see android.graphics.Bitmap#setDensity(int)
     * @see android.graphics.Bitmap#getDensity()
     */
    public void setTargetDensity(@NonNull Canvas canvas) {
        setTargetDensity(canvas.getDensity());
    }

    /**
     * Set the density scale at which this drawable will be rendered.
     *
     * @param metrics The DisplayMetrics indicating the density scale for this drawable.
     *
     * @see android.graphics.Bitmap#setDensity(int)
     * @see android.graphics.Bitmap#getDensity()
     */
    public void setTargetDensity(@NonNull DisplayMetrics metrics) {
        setTargetDensity(metrics.densityDpi);
    }

    /**
     * Set the density at which this drawable will be rendered.
     *
     * @param density The density scale for this drawable.
     *
     * @see android.graphics.Bitmap#setDensity(int)
     * @see android.graphics.Bitmap#getDensity()
     */
    public void setTargetDensity(int density) {
        if (mTargetDensity != density) {
            mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
            if (mBitmap != null) {
                computeBitmapSize();
            }
            invalidateSelf();
        }
    }

    /**
     * Get the gravity used to position/stretch the bitmap within its bounds.
     *
     * @return the gravity applied to the bitmap
     *
     * @see android.view.Gravity
     */
    public int getGravity() {
        return mGravity;
    }

    /**
     * Set the gravity used to position/stretch the bitmap within its bounds.
     *
     * @param gravity the gravity
     *
     * @see android.view.Gravity
     */
    public void setGravity(int gravity) {
        if (mGravity != gravity) {
            mGravity = gravity;
            mApplyGravity = true;
            invalidateSelf();
        }
    }

    /**
     * Enables or disables the mipmap hint for this drawable's bitmap.
     * See {@link Bitmap#setHasMipMap(boolean)} for more information.
     *
     * If the bitmap is null, or the current API version does not support setting a mipmap hint,
     * calling this method has no effect.
     *
     * @param mipMap True if the bitmap should use mipmaps, false otherwise.
     *
     * @see #hasMipMap()
     */
    public void setMipMap(boolean mipMap) {
        throw new UnsupportedOperationException(); // must be overridden in subclasses
    }

    /**
     * Indicates whether the mipmap hint is enabled on this drawable's bitmap.
     *
     * @return True if the mipmap hint is set, false otherwise. If the bitmap
     *         is null, this method always returns false.
     *
     * @see #setMipMap(boolean)
     */
    public boolean hasMipMap() {
        throw new UnsupportedOperationException(); // must be overridden in subclasses
    }

    /**
     * Enables or disables anti-aliasing for this drawable. Anti-aliasing affects
     * the edges of the bitmap only so it applies only when the drawable is rotated.
     *
     * @param aa True if the bitmap should be anti-aliased, false otherwise.
     *
     * @see #hasAntiAlias()
     */
    public void setAntiAlias(boolean aa) {
        mPaint.setAntiAlias(aa);
        invalidateSelf();
    }

    /**
     * Indicates whether anti-aliasing is enabled for this drawable.
     *
     * @return True if anti-aliasing is enabled, false otherwise.
     *
     * @see #setAntiAlias(boolean)
     */
    public boolean hasAntiAlias() {
        return mPaint.isAntiAlias();
    }

    @Override
    public void setFilterBitmap(boolean filter) {
        mPaint.setFilterBitmap(filter);
        invalidateSelf();
    }

    @Override
    public void setDither(boolean dither) {
        mPaint.setDither(dither);
        invalidateSelf();
    }

    void gravityCompatApply(int gravity, int bitmapWidth, int bitmapHeight,
            Rect bounds, Rect outRect) {
        throw new UnsupportedOperationException();
    }

    void updateDstRect() {
        if (mApplyGravity) {
            if (mIsCircular) {
                final int minDimen = Math.min(mBitmapWidth, mBitmapHeight);
                gravityCompatApply(mGravity, minDimen, minDimen, getBounds(), mDstRect);

                // inset the drawing rectangle to the largest contained square,
                // so that a circle will be drawn
                final int minDrawDimen = Math.min(mDstRect.width(), mDstRect.height());
                final int insetX = Math.max(0, (mDstRect.width() - minDrawDimen) / 2);
                final int insetY = Math.max(0, (mDstRect.height() - minDrawDimen) / 2);
                mDstRect.inset(insetX, insetY);
                mCornerRadius = 0.5f * minDrawDimen;
            } else {
                gravityCompatApply(mGravity, mBitmapWidth, mBitmapHeight, getBounds(), mDstRect);
            }
            mDstRectF.set(mDstRect);

            if (mBitmapShader != null) {
                // setup shader matrix
                mShaderMatrix.setTranslate(mDstRectF.left,mDstRectF.top);
                mShaderMatrix.preScale(
                        mDstRectF.width() / mBitmap.getWidth(),
                        mDstRectF.height() / mBitmap.getHeight());
                mBitmapShader.setLocalMatrix(mShaderMatrix);
                mPaint.setShader(mBitmapShader);
            }

            mApplyGravity = false;
        }
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        final Bitmap bitmap = mBitmap;
        if (bitmap == null) {
            return;
        }

        updateDstRect();
        if (mPaint.getShader() == null) {
            canvas.drawBitmap(bitmap, null, mDstRect, mPaint);
        } else {
            canvas.drawRoundRect(mDstRectF, mCornerRadius, mCornerRadius, mPaint);
        }
    }

    @Override
    public void setAlpha(int alpha) {
        final int oldAlpha = mPaint.getAlpha();
        if (alpha != oldAlpha) {
            mPaint.setAlpha(alpha);
            invalidateSelf();
        }
    }

    @Override
    public int getAlpha() {
        return mPaint.getAlpha();
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        mPaint.setColorFilter(cf);
        invalidateSelf();
    }

    @Override
    public ColorFilter getColorFilter() {
        return mPaint.getColorFilter();
    }

    /**
     * Sets the image shape to circular.
     * <p>This overwrites any calls made to {@link #setCornerRadius(float)} so far.</p>
     */
    public void setCircular(boolean circular) {
        mIsCircular = circular;
        mApplyGravity = true;
        if (circular) {
            updateCircularCornerRadius();
            mPaint.setShader(mBitmapShader);
            invalidateSelf();
        } else {
            setCornerRadius(0);
        }
    }

    private void updateCircularCornerRadius() {
        final int minCircularSize = Math.min(mBitmapHeight, mBitmapWidth);
        mCornerRadius = minCircularSize / 2;
    }

    /**
     * @return <code>true</code> if the image is circular, else <code>false</code>.
     */
    public boolean isCircular() {
        return mIsCircular;
    }

    /**
     * Sets the corner radius to be applied when drawing the bitmap.
     */
    public void setCornerRadius(float cornerRadius) {
        if (mCornerRadius == cornerRadius) return;

        mIsCircular = false;
        if (isGreaterThanZero(cornerRadius)) {
            mPaint.setShader(mBitmapShader);
        } else {
            mPaint.setShader(null);
        }

        mCornerRadius = cornerRadius;
        invalidateSelf();
    }

    @Override
    protected void onBoundsChange(@NonNull Rect bounds) {
        super.onBoundsChange(bounds);
        if (mIsCircular) {
            updateCircularCornerRadius();
        }
        mApplyGravity = true;
    }

    /**
     * @return The corner radius applied when drawing the bitmap.
     */
    public float getCornerRadius() {
        return mCornerRadius;
    }

    @Override
    public int getIntrinsicWidth() {
        return mBitmapWidth;
    }

    @Override
    public int getIntrinsicHeight() {
        return mBitmapHeight;
    }

    @Override
    public int getOpacity() {
        if (mGravity != Gravity.FILL || mIsCircular) {
            return PixelFormat.TRANSLUCENT;
        }
        Bitmap bm = mBitmap;
        return (bm == null
                || bm.hasAlpha()
                || mPaint.getAlpha() < 255
                || isGreaterThanZero(mCornerRadius))
                ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
    }

    RoundedBitmapDrawable(Resources res, Bitmap bitmap) {
        if (res != null) {
            mTargetDensity = res.getDisplayMetrics().densityDpi;
        }

        mBitmap = bitmap;
        if (mBitmap != null) {
            computeBitmapSize();
            mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        } else {
            mBitmapWidth = mBitmapHeight = -1;
            mBitmapShader = null;
        }
    }

    private static boolean isGreaterThanZero(float toCompare) {
        return toCompare > 0.05f;
    }
}