使用canvas的clipXxx函數,可以獲取只顯露出某一區域的圖形,但是有鋸齒,即使paint使用了setAntiAlias(true)函數依然無法消除鋸齒問題。
解決方案: 使用shader方案,即:
其中mBitmapShader的聲明與實現是:
BitmapShader mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);//如果要實現位置變換等,可以添加如下代碼:mBitmapShader.setLocalMatrix(matrix);具體的實現,可見AvatarImageView項目中,多字裁剪的實現方式。
PorterDuffXfermode主要用于獲取兩張圖片取“并集/交集”等的效果。這里的取“交集/并集”是根據圖片A和圖片B的某個像素點的顏色值來確定的。 假設代碼的實現為如下方式: 1. 首先,畫出A-des。這里的A-des不一定必須是bitmap,可以是path等。 2. 其次,設置paint的Xfermode為 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 3. 最后,畫出B-src。與第一步中的A-des相似,這里的B-src不一定必須是bitmap,可以是path等。
根據上面的三個步驟,分析繪出的圖的某一個像素點的顏色值情況: 1. 如果在(x,y)像素點處,A的顏色值為透明或者沒有設定,而B的不為0,那么此點的顏色值為0x00000000。因為A為0了,而SRC_IN的效果就是最后要顯示的圖片取交集,并且后畫的顯示在交集上,而交集為0(底部顏色為0,可以認為最后顏色的透明度為兩者相乘),所以就將B圖變成透明的了。如果A的透明度為0.5,那么SRC_IN后的圖片的相當于B*0.5透明度。 2. 最后生成的圖像,是對兩個圖像的每一個像素點分別計算交集獲取的結果,與圖像的“區域”無關。
舉例說明: 仿微信聊天中帶有三角凸起的圖片的代碼片段:
public static Bitmap canvasTriangle(Bitmap bitmapimg, int direct) { Bitmap output = Bitmap.createBitmap(bitmapimg.getWidth(), bitmapimg.getHeight(), Bitmap.Config.ARGB_4444); Canvas canvas = new Canvas(output); final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmapimg.getWidth(), bitmapimg.getHeight());// paint.setStrokeWidth(30);// paint.setStyle(Paint.Style.STROKE); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(0x66000000); //可以使用canvas.drawRect() + canvas.drawPath()等方式多個區域合并后進行繪制 //path只是用來繪制像素的透明度的。如果paint的透明度為0,那么相當于沒有畫任何東西,如果paint的透明度為0.3,那么最后的圖片的透明度為0.3 Path path = new Path(); path.moveTo(0, 0); path.lineTo(bitmapimg.getWidth() - 15, 0); path.lineTo(bitmapimg.getWidth() - 15, 10); path.lineTo(bitmapimg.getWidth(), 20); path.lineTo(bitmapimg.getWidth() - 15, 30); path.lineTo(bitmapimg.getWidth() - 15, bitmapimg.getHeight()); path.lineTo(0, bitmapimg.getHeight()); path.close(); canvas.drawPath(path, paint);//(DES) //兩層繪制交集。顯示上層 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmapimg, rect, rect, paint);//(SRC) return output; }新聞熱點
疑難解答