From e8b90f67885d33685ba4a7a0c6ac82dc70b977f5 Mon Sep 17 00:00:00 2001 From: Jakob Grabner <285173036@qq.com> Date: Thu, 13 Aug 2015 21:56:24 +0200 Subject: [PATCH] Edit: Calling setupPaints() after setting a color is no longer necessary. Added: Bitmap clipping support. Added: Documentation. --- .../circleprogress/CircleProgressView.java | 303 +++++++++++++----- .../src/main/res/values/attrs.xml | 28 +- .../at/grabner/circleview/MainActivity.java | 28 +- ExampleApp/src/main/res/drawable/mask.png | Bin 0 -> 18102 bytes aar/CircleProgressView.aar | Bin 17350 -> 18323 bytes 5 files changed, 274 insertions(+), 85 deletions(-) create mode 100644 ExampleApp/src/main/res/drawable/mask.png diff --git a/CircleProgressView/src/main/java/at/grabner/circleprogress/CircleProgressView.java b/CircleProgressView/src/main/java/at/grabner/circleprogress/CircleProgressView.java index 39ffed4..8365d0f 100644 --- a/CircleProgressView/src/main/java/at/grabner/circleprogress/CircleProgressView.java +++ b/CircleProgressView/src/main/java/at/grabner/circleprogress/CircleProgressView.java @@ -3,11 +3,14 @@ import android.animation.TimeInterpolator; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Paint.Style; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; @@ -83,7 +86,7 @@ public class CircleProgressView extends View { private final int mBarColorStandard = 0xff009688; //stylish blue private int mContourColor = 0xAA000000; private int mSpinnerColor = mBarColorStandard; //stylish blue - private int mFillColor = 0x00000000; //transparent + private int mBackgroundCircleColor = 0x00000000; //transparent private int mRimColor = 0xAA83d0c9; private int mTextColor = 0xFF000000; private int mUnitColor = 0xFF000000; @@ -97,15 +100,16 @@ public class CircleProgressView extends View { //Paints private Paint mBarPaint = new Paint(); private Paint mBarSpinnerPaint = new Paint(); - private Paint mCirclePaint = new Paint(); + private Paint mBackgroundCirclePaint = new Paint(); private Paint mRimPaint = new Paint(); private Paint mTextPaint = new Paint(); private Paint mUnitTextPaint = new Paint(); private Paint mContourPaint = new Paint(); //Rectangles private RectF mCircleBounds = new RectF(); - private RectF mInnerCircleBounds = new RectF(); - private RectF mTextBounds = new RectF(); + private RectF mInnerCircleBound = new RectF(); + private RectF mOuterTextBounds = new RectF(); + private RectF mActualTextBounds = new RectF(); private RectF mUnitBounds = new RectF(); private RectF mCircleOuterContour = new RectF(); private RectF mCircleInnerContour = new RectF(); @@ -146,6 +150,12 @@ public class CircleProgressView extends View { private boolean mShowUnit = false; + + + //clipping + private Bitmap mClippingBitmap; + private Paint mMaskPaint; + /** * Relative size of the unite string to the value string. */ @@ -154,6 +164,10 @@ public class CircleProgressView extends View { + + + + //endregion members /** @@ -167,6 +181,10 @@ public CircleProgressView(Context context, AttributeSet attrs) { parseAttributes(context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView)); + + mMaskPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mMaskPaint.setFilterBitmap(false); + mMaskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); } /** @@ -221,8 +239,8 @@ private void parseAttributes(TypedArray a) { setRimColor(a.getColor(R.styleable.CircleProgressView_rimColor, mRimColor)); - setFillColor(a.getColor(R.styleable.CircleProgressView_fillColor, - mFillColor)); + setBackgroundCircleColor(a.getColor(R.styleable.CircleProgressView_fillColor, + mBackgroundCircleColor)); setContourColor(a.getColor(R.styleable.CircleProgressView_contourColor, mContourColor)); setContourSize(a.getDimension(R.styleable.CircleProgressView_contourSize, mContourSize)); @@ -308,7 +326,7 @@ private RectF getInnerCircleRect(RectF _circleBounds) { private float calcTextSizeForCircle(String _text, Paint _textPaint, RectF _circleBounds) { - //get mTextBounds bounds + //get mActualTextBounds bounds RectF innerCircleBounds = getInnerCircleRect(_circleBounds); return calcTextSizeForRect(_text, _textPaint, innerCircleBounds); @@ -346,17 +364,33 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { mLayoutHeight = h; setupBounds(); - setupPaints(); + setupBarPaint(); + + if (mClippingBitmap != null) { + mClippingBitmap = Bitmap.createScaledBitmap(mClippingBitmap, getWidth(), getHeight(), false); + } + invalidate(); } //region setter / getter + /** + * + * @param _relativeUniteSize The relative size (scale factor) of the unit text size to the text size. + * Especially useful for autotextsize=true; + */ + public void setRelativeUniteSize(float _relativeUniteSize) { + mRelativeUniteSize = _relativeUniteSize; + } public Paint.Cap getSpinnerStrokeCap() { return mSpinnerStrokeCap; } + /** + * @param _spinnerStrokeCap The stroke cap of the progress bar in spinning mode. + */ public void setSpinnerStrokeCap(Paint.Cap _spinnerStrokeCap) { mSpinnerStrokeCap = _spinnerStrokeCap; } @@ -365,6 +399,10 @@ public Paint.Cap getBarStrokeCap() { return mBarStrokeCap; } + /** + * + * @param _barStrokeCap The stroke cap of the progress bar. + */ public void setBarStrokeCap(Paint.Cap _barStrokeCap) { mBarStrokeCap = _barStrokeCap; } @@ -373,23 +411,32 @@ public int getContourColor() { return mContourColor; } + /** + * + * @param _contourColor The color of the background contour of the circle. + */ public void setContourColor(int _contourColor) { mContourColor = _contourColor; + setupContourPaint(); } public float getContourSize() { return mContourSize; } + /** + * + * @param _contourSize The size of the background contour of the circle. + */ public void setContourSize(float _contourSize) { mContourSize = _contourSize; } /** * Set the text in the mCurrentValue bar. If no text (null or empty) is specified, - * * the current percentage value is used - * * (max value and current value are mandatory to do so). - * * + * the current percentage value is used + * max value and current value are mandatory to do so). + * @param text The text to show */ public void setText(String text) { if (text == null || text.isEmpty()) { @@ -406,6 +453,11 @@ public String getUnit() { return mUnit; } + /** + * + * @param _unit The unit to show next to the current value. + * You also need to set {@link #setShowUnit(boolean)} to true. + */ public void setUnit(String _unit) { if (_unit == null) { mUnit = ""; @@ -447,7 +499,7 @@ public boolean isShowPercentAsAutoValue() { /** * If true and no text was specified. The percentage (max value, current value) is shown. - * If false the current value is shown. + * If false the current value is shown. If a text was specified the text is shown. * @param _showPercentAsAutoValue bool */ public void setShowPercentAsAutoValue(boolean _showPercentAsAutoValue) { @@ -460,7 +512,7 @@ public int getTextSize() { /** * If text size was not set, it is automatically calculated - * @param textSize The text size or 0 enable automatic size (default) + * @param textSize The text size or 0 to enable automatic size (default) */ public void setTextSize(int textSize) { if (textSize > 0) { @@ -475,6 +527,11 @@ public double getMaxValue() { return mMaxValue; } + /** + * The max value of the progress bar. Used to calculate the percentage of the current value. + * The bar fills according to the percentage. The default value is 100. + * @param _maxValue The max value. + */ public void setMaxValue(float _maxValue) { mMaxValue = _maxValue; } @@ -519,11 +576,15 @@ public boolean isShowUnit() { return mShowUnit; } + /** + * + * @param _showUnit True to show unite, flas to hide. + */ public void setShowUnit(boolean _showUnit) { mShowUnit = _showUnit; mTextLength = 0; // triggers recalculating text sizes invalidate(); - mInnerCircleBounds = getInnerCircleRect(mCircleBounds); + mOuterTextBounds = getInnerCircleRect(mCircleBounds); } @@ -570,6 +631,10 @@ public int getBarWidth() { return mBarWidth; } + /** + * + * @param barWidth The width of the progress bar in pixel. + */ public void setBarWidth(int barWidth) { this.mBarWidth = barWidth; } @@ -578,33 +643,54 @@ public int[] getBarColors() { return mBarColors; } + + /** + *Sets the color of progress bar. + * @param barColors One or more colors. If more than one color is specified, a gradient of the colors is used. + * + */ public void setBarColor(int... barColors) { if (barColors.length == 1) { this.mBarColors = new int[]{barColors[0], barColors[0]}; } else { this.mBarColors = barColors; } - + setupBarPaint(); } + /** + * + * @param _color The color of progress the bar in spinning mode. + */ public void setSpinBarColor(int _color) { mSpinnerColor = _color; + setupBarSpinnerPaint(); } - public int getFillColor() { - return mFillColor; + public int getBackgroundCircleColor() { + return mBackgroundCircleColor; } - public void setFillColor(int circleColor) { - this.mFillColor = circleColor; + /** + * Sets the background color of the entire Progress Circle. + * @param circleColor the color. + */ + public void setBackgroundCircleColor(int circleColor) { + this.mBackgroundCircleColor = circleColor; + setupBackgroundCirclePaint(); } public int getRimColor() { return mRimColor; } + /** + * + * @param rimColor The color of the rim around the Circle. + */ public void setRimColor(int rimColor) { this.mRimColor = rimColor; + setupRimPaint(); } public Shader getRimShader() { @@ -629,14 +715,20 @@ public int getTextColor() { /** * * - * @param textColor the color or -1 to use auto color (depending on bar colors) + * @param textColor the color or -1 to use auto color (depending on bar colors and current value) */ public void setTextColor(int textColor) { this.mTextColor = textColor; + setupTextPaint(); } - public void setUnitColor(int textColor) { - this.mUnitColor = textColor; + /** + * the color or -1 to use auto color (depending on bar colors and current value) + * @param unitColor The color. + */ + public void setUnitColor(int unitColor) { + this.mUnitColor = unitColor; + setupUnitTextPaint(); } public float getSpinSpeed() { @@ -644,7 +736,7 @@ public float getSpinSpeed() { } /** - * The amount of degree to move the bar by on each draw + * The amount of degree to move the bar on every draw call. * @param spinSpeed the speed of the spinner */ public void setSpinSpeed(float spinSpeed) { @@ -655,31 +747,110 @@ public int getRimWidth() { return mRimWidth; } + /** + * + * @param rimWidth The width in pixel of the rim around the circle + */ public void setRimWidth(int rimWidth) { this.mRimWidth = rimWidth; } + /** + * + * @return The number of ms to wait between each draw call. + */ public int getDelayMillis() { return mDelayMillis; } + /** + * + * @param delayMillis The number of ms to wait between each draw call. + */ public void setDelayMillis(int delayMillis) { this.mDelayMillis = delayMillis; } + /** + * @param _clippingBitmap The bitmap used for clipping. Set to null to disable clipping. + * Default: No clipping. + */ + public void setClippingBitmap(Bitmap _clippingBitmap) { + + if(getWidth() > 0 && getHeight() > 0){ + mClippingBitmap = Bitmap.createScaledBitmap(_clippingBitmap, getWidth(), getHeight(), false); + }else{ + mClippingBitmap = _clippingBitmap; + } + if (mClippingBitmap == null) { + // enable HW acceleration + setLayerType(View.LAYER_TYPE_HARDWARE, null); + }else{ + // disable HW acceleration + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + } + + + /** + * + * @return The relative size (scale factor) of the unit text size to the text size + */ + public float getRelativeUniteSize() { + return mRelativeUniteSize; + } + //endregion getter / setter //---------------------------------- //region Setting up stuff //---------------------------------- - /** - * Set the properties of the paints we're using to - * draw all the things. - * - * Call this if you change colors after the view was drawn - */ - public void setupPaints() { + + + private void setupContourPaint() { + mContourPaint.setColor(mContourColor); + mContourPaint.setAntiAlias(true); + mContourPaint.setStyle(Style.STROKE); + mContourPaint.setStrokeWidth(mContourSize); + } + + private void setupUnitTextPaint() { + mUnitTextPaint.setColor(mUnitColor); + mUnitTextPaint.setStyle(Style.FILL); + mUnitTextPaint.setAntiAlias(true); + mUnitTextPaint.setTextSize(getTextSize()); + } + + private void setupTextPaint() { + mTextPaint.setColor(mTextColor); + mTextPaint.setStyle(Style.FILL); + mTextPaint.setAntiAlias(true); + mTextPaint.setTextSize(getTextSize()); + } + + private void setupBackgroundCirclePaint() { + mBackgroundCirclePaint.setColor(mBackgroundCircleColor); + mBackgroundCirclePaint.setAntiAlias(true); + mBackgroundCirclePaint.setStyle(Style.FILL); + } + + private void setupRimPaint() { + mRimPaint.setColor(mRimColor); + mRimPaint.setAntiAlias(true); + mRimPaint.setStyle(Style.STROKE); + mRimPaint.setStrokeWidth(mRimWidth); + } + + private void setupBarSpinnerPaint() { + mBarSpinnerPaint.setAntiAlias(true); + mBarSpinnerPaint.setStrokeCap(mSpinnerStrokeCap); + mBarSpinnerPaint.setStyle(Style.STROKE); + mBarSpinnerPaint.setStrokeWidth(mBarWidth); + mBarSpinnerPaint.setColor(mSpinnerColor); + } + + private void setupBarPaint() { mBarPaint.setShader(new SweepGradient(mCircleBounds.centerX(), mCircleBounds.centerY(), mBarColors, null)); Matrix matrix = new Matrix(); mBarPaint.getShader().getLocalMatrix(matrix); @@ -694,36 +865,6 @@ public void setupPaints() { mBarPaint.setStrokeCap(mBarStrokeCap); mBarPaint.setStyle(Style.STROKE); mBarPaint.setStrokeWidth(mBarWidth); - - mBarSpinnerPaint.setAntiAlias(true); - mBarSpinnerPaint.setStrokeCap(mSpinnerStrokeCap); - mBarSpinnerPaint.setStyle(Style.STROKE); - mBarSpinnerPaint.setStrokeWidth(mBarWidth); - mBarSpinnerPaint.setColor(mSpinnerColor); - - mRimPaint.setColor(mRimColor); - mRimPaint.setAntiAlias(true); - mRimPaint.setStyle(Style.STROKE); - mRimPaint.setStrokeWidth(mRimWidth); - - mCirclePaint.setColor(mFillColor); - mCirclePaint.setAntiAlias(true); - mCirclePaint.setStyle(Style.FILL); - - mTextPaint.setColor(mTextColor); - mTextPaint.setStyle(Style.FILL); - mTextPaint.setAntiAlias(true); - mTextPaint.setTextSize(getTextSize()); - - mUnitTextPaint.setColor(mUnitColor); - mUnitTextPaint.setStyle(Style.FILL); - mUnitTextPaint.setAntiAlias(true); - mUnitTextPaint.setTextSize(getTextSize()); - - mContourPaint.setColor(mContourColor); - mContourPaint.setAntiAlias(true); - mContourPaint.setStyle(Style.STROKE); - mContourPaint.setStrokeWidth(mContourSize); } /** @@ -751,7 +892,11 @@ private void setupBounds() { mPaddingTop + mBarWidth, width - mPaddingRight - mBarWidth, height - mPaddingBottom - mBarWidth); - mInnerCircleBounds = getInnerCircleRect(mCircleBounds); + mInnerCircleBound = new RectF(mPaddingLeft + (mBarWidth * 1.5f), + mPaddingTop + (mBarWidth * 1.5f), + width - mPaddingRight - (mBarWidth * 1.5f), + height - mPaddingBottom - (mBarWidth * 1.5f)); + mOuterTextBounds = getInnerCircleRect(mCircleBounds); mCircleInnerContour = new RectF(mCircleBounds.left + (mRimWidth / 2.0f) + (mContourSize / 2.0f), mCircleBounds.top + (mRimWidth / 2.0f) + (mContourSize / 2.0f), mCircleBounds.right - (mRimWidth / 2.0f) - (mContourSize / 2.0f), mCircleBounds.bottom - (mRimWidth / 2.0f) - (mContourSize / 2.0f)); mCircleOuterContour = new RectF(mCircleBounds.left - (mRimWidth / 2.0f) - (mContourSize / 2.0f), mCircleBounds.top - (mRimWidth / 2.0f) - (mContourSize / 2.0f), mCircleBounds.right + (mRimWidth / 2.0f) + (mContourSize / 2.0f), mCircleBounds.bottom + (mRimWidth / 2.0f) + (mContourSize / 2.0f)); @@ -765,6 +910,7 @@ private void setupBounds() { protected void onDraw(Canvas canvas) { super.onDraw(canvas); + if (DEBUG) { drawDebug(canvas); @@ -772,8 +918,8 @@ protected void onDraw(Canvas canvas) { float degrees = (360f / mMaxValue * mCurrentValue); - //Draw the inner circle - canvas.drawArc(mCircleBounds, 360, 360, false, mCirclePaint); + //Draw the background circle + canvas.drawArc(mInnerCircleBound, 360, 360, false, mBackgroundCirclePaint); //Draw the rim if(mRimWidth > 0){ canvas.drawArc(mCircleBounds, 360, 360, false, mRimPaint); @@ -802,6 +948,11 @@ protected void onDraw(Canvas canvas) { drawCircleWithNumber(canvas, degrees); } + + if (mClippingBitmap != null) { + canvas.drawBitmap(mClippingBitmap, 0, 0, mMaskPaint); + } + } private void drawSpinningArc(Canvas canvas) { @@ -820,7 +971,7 @@ private void drawDebug(Canvas canvas){ canvas.drawRect(mCircleBounds, innerRectPaint); innerRectPaint.setColor(Color.MAGENTA); - canvas.drawRect(mInnerCircleBounds, innerRectPaint); + canvas.drawRect(mOuterTextBounds, innerRectPaint); } private void drawCircleWithNumber(Canvas canvas, float _degrees) { @@ -856,33 +1007,33 @@ private void drawCircleWithNumber(Canvas canvas, float _degrees) { update = true; mTextLength = text.length(); if (mTextLength == 1) { - mInnerCircleBounds = new RectF(mInnerCircleBounds.left + (mInnerCircleBounds.width() * 0.1f), mInnerCircleBounds.top, mInnerCircleBounds.right - (mInnerCircleBounds.width() * 0.1f), mInnerCircleBounds.bottom); + mOuterTextBounds = new RectF(mOuterTextBounds.left + (mOuterTextBounds.width() * 0.1f), mOuterTextBounds.top, mOuterTextBounds.right - (mOuterTextBounds.width() * 0.1f), mOuterTextBounds.bottom); }else { - mInnerCircleBounds = getInnerCircleRect(mCircleBounds); + mOuterTextBounds = getInnerCircleRect(mCircleBounds); } - RectF textRect = mInnerCircleBounds; + RectF textRect = mOuterTextBounds; if (mShowUnit) { //shrink text Rect so that there is space for the unit - textRect = new RectF(mInnerCircleBounds.left, mInnerCircleBounds.top, mInnerCircleBounds.right - ((mInnerCircleBounds.width() * (mRelativeUniteSize))*relativeGap), mInnerCircleBounds.bottom); + textRect = new RectF(mOuterTextBounds.left, mOuterTextBounds.top, mOuterTextBounds.right - ((mOuterTextBounds.width() * (mRelativeUniteSize))*relativeGap), mOuterTextBounds.bottom); } mTextPaint.setTextSize(calcTextSizeForRect(text, mTextPaint, textRect)* mTextScale); - mTextBounds = getTextBounds(text, mTextPaint, textRect); // center text in text rect + mActualTextBounds = getTextBounds(text, mTextPaint, textRect); // center text in text rect } } else { - mTextBounds = getTextBounds(text, mTextPaint, mCircleBounds); //center text in circle + mActualTextBounds = getTextBounds(text, mTextPaint, mCircleBounds); //center text in circle } if (DEBUG){ Paint rectPaint = new Paint(); rectPaint.setColor(Color.GREEN); - canvas.drawRect(mTextBounds, rectPaint); + canvas.drawRect(mActualTextBounds, rectPaint); } - canvas.drawText(text, mTextBounds.left-(mTextPaint.getTextSize()*0.09f), mTextBounds.bottom, mTextPaint); + canvas.drawText(text, mActualTextBounds.left-(mTextPaint.getTextSize()*0.09f), mActualTextBounds.bottom, mTextPaint); if (mShowUnit) { @@ -894,11 +1045,11 @@ private void drawCircleWithNumber(Canvas canvas, float _degrees) { } if (update) { //calc unit text position - mUnitBounds = new RectF(mInnerCircleBounds.left + (mInnerCircleBounds.width() * (1 - mRelativeUniteSize) * relativeGap), mInnerCircleBounds.top, mInnerCircleBounds.right, mInnerCircleBounds.bottom); + mUnitBounds = new RectF(mOuterTextBounds.left + (mOuterTextBounds.width() * (1 - mRelativeUniteSize) * relativeGap), mOuterTextBounds.top, mOuterTextBounds.right, mOuterTextBounds.bottom); mUnitTextPaint.setTextSize(calcTextSizeForRect(mUnit, mUnitTextPaint, mUnitBounds) * mUnitScale); mUnitBounds = getTextBounds(mUnit, mUnitTextPaint, mUnitBounds); //move unite to top of text - float dy = mTextBounds.top - mUnitBounds.top; + float dy = mActualTextBounds.top - mUnitBounds.top; mUnitBounds.offset(0, dy); } @@ -918,14 +1069,14 @@ private void drawCircleWithNumber(Canvas canvas, float _degrees) { //region important getter / setter //---------------------------------- /** - * Turn off spin mode + * Turn off spinning mode */ public void stopSpinning() { mAnimationHandler.sendEmptyMessage(AnimationMsg.STOP_SPINNING.ordinal()); } /** - * Puts the view on spin mode + * Puts the view in spin mode */ public void spin() { mAnimationHandler.sendEmptyMessage(AnimationMsg.START_SPINNING.ordinal()); diff --git a/CircleProgressView/src/main/res/values/attrs.xml b/CircleProgressView/src/main/res/values/attrs.xml index 5081264..8a43e04 100644 --- a/CircleProgressView/src/main/res/values/attrs.xml +++ b/CircleProgressView/src/main/res/values/attrs.xml @@ -1,27 +1,39 @@ + - + - + + + + + - - - + + + - + + + + + + - - + + + + \ No newline at end of file diff --git a/ExampleApp/src/main/java/at/grabner/circleview/MainActivity.java b/ExampleApp/src/main/java/at/grabner/circleview/MainActivity.java index 82f53c4..eb1b40e 100644 --- a/ExampleApp/src/main/java/at/grabner/circleview/MainActivity.java +++ b/ExampleApp/src/main/java/at/grabner/circleview/MainActivity.java @@ -1,5 +1,9 @@ package at.grabner.circleview; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; @@ -75,7 +79,7 @@ public void onStartTrackingTouch(SeekBar seekBar) { @Override public void onStopTrackingTouch(SeekBar seekBar) { - mCircleView.setValueAnimated(seekBar.getProgress(),1500); + mCircleView.setValueAnimated(seekBar.getProgress(), 1500); mSwitchSpin.setChecked(false); } }); @@ -100,6 +104,9 @@ public void onStopTrackingTouch(SeekBar seekBar) { }); + + mCircleView.setBackgroundCircleColor(Color.RED); + } @@ -131,5 +138,24 @@ protected void onStart() { mCircleView.setValue(0); mCircleView.setValueAnimated(42); } + + public static Bitmap getMaskingBitmap(Resources res, int sourceResId) { + BitmapFactory.Options options = new BitmapFactory.Options(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + options.inMutable = true; + } + options.inPreferredConfig = Bitmap.Config.ARGB_8888; + Bitmap source = BitmapFactory.decodeResource(res, sourceResId, options); + Bitmap bitmap; + if (source.isMutable()) { + bitmap = source; + } else { + bitmap = source.copy(Bitmap.Config.ARGB_8888, true); + source.recycle(); + } + bitmap.setHasAlpha(true); + + return bitmap; + } } diff --git a/ExampleApp/src/main/res/drawable/mask.png b/ExampleApp/src/main/res/drawable/mask.png new file mode 100644 index 0000000000000000000000000000000000000000..8a527408fd03fa3e20cad86abe849484a7423bc7 GIT binary patch literal 18102 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 s0&Yc@asU7T delta 15929 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 bb1zU!1qJ{B000O82mr$Y008Yl00000AC|?*