
ã¯ããã«
Androidçšã«éçºããå Žåãç»åããã¹ã¯ããã¿ã¹ã¯ãé »ç¹ã«çºçããŸãã ã»ãšãã©ã®å Žåãåçã®è§ãäžžãããããç»åãå®å
šã«äžžãããå¿
èŠããããŸãã ãã ããããè€éãªåœ¢åŒã®ãã¹ã¯ã䜿çšãããå ŽåããããŸãã
ãã®èšäºã§ã¯ããã®ãããªåé¡ã解決ããããã«Androidéçºè
ã®å
µåšåº«ã§å©çšå¯èœãªããŒã«ãåæããæãæåãããã®ãéžæããããšæããŸãã ãã®èšäºã¯ãäž»ã«ããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿çšããã«ããã¹ãã³ã°ãæåã§å®è£
ããå¿
èŠãããå Žåã«åœ¹ç«ã¡ãŸãã
èªè
ã¯Androidéçºã®çµéšããããCanvasãDrawableãããã³Bitmapã¯ã©ã¹ã«ç²ŸéããŠãããšæããŸãã
ãã®èšäºã§äœ¿çšãããŠããã³ãŒãã¯
GitHubã«ãããŸã ã
åé¡ã®å£°æ
ãããããããªããžã§ã¯ãã«ãã£ãŠè¡šããã2ã€ã®ç»åããããšããŸãã ãããã®1ã€ã«ã¯å
ã®ç»åãå«ãŸãã2çªç®ã«ã¯ã¢ã«ãã¡ãã£ãã«ã«ãã¹ã¯ãå«ãŸããŠããŸãã ãã¹ã¯ãé©çšããŠç»åã衚瀺ããå¿
èŠããããŸãã
éåžžããã¹ã¯ã¯ãªãœãŒã¹ã«ä¿åãããã€ã¡ãŒãžã¯ãããã¯ãŒã¯çµç±ã§ããŠã³ããŒããããŸããããã®äŸã§ã¯ãäž¡æ¹ã®ã€ã¡ãŒãžã次ã®ã³ãŒãã§ãªãœãŒã¹ããããŠã³ããŒããããŸãã
private void loadImages() { mPictureBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.picture); mMaskBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mask_circle).extractAlpha(); }
.extractAlpha()
泚æããŠ
.extractAlpha()
ããã®åŒã³åºãã¯ãALPHA_8æ§æã®ãããããããäœæããŸããã€ãŸãããã¯ã»ã«ããšã«1ãã€ããæ¶è²»ããããã®ãã¯ã»ã«ã®éæ床ããšã³ã³ãŒããããŸãã ãã¹ã¯ã®è²æ
å ±ã¯ãã€ããŒããéã°ããæšãŠãããšãã§ããããããã®åœ¢åŒã§ãã¹ã¯ãä¿åããããšã¯éåžžã«æçã§ãã
ç»åãã¢ããããŒããããã®ã§ã楜ããéšåã«é²ãããšãã§ããŸã-ãã¹ãã³ã°ã ããã«ã¯ã©ã®ããŒã«ã䜿çšã§ããŸããïŒ
PorterDuffã¢ãŒã
ææ¡ããããœãªã¥ãŒã·ã§ã³ã®1ã€ã¯ããã£ã³ãã¹ïŒCanvasïŒã§ã®ã€ã¡ãŒãžãªãŒããŒã¬ã€ã®PorterDuffã¢ãŒãã®äœ¿çšã§ãã ãããäœã§ãããããªãã¬ãã·ã¥ããŸãããã
çè«
è¡šèšæ³ãå°å
¥ããŸãïŒ
æšæºã®ããã« ïŒïŒ
- DaïŒãã¹ãã£ããŒã·ã§ã³ã¢ã«ãã¡ïŒ-ãã£ã³ãã¹ãã¯ã»ã«ã®å
ã®éæ床ã
- DcïŒå®å
è²ïŒ-ãã£ã³ãã¹ãã¯ã»ã«ã®åæè²ã
- SaïŒãœãŒã¹ã¢ã«ãã¡ïŒ-ãªãŒããŒã¬ã€ã€ã¡ãŒãžã®ãã¯ã»ã«ã®éæ床ã
- ScïŒãœãŒã¹ã«ã©ãŒïŒ-ãªãŒããŒã¬ã€ç»åã®ãã¯ã»ã«ã«ã©ãŒã
- Da '-é©çšåŸã®éæãªãã¹ã±ã«ãã£ã³ãã¹ã
- Dcã¯ãé©çšåŸã®ãã£ã³ãã¹ã®è²ã§ãã
ã¢ãŒãã¯ãDcãDaãSaãScã«å¿ããŠDa 'ããã³Dc'ã決å®ãããã«ãŒã«ã«ãã£ãŠæ±ºå®ãããŸãã
ãããã£ãŠãåãã¯ã»ã«ã«4ã€ã®ãã©ã¡ãŒã¿ãŒããããŸãã ãããã®4ã€ã®ãã©ã¡ãŒã¿ãŒããæçµç»åã®ãã¯ã»ã«ã®è²ãšéæ床ãååŸããå
¬åŒã¯ããã¬ã³ãã¢ãŒãã®èª¬æã§ãã
[Da 'ãDc'] = fïŒDcãDaãSaãScïŒ
ããšãã°ãDST_INã¢ãŒãã®å Žåã
Da '= Sa
Dc '= Saã»Dc
ãŸãã¯ãã³ã³ãã¯ãè¡šèš[Da 'ãDc'] = [Saã»DaãSaã»Dc]ã Androidã®ããã¥ã¡ã³ãã§ã¯ã次ã®ããã«ãªã£ãŠããŸã
Googleããé床ã«ç°¡æœãªããã¥ã¡ã³ããžã®ãªã³ã¯ãæäŸããŠããã ããã°å¹žãã§ãã äºåçãªèª¬æããªããã°ããããçèãããšãéçºè
ã¯ãã°ãã°stè¿·ã«é¥ããŸãïŒ
developer.android.com/reference/android/graphics/PorterDuff.Mode.html ã
ãããããããã®å
¬åŒã«åŸã£ãŠæçµç»åãã©ã®ããã«èŠããããé ã®äžã§ç解ããããšã¯éåžžã«é¢åã§ãã ãã¬ã³ãã¢ãŒãã«ãã®ãããªããŒãã·ãŒãã䜿çšãããšãã¯ããã«äŸ¿å©ã§ãã
ãã®ããŒãã·ãŒãããèå³ã®ããSRC_INããã³DST_INã¢ãŒããããã«ç¢ºèªã§ããŸãã å®éããããã¯ãã£ã³ãã¹ã®äžéæãªé åãšãªãŒããŒã¬ã€ç»åã®äº€å·®éšåã§ãããDST_INã¯ãã£ã³ãã¹ã®è²ããã®ãŸãŸã«ããŠãSRC_INã¯è²ãå€æŽããŸãã ç»åãæåã«ãã£ã³ãã¹ã«æãããå Žåã¯ãDST_INãéžæããŸãã ãã¹ã¯ãããšããšãã£ã³ãã¹ã«ãã€ã³ããããŠããå Žåã¯ãSRC_INãéžæããŸãã
ãã¹ãŠãæããã«ãªã£ãã®ã§ãã³ãŒããæžãããšãã§ããŸãã
SRC_IN
Stackoverflow.comã«ã¯ãPorterDuffã䜿çšãããšãã«ãããã¡ãŒçšã®ã¡ã¢ãªãå²ãåœãŠãããšãæšå¥šãããåçããããŸãã å Žåã«ãã£ãŠã¯ãonDrawãåŒã³åºããã³ã«ãããè¡ãããšããå§ãããŸãã ãã¡ãããããã¯éåžžã«éå¹ççã§ãã onDrawã®ããŒãäžã®ã¡ã¢ãªå²ãåœãŠããŸã£ããåé¿ããããã«ããŠãã ããã ããã§Bitmap.createBitmapãèŠãã®ã¯é©ãã¹ãããšã§ãããããã«ã¯æ°ã¡ã¬ãã€ãã®ã¡ã¢ãªãå¿
èŠã«ãªãå ŽåããããŸãã ç°¡åãªäŸïŒARGB圢åŒã®640 * 640ã®ç»åã¯ãã¡ã¢ãªã§1.5 MB以äžãå æããŸãã
ãããåé¿ããã«ã¯ããããã¡ãäºåã«å²ãåœãŠãŠãonDrawåŒã³åºãã§åå©çšã§ããŸãã
SRC_INã¢ãŒãã䜿çšããDrawableã®äŸã次ã«ç€ºããŸãã ãããã¡ã®ã¡ã¢ãªã¯ãDrawableã®ãµã€ãºãå€æŽãããšãã«å²ãåœãŠãããŸãã
public class MaskedDrawablePorterDuffSrcIn extends Drawable { private Bitmap mPictureBitmap; private Bitmap mMaskBitmap; private Bitmap mBufferBitmap; private Canvas mBufferCanvas; private final Paint mPaintSrcIn = new Paint(); public MaskedDrawablePorterDuffSrcIn() { mPaintSrcIn.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); } public void setPictureBitmap(Bitmap pictureBitmap) { mPictureBitmap = pictureBitmap; } public void setMaskBitmap(Bitmap maskBitmap) { mMaskBitmap = maskBitmap; } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); final int width = bounds.width(); final int height = bounds.height(); if (width <= 0 || height <= 0) { return; } mBufferBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mBufferCanvas = new Canvas(mBufferBitmap); } @Override public void draw(Canvas canvas) { if (mPictureBitmap == null || mMaskBitmap == null) { return; } mBufferCanvas.drawBitmap(mMaskBitmap, 0, 0, null); mBufferCanvas.drawBitmap(mPictureBitmap, 0, 0, mPaintSrcIn);
äžèšã®äŸã§ã¯ãæåã«ãã¹ã¯ããããã¡ãã£ã³ãã¹ã«æç»ããã次ã«SRC_INã¢ãŒãã§ç»åãæç»ãããŸãã
泚ææ·±ãèªè
ã¯ããã®ã³ãŒããæé©ã§ã¯ãªãããšã«æ°ä»ãã§ãããã æç»åŒã³åºãããšã«ãããã¡ãã£ã³ãã¹ãåæç»ããã®ã¯ãªãã§ããïŒ çµå±ã®ãšãããäœããå€æŽãããå Žåã«ã®ã¿ãããè¡ãããšãã§ããŸãã
æé©åãããã³ãŒã public class MaskedDrawablePorterDuffSrcIn extends MaskedDrawable { private Bitmap mPictureBitmap; private Bitmap mMaskBitmap; private Bitmap mBufferBitmap; private Canvas mBufferCanvas; private final Paint mPaintSrcIn = new Paint(); public static MaskedDrawableFactory getFactory() { return new MaskedDrawableFactory() { @Override public MaskedDrawable createMaskedDrawable() { return new MaskedDrawablePorterDuffSrcIn(); } }; } public MaskedDrawablePorterDuffSrcIn() { mPaintSrcIn.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); } @Override public void setPictureBitmap(Bitmap pictureBitmap) { mPictureBitmap = pictureBitmap; redrawBufferCanvas(); } @Override public void setMaskBitmap(Bitmap maskBitmap) { mMaskBitmap = maskBitmap; redrawBufferCanvas(); } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); final int width = bounds.width(); final int height = bounds.height(); if (width <= 0 || height <= 0) { return; } if (mBufferBitmap != null && mBufferBitmap.getWidth() == width && mBufferBitmap.getHeight() == height) { return; } mBufferBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
DST_IN
SRC_INãšã¯ç°ãªããDST_INã䜿çšããå Žåã¯ãæç»é åºãå€æŽããå¿
èŠããããŸããæåã«ããã£ã³ãã¹ãšãã¹ã¯ã®äžã«ç»åãæç»ãããŸãã åã®äŸããã®å€æŽã¯æ¬¡ã®ãšããã§ãã
mPaintDstIn.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); mBufferCanvas.drawBitmap(mPictureBitmap, 0, 0, null); mBufferCanvas.drawBitmap(mMaskBitmap, 0, 0, mPaintDstIn);
å¥åŠãªããšã«ããã¹ã¯ãALPHA_8圢åŒã§æ瀺ãããŠããå Žåããã®ã³ãŒãã¯æåŸ
ããçµæãäžããŸããã éå¹ççãªåœ¢åŒã®ARGB_8888ã§è¡šç€ºãããå Žåã¯ããã¹ãŠåé¡ãããŸããã stackoverflow.com
ã®è³ªåã¯çŸåšæªåçã®ãŸãŸã§ãã 誰ããçç±ãç¥ã£ãŠããå Žå-ã³ã¡ã³ãã§ç¥èãå
±æããŠãã ããã
CLEAR + DST_OVER
äžèšã®äŸã§ã¯ããããã¡ã®ã¡ã¢ãªã¯Drawableãµã€ãºãå€æŽããããšãã«ã®ã¿å²ãåœãŠãããŸãããããã¯ãæ¯åå²ãåœãŠããããã¯ããã«åªããŠããŸãã
ããããèããŠã¿ããšãå Žåã«ãã£ãŠã¯ããããã¡ããŸã£ããå²ãåœãŠãã«ãæç»ã§æž¡ããããã£ã³ãã¹ã«ããã«æç»ã§ããŸãã äœãããã§ã«æãããŠããããšãèŠããŠãããŠãã ããã
ãããè¡ãã«ã¯ããã£ã³ãã¹ã§CLEARã¢ãŒãã䜿çšããŠãã¹ã¯ã®åœ¢ã«ç©ŽãéããDST_OVERã¢ãŒãã§çµµãæããŸããæ¯figçã«èšãã°ããã£ã³ãã¹ã®äžã«çµµãå
¥ããŸãã ãã®ç©ŽãéããŠåçãèŠãããšãã§ããå¹æã¯ãŸãã«ç§ãã¡ãå¿
èŠãšãããã®ã§ãã
ãã®ãããªããªãã¯ã¯ããã¹ã¯ãšç»åã«åéæã®é åãå«ãŸããŠããããå®å
šã«éæãŸãã¯å®å
šã«äžéæãªãã¯ã»ã«ã®ã¿ãå«ãŸããŠããããšãããã£ãŠããå Žåã«äœ¿çšã§ããŸãã
ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
mPaintDstOver.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER)); mPaintClear.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
ãã®ãœãªã¥ãŒã·ã§ã³ã«ã¯éææ§ã«é¢ããåé¡ããããŸãã setAlphaã¡ãœãããå®è£
ããå Žåã¯ãDrawableã®äžã®ãã£ã³ãã¹ã«æããããã®ã§ã¯ãªãããŠã£ã³ããŠã®èæ¯ãç»åãç
§ãããŸãã ç»åã®æ¯èŒïŒ
CLEAR + DST_OVERãåéææ§ãšçµã¿åãããŠäœ¿çšââãããšãå·ŠåŽã«ããã¯ãã®ãšãããå³åŽã«ããããšãããããŸãã
ã芧ã®ãšãããAndroidã§ã®PorterDuffã¢ãŒãã®äœ¿çšã¯ãéå°ãªã¡ã¢ãªã®å²ãåœãŠãŸãã¯äœ¿çšå¶éã«é¢é£ä»ããããŠããŸãã 幞ããªããšã«ãããããã¹ãŠã®åé¡ãåé¿ããæ¹æ³ããããŸãã BitmapShaderã䜿çšããã ãã§ãã
ããããããã·ã§ãŒããŒ
éåžžãã·ã§ãŒããŒãèšåããããšãããããã¯OpenGLãæãåºããŸãã ãã ããAndroidã§BitmapShaderã䜿çšããå Žåãéçºè
ããã®åéã®ç¥èãæã£ãŠããå¿
èŠã¯ãããŸããã å®éãandroid.graphics.Shaderå®è£
ã¯ãåãã¯ã»ã«ã®è²ã決å®ããã¢ã«ãŽãªãºã ãã€ãŸããã¯ã»ã«ã·ã§ãŒããŒãèšè¿°ããŠããŸãã
ãããã®äœ¿çšæ¹æ³ã¯ïŒ éåžžã«ç°¡åïŒãã€ã³ãã§ã·ã§ãŒããŒãããŒããããšããã®ãã€ã³ãã䜿çšããŠæç»ããããã¹ãŠã®ãã®ãã·ã§ãŒããŒãããã¯ã»ã«ã®è²ãåããŸãã ãã®ããã±ãŒãžã«ã¯ãã°ã©ããŒã·ã§ã³ãæç»ããä»ã®ã·ã§ãŒããŒãšïŒãã®ã¿ã¹ã¯ã®ã³ã³ããã¹ãã§æã圹ç«ã€ïŒBitmapShaderãçµã¿åãããŠãBitmapã䜿çšããŠåæåããã·ã§ãŒããŒå®è£
ããããŸãã ãã®ãããªã·ã§ãŒããŒã¯ãåæåäžã«è»¢éããããããããããã察å¿ãããã¯ã»ã«ã®è²ãè¿ããŸãã
ããã¥ã¡ã³ãã«ã¯éèŠãªèª¬æããããŸãããããããã以å€ã®ãã¹ãŠãã·ã§ãŒããŒã§æç»ã§ããŸãã å®éããããããããALPHA_8圢åŒã®å Žåãã·ã§ãŒããŒã䜿çšããŠãã®ãããªãããããããã¬ã³ããªã³ã°ãããšãããã¹ãŠãæ£åžžã«æ©èœããŸãã ãã¹ã¯ã¯ãã®åœ¢åŒã«ãªã£ãŠãããããè±ã®ç»åã䜿çšããã·ã§ãŒããŒã䜿çšããŠãã¹ã¯ã衚瀺ããŠã¿ãŸãããã
æé ïŒ
- è±ã®ç»åãèªã¿èŸŒãBitmapShaderãäœæããŸãã
- ãã®BitmapShaderãèªã¿èŸŒããã€ã³ããäœæããŸãã
- ãã®ãã€ã³ãã§ãã¹ã¯ãæããŸãã
public void setPictureBitmap(Bitmap src) { mPictureBitmap = src; mBitmapShader = new BitmapShader(mPictureBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mPaintShader.setShader(mBitmapShader); } public void draw(Canvas canvas) { if (mPaintShader == null || mMaskBitmap == null) { return; } canvas.drawBitmap(mMaskBitmap, 0, 0, mPaintShader); }
ãã¹ãŠãéåžžã«ç°¡åã§ãããïŒ å®éããã¹ã¯ãšç»åã®ãµã€ãºãäžèŽããªãå ŽåãæåŸ
ãããã®ãæ£ç¢ºã«è¡šç€ºãããŸããã ãã¹ã¯ã¯ã
Shader.TileMode.REPEAT
ã¢ãŒãã«å¯Ÿå¿ããç»åã§
Shader.TileMode.REPEAT
ãŸãã
ç»åã®ãµã€ãºããã¹ã¯ã®ãµã€ãºã«çž®å°ããã«ã¯ã
android.graphics.ShaderïŒsetLocalMatrix methodã䜿çšããŸã
ããã®ã¡ãœããã«å€æãããªãã¯ã¹ã転éããå¿
èŠããããŸãã 幞ããªããšã«ãåæãžãªã¡ããªã®ã³ãŒã¹ãèŠããå¿
èŠã¯ãããŸãããandroid.graphics.Matrixã¯ã©ã¹ã«ã¯ããããªãã¯ã¹ã圢æããããã®äŸ¿å©ãªã¡ãœãããå«ãŸããŠããŸãã ç»åãããããŒã·ã§ã³ã®æªã¿ãªãã«ãã¹ã¯ã«å®å
šã«åãŸãããã«ã·ã§ãŒããŒãå§çž®ããç»åã®äžå¿ãšãã¹ã¯ãæãããã«ç§»åããŸãã
private void updateScaleMatrix() { if (mPictureBitmap == null || mMaskBitmap == null) { return; } int maskW = mMaskBitmap.getWidth(); int maskH = mMaskBitmap.getHeight(); int pictureW = mPictureBitmap.getWidth(); int pictureH = mPictureBitmap.getHeight(); float wScale = maskW / (float) pictureW; float hScale = maskH / (float) pictureH; float scale = Math.max(wScale, hScale); Matrix matrix = new Matrix(); matrix.setScale(scale, scale); matrix.postTranslate((maskW - pictureW * scale) / 2f, (maskH - pictureH * scale) / 2f); mBitmapShader.setLocalMatrix(matrix); }
ãŸããã·ã§ãŒããŒã䜿çšãããšãDrawableã®éæ床ãå€æŽããColorFilterãèšå®ããã¡ãœãããç°¡åã«å®è£
ã§ããŸãã åãååã®ã·ã§ãŒããŒã¡ãœãããåŒã³åºãã ãã§ååã§ãã
æçµã³ãŒã public class MaskedDrawableBitmapShader extends Drawable { private Bitmap mPictureBitmap; private Bitmap mMaskBitmap; private final Paint mPaintShader = new Paint(); private BitmapShader mBitmapShader; public void setMaskBitmap(Bitmap maskBitmap) { mMaskBitmap = maskBitmap; updateScaleMatrix(); } public void setPictureBitmap(Bitmap src) { mPictureBitmap = src; mBitmapShader = new BitmapShader(mPictureBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mPaintShader.setShader(mBitmapShader); updateScaleMatrix(); } @Override public void draw(Canvas canvas) { if (mPaintShader == null || mMaskBitmap == null) { return; } canvas.drawBitmap(mMaskBitmap, 0, 0, mPaintShader); } private void updateScaleMatrix() { if (mPictureBitmap == null || mMaskBitmap == null) { return; } int maskW = mMaskBitmap.getWidth(); int maskH = mMaskBitmap.getHeight(); int pictureW = mPictureBitmap.getWidth(); int pictureH = mPictureBitmap.getHeight(); float wScale = maskW / (float) pictureW; float hScale = maskH / (float) pictureH; float scale = Math.max(wScale, hScale); Matrix matrix = new Matrix(); matrix.setScale(scale, scale); matrix.postTranslate((maskW - pictureW * scale) / 2f, (maskH - pictureH * scale) / 2f); mBitmapShader.setLocalMatrix(matrix); } @Override public void setAlpha(int alpha) { mPaintShader.setAlpha(alpha); } @Override public void setColorFilter(ColorFilter cf) { mPaintShader.setColorFilter(cf); } @Override public int getOpacity() { return PixelFormat.UNKNOWN; } @Override public int getIntrinsicWidth() { return mMaskBitmap != null ? mMaskBitmap.getWidth() : super.getIntrinsicWidth(); } @Override public int getIntrinsicHeight() { return mMaskBitmap != null ? mMaskBitmap.getHeight() : super.getIntrinsicHeight(); } }
ç§ã®æèŠã§ã¯ãããã¯åé¡ã«å¯Ÿããæãæåãã解決çã§ãããããã¡å²ãåœãŠã¯äžèŠã§ãããéææ§ã«åé¡ã¯ãããŸããã ããã«ããã¹ã¯ãåçŽãªå¹ŸäœåŠåœ¢ç¶ã§ããå Žåããã¹ã¯ä»ãã®ããããããã®ããŠã³ããŒããæåŠããŠãããã°ã©ã ã§ãã¹ã¯ãæç»ã§ããŸãã ããã«ããããã¹ã¯ããããããããšããŠä¿åããããã«å¿
èŠãªã¡ã¢ãªãç¯çŽãããŸãã
ããšãã°ããã®èšäºã§äŸãšããŠäœ¿çšãããã¹ã¯ã¯ãç°¡åã«æç»ã§ããéåžžã«åçŽãªå¹ŸäœåŠçå³åœ¢ã§ãã
ã³ãŒãäŸ public class FixedMaskDrawableBitmapShader extends Drawable { private Bitmap mPictureBitmap; private final Paint mPaintShader = new Paint(); private BitmapShader mBitmapShader; private Path mPath; public void setPictureBitmap(Bitmap src) { mPictureBitmap = src; mBitmapShader = new BitmapShader(mPictureBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mPaintShader.setShader(mBitmapShader); mPath = new Path(); mPath.addOval(0, 0, getIntrinsicWidth(), getIntrinsicHeight(), Path.Direction.CW); Path subPath = new Path(); subPath.addOval(getIntrinsicWidth() * 0.7f, getIntrinsicHeight() * 0.7f, getIntrinsicWidth(), getIntrinsicHeight(), Path.Direction.CW); mPath.op(subPath, Path.Op.DIFFERENCE); } @Override public void draw(Canvas canvas) { if (mPictureBitmap == null) { return; } canvas.drawPath(mPath, mPaintShader); } @Override public void setAlpha(int alpha) { mPaintShader.setAlpha(alpha); } @Override public void setColorFilter(ColorFilter cf) { mPaintShader.setColorFilter(cf); } @Override public int getOpacity() { return PixelFormat.UNKNOWN; } @Override public int getIntrinsicWidth() { return mPictureBitmap != null ? mPictureBitmap.getWidth() : super.getIntrinsicWidth(); } @Override public int getIntrinsicHeight() { return mPictureBitmap != null ? mPictureBitmap.getHeight() : super.getIntrinsicHeight(); } }
ã·ã§ãŒããŒã䜿çšããŠäœã§ãæç»ã§ãããããããšãã°æ¬¡ã®ããã«ããã¹ããæç»ã§ããŸãã
public void setPictureBitmap(Bitmap src) { mPictureBitmap = src; mBitmapShader = new BitmapShader(mPictureBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mPaintShader.setShader(mBitmapShader); mPaintShader.setTextSize(getIntrinsicHeight()); mPaintShader.setStyle(Paint.Style.FILL); mPaintShader.setTextAlign(Paint.Align.CENTER); mPaintShader.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); } @Override public void draw(Canvas canvas) { if (mPictureBitmap == null) { return; } canvas.drawText("A", getIntrinsicWidth() / 2, getIntrinsicHeight() * 0.9f, mPaintShader); }
çµæïŒ

RoundedBitmapDrawable
RoundedBitmapDrawableã¯ã©ã¹ããµããŒãã©ã€ãã©ãªã«ååšããããšãç¥ã£ãŠãããšåœ¹ç«ã¡ãŸãã ãšããžãäžžãããããç»åãå®å
šã«äžžãããå¿
èŠãããå Žåã«äŸ¿å©ã§ãã å
éšçã«ã¯ãBitmapShaderã䜿çšãããŸãã
æ§èœ
äžèšã®ãœãªã¥ãŒã·ã§ã³ãããã©ãŒãã³ã¹ã«ã©ã®ããã«åœ±é¿ããããèŠãŠã¿ãŸãããã ãã®ããã«ã100åã®èŠçŽ ãæã€RecyclerViewã䜿çšããŸããã GPUã¢ãã¿ãŒã°ã©ãã¯ãããªãçç£çãªã¹ããŒããã©ã³ïŒMoto X StyleïŒã§é«éã¹ã¯ããŒã«ã§æ®åœ±ãããŸããã
暪軞ã«æ²¿ã£ãã°ã©ã-瞊軞ã«æ²¿ã£ãæé-åãã¬ãŒã ã®æç»ã«è²»ããããããªç§æ°ãæãåºãããŠãã ããã çæ³çã«ã¯ããã£ãŒãã¯60 FPSã«å¯Ÿå¿ããç·ã®ç·ã®äžã«é
眮ããå¿
èŠããããŸãã

ãã¬ãŒã³BitmapDrawableïŒãã¹ãã³ã°ãªãïŒ

SRC_IN

ããããããã·ã§ãŒããŒ
BitmapShaderã䜿çšãããšãäžè¬çãªãã¹ãã³ã°ãªããšåãé«ãã¬ãŒã ã¬ãŒããå®çŸã§ããããšãããããŸãã SRC_INãœãªã¥ãŒã·ã§ã³ã¯ååã«çç£çã§ãããšã¯èŠãªããŸããããé«éã¹ã¯ããŒã«äžã«ã€ã³ã¿ãŒãã§ã€ã¹ã®é床ã倧å¹
ã«äœäžããŸããããã¯ãã°ã©ãã§ç¢ºèªãããŠããŸãã
çµè«
ç§ã®æèŠã§ã¯ãBitmapShaderã䜿çšããã¢ãããŒãã®å©ç¹ã¯æããã§ãããããã¡ã«ã¡ã¢ãªãå²ãåœãŠãå¿
èŠã¯ãªããåªããæè»æ§ãåéææ§ã®ãµããŒããé«æ§èœãå¿
èŠã§ãã
ãã®ã¢ãããŒããã©ã€ãã©ãªã®å®è£
ã§äœ¿çšãããããšã¯é©ãããšã§ã¯ãããŸããã
ã³ã¡ã³ãã§ããªãã®èããå
±æããŠãã ããïŒ
stackoverflow.comãããªããšå
±ã«ãããŸãããã«ïŒ