Android Xfermode learning notes, androidxfermode
I. Overview
The full name of Xfermode is transfer-mode, which is used to achieve the hybrid effect of the two images.
The most famous figure about Xfermode circulating on the internet is from samples of AndroidSDK, named Xfermodes. java. The effect is as follows:
[Repost this article at http://www.cnblogs.com/goagent/p/5336938.html]
Ii. Experience
Extract the core code in Xfermodes. java and write a simple and crude demo:
1 public class ImageViewXfermode extends ImageView {2 public ImageViewXfermode (Context context) {3 super (context); 4 init (); 5} 6 7 public ImageViewXfermode (Context context, AttributeSet attrs) {8 super (context, attrs); 9 init (); 10} 11 12 public ImageViewXfermode (Context context, AttributeSet attrs, int defStyle) {13 super (context, attrs, defStyle); 14 init (); 15} 16 17 private void init () {18 if (Build. VERSION. SDK_INT> = Build. VERSION_CODES.HONEYCOMB) {19 setLayerType (View. LAYER_TYPE_SOFTWARE, null); 20} 21} 22 23 @ Override24 protected void onDraw (Canvas canvas) {25 int defaultWidth = dip2px (85 ); // In xml, the view width is 85dp26 int defaultdHeight = dip2px (85); // in xml, the view height is 85dp27 28 if (canvas. getHeight () = defaultWidth & canvas. getHeight () = defaultdHeight) {29 // get bitmap30 Bitmap bitcircle = Bitmap in the yellow circle. createBitmap (getWidth (), getHeight (), Bitmap. config. ARGB_8888); 31 Canvas canvascicle = new Canvas (bitcircle); 32 Paint paintcicle = new Paint (Paint. ANTI_ALIAS_FLAG); 33 paintcicle. setColor (0xFFFFCC44); 34 canvascicle. drawCircle (dip2px (30), dip2px (30), dip2px (25), paintcicle); 35 36 // get bitmap37 Bitmap bitrect = Bitmap of the blue rectangle. createBitmap (defaultWidth, defaultdHeight, Config. ARGB_8888); 38 Canvas canvasrect = new Canvas (bitrect); 39 Paint paintrect = new Paint (Paint. ANTI_ALIAS_FLAG); 40 paintrect. setColor (0xFF66AAFF); 41 canvasrect. drawRect (dip2px (30), dip2px (30), dip2px (80), dip2px (80), paintrect); 42 43 Paint paint = new Paint (Paint. ANTI_ALIAS_FLAG); 44 Xfermode xfermode = new porterduxfermode (Mode. LIGHTEN); 45 46 // use saveLayer to draw the canvas on the automatically created bitmap 47 int cnt = canvas. saveLayer (0, 0, defaultWidth, defaultdHeight, null, Canvas. ALL_SAVE_FLAG); 48 // draw a circle first, and the circle is dest49 canvas. drawBitmap (bitcircle, 0, 0, paint); 50 paint. setXfermode (xfermode); 51 // draw a rectangle behind it. The rectangle is src52 canvas. drawBitmap (bitrect, 0, 0, paint); 53 paint. setXfermode (null); 54 canvas. restoreToCount (cnt); 55} else {56 super. onDraw (canvas); 57} 58} 59 60 private int dip2px (float dip) {61 float scale = getResources (). getDisplayMetrics (). density; 62 return (int) (dip * scale + 0.5f); 63} 64}
The effect is as follows:
Several key points are introduced:
1. About src and dest
Dest is first drawn on the canvas, and src is then drawn.
2. About hardware acceleration
When sdkversion> = 11, you must disable hardware acceleration (line 1). Otherwise, the rendering effect is not normal in Mode. CLEAR, Mode. DARKEN, and Mode. LIGHTEN.
3. Roles of saveLayer
Canvas. saveLayer automatically assigns an additional bitmap Based on Canvas. save, so that all the drawings after the saveLayer are completed on the new bitmap.
What if saveLayer is removed? The result is that the Mode. LIGHTEN operation is performed on both the blue rectangle and the yellow circle and the gray background:
4. If you do not save elayer
There is a work und: Draw a bitmap corresponding to src on the canvas of the bitmap corresponding to the dest, so the purpose is consistent with that of saveLayer, not directly drawing on the current canvas:
1 @ Override 2 protected void onDraw (Canvas canvas) {3 int defaultWidth = dip2px (85); // in xml, the view width is 85dp 4 int defaultdHeight = dip2px (85 ); // In xml, the view height is 85dp 5 6 if (canvas. getHeight () = defaultWidth & canvas. getHeight () = defaultdHeight) {7 // get bitmap 8 Bitmap bitcircle = Bitmap in the yellow circle. createBitmap (getWidth (), getHeight (), Bitmap. config. ARGB_8888); 9 Canvas canvascicle = new Canvas (bitcircle); 10 Paint paintcicle = new Paint (Paint. ANTI_ALIAS_FLAG); 11 paintcicle. setColor (0xFFFFCC44); 12 canvascicle. drawCircle (dip2px (30), dip2px (30), dip2px (25), paintcicle); 13 14 // get bitmap15 Bitmap bitrect = Bitmap of the blue rectangle. createBitmap (defaultWidth, defaultdHeight, Config. ARGB_8888); 16 Canvas canvasrect = new Canvas (bitrect); 17 Paint paintrect = new Paint (Paint. ANTI_ALIAS_FLAG); 18 paintrect. setColor (0xFF66AAFF); 19 canvasrect. drawRect (dip2px (30), dip2px (30), dip2px (80), dip2px (80), paintrect); 20 21 Paint paint = new Paint (Paint. ANTI_ALIAS_FLAG); 22 Xfermode xfermode = new porterduxfermode (Mode. LIGHTEN); 23 24 // set setXfermode25 paint. setXfermode (xfermode); 26 // draw a rectangle on the canvas of the circle. Draw a circle first, a circle is dest, and a rectangle is drawn. The rectangle is src27 canvascicle. drawBitmap (bitrect, 0, 0, paint); 28 paint. setXfermode (null); 29 // draw the result of the circular canvas to 30 canvas. drawBitmap (bitcircle, 0.0f, 0.0f, paint); 31} else {32 super. onDraw (canvas); 33} 34}
[Repost this article at http://www.cnblogs.com/goagent/p/5336938.html]
3. More methods-circular ImageView
The Xfermode feature can also be used to create a circular ImageView. First draw the source image, then draw a circle, use Mode. DST_IN:
1 @ Override 2 protected void onDraw (Canvas canvas) {3 int defaultWidth = dip2px (85); // in xml, the view width is 85dp 4 int defaultdHeight = dip2px (85 ); // In xml, the view height is 85dp 5 Drawable drawable = getDrawable (); 6 7 if (canvas. getHeight () = defaultWidth & canvas. getHeight () = defaultdHeight & drawable instanceof BitmapDrawable) {8 // setBackgroundColor (Color. TRANSPARENT); 9 // obtain the bitmap10 Bitmap bitimg = Bitmap of the source image. createBitmap (getWidth (), getHeight (), Bitmap. config. ARGB_8888); 11 Canvas canvasimg = new Canvas (bitimg); 12 Matrix matrix = new Matrix (); 13 matrix. setScale (defaultWidth * 1.0f/drawable. getIntrinsicWidth (), defaultdHeight * 1.0f/drawable. getIntrinsicHeight (); 14 Paint paintimg = new Paint (Paint. ANTI_ALIAS_FLAG); 15 canvasimg. drawBitmap (BitmapDrawable) drawable ). getBitmap (), matrix, paintimg); 16 17 // get bitmap18 Bitmap bitcircle = Bitmap. createBitmap (defaultWidth, defaultdHeight, Config. ARGB_8888); 19 Canvas canvascircle = new Canvas (bitcircle); 20 Paint paintcircle = new Paint (Paint. ANTI_ALIAS_FLAG); 21 paintcircle. setColor (0xFF66AAFF); 22 canvascircle. drawCircle (dip2px (85/2 running f), dip2px (85/2 running f), dip2px (85/2 running f), paintcircle); 23 24 Paint paint = new Paint (Paint. ANTI_ALIAS_FLAG); 25 Xfermode xfermode = new porterduxfermode (Mode. DST_IN); 26 27 // use saveLayer to draw the canvas on the automatically created bitmap 28 int cnt = canvas. saveLayer (0, 0, defaultWidth, defaultdHeight, null, Canvas. ALL_SAVE_FLAG); 29 // draw the source image first. The source image is dest30 canvas. drawBitmap (bitimg, 0, 0, paint); 31 paint. setXfermode (xfermode); 32 // draw a circle with the circle src33 canvas. drawBitmap (bitcircle, 0, 0, paint); 34 paint. setXfermode (null); 35 canvas. restoreToCount (cnt); 36} else {37 super. onDraw (canvas); 38} 39}
[Repost this article at http://www.cnblogs.com/goagent/p/5336938.html]