<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                菜雞wing遇敵PorterDuffXferMode,不料過于輕敵,應戰吃力。隨后與其大戰三天三夜,三百余回合不分勝負。幸得 @咪咪控 相助,僥幸獲勝。 關鍵字:PorterDuffXferMode ?錯誤 不正確 ?不達到預期 ?bug 上一篇帶來一個使用PorterDuffXferMode ?做的?[水波紋loadingview](http://blog.csdn.net/wingichoy/article/details/50523713),中間遇到了點小困難。 (說人話) ?PorterDuffXferMode總是不能按照效果圖預期的效果執行。關于PorterDuffXferMode的錯誤顯示是一個對初學者十分深的坑,到底是bug呢,還是有需要注意的地方呢。這里就跟隨我 帶上手電筒,去一探究竟。 轉載請注明出處:http://blog.csdn.net/wingichoy/article/details/50534175 首先,大家都知道有一個圖片: ![](https://box.kancloud.cn/2016-03-21_56efaea6b35c1.jpg) 然后,大部分時候 是看到了覺得很神奇,就躍躍欲試,尤其是src_in ?和dstIn可以實現遮罩效果,例如圓角圖片 圓形圖片都用了這種模式。 于是就挨個測試各種模式是否生效,結果往往不能達到預期效果。我們來做個測試。 從最簡單的開始: **1.直接在canvas上面繪制圖形**: ~~~ @Override protected void onDraw(Canvas canvas) { //dst canvas.drawRect(20,20,80,80,mDstPaint); //src canvas.drawCircle(30,30,30,mSrcPaint); } ~~~ 原圖效果是這樣的: ![](https://box.kancloud.cn/2016-03-21_56efaea77adc4.jpg) 現在加一個mode上來,XOR ~~~ @Override protected void onDraw(Canvas canvas) { //dst canvas.drawRect(20,20,80,80,mDstPaint); mSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); //src canvas.drawCircle(30,30,30,mSrcPaint); } ~~~ 跑起來的結果是這樣的: ![](https://box.kancloud.cn/2016-03-21_56efaea78d8d1.jpg) WTF!!?? 這是什么鬼。不應該是相交部分消失嗎。 網上說“硬件加速”對這個有影響,那么在構造器里關閉硬件加速試一下: ~~~ public TestView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mDstPaint = new Paint(); mSrcPaint = new Paint(); mDstPaint.setColor(Color.YELLOW); mSrcPaint.setColor(Color.BLUE); setLayerType(View.LAYER_TYPE_SOFTWARE, null); } ~~~ 運行的結果: ![](https://box.kancloud.cn/2016-03-21_56efaea79d8fe.jpg) 這下正常了。相交的部分消失了。 **結論1:硬件加速對PorterDuffXferMode有影響,使用前請關閉硬件加速。** 那么這下真的天下太平了嗎?nonono~不要太天真,不然怎么能叫萬丈深淵呢。 繼續試驗其他模式: ?將模式改為SRC_IN ![](https://box.kancloud.cn/2016-03-21_56efaea7aff26.jpg) WTF?????跟效果圖根本不一致好嗎!!!! 在試試DST_IN ![](https://box.kancloud.cn/2016-03-21_56efaea7c35ce.jpg) 你確定你沒有在逗我???? ?怎么是這個鬼東西。 ?(當時鼓搗了我三天四夜,一直在日狗,不過先別急,慢慢來。) 為什么一定要按照那個效果圖來呢。。。 因為特么的那個圖是官方的一個demo。。 那么我們就來看看這個demo長什么樣! ~~~ package io.appium.android.apis.graphics; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.Xfermode; import android.os.Bundle; import android.view.View; public class Xfermodes extends GraphicsActivity { // create a bitmap with a circle, used for the "dst" image static Bitmap makeDst(int w, int h) { Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(bm); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setColor(0xFFFFCC44); c.drawOval(new RectF(0, 0, w*3/4, h*3/4), p); return bm; } // create a bitmap with a rect, used for the "src" image static Bitmap makeSrc(int w, int h) { Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(bm); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setColor(0xFF66AAFF); c.drawRect(w/3, h/3, w*19/20, h*19/20, p); return bm; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new SampleView(this)); } private static class SampleView extends View { private static final int W = 64; private static final int H = 64; private static final int ROW_MAX = 4; // number of samples per row private Bitmap mSrcB; private Bitmap mDstB; private Shader mBG; // background checker-board pattern private static final Xfermode[] sModes = { new PorterDuffXfermode(PorterDuff.Mode.CLEAR), new PorterDuffXfermode(PorterDuff.Mode.SRC), new PorterDuffXfermode(PorterDuff.Mode.DST), new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER), new PorterDuffXfermode(PorterDuff.Mode.DST_OVER), new PorterDuffXfermode(PorterDuff.Mode.SRC_IN), new PorterDuffXfermode(PorterDuff.Mode.DST_IN), new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT), new PorterDuffXfermode(PorterDuff.Mode.DST_OUT), new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP), new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP), new PorterDuffXfermode(PorterDuff.Mode.XOR), new PorterDuffXfermode(PorterDuff.Mode.DARKEN), new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN), new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY), new PorterDuffXfermode(PorterDuff.Mode.SCREEN) }; private static final String[] sLabels = { "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Darken", "Lighten", "Multiply", "Screen" }; public SampleView(Context context) { super(context); mSrcB = makeSrc(W, H); mDstB = makeDst(W, H); // make a ckeckerboard pattern Bitmap bm = Bitmap.createBitmap(new int[] { 0xFFFFFFFF, 0xFFCCCCCC, 0xFFCCCCCC, 0xFFFFFFFF }, 2, 2, Bitmap.Config.RGB_565); mBG = new BitmapShader(bm, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); Matrix m = new Matrix(); m.setScale(6, 6); mBG.setLocalMatrix(m); } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(Color.WHITE); Paint labelP = new Paint(Paint.ANTI_ALIAS_FLAG); labelP.setTextAlign(Paint.Align.CENTER); Paint paint = new Paint(); paint.setFilterBitmap(false); canvas.translate(15, 35); int x = 0; int y = 0; for (int i = 0; i < sModes.length; i++) { // draw the border paint.setStyle(Paint.Style.STROKE); paint.setShader(null); canvas.drawRect(x - 0.5f, y - 0.5f, x + W + 0.5f, y + H + 0.5f, paint); // draw the checker-board pattern paint.setStyle(Paint.Style.FILL); paint.setShader(mBG); canvas.drawRect(x, y, x + W, y + H, paint); // draw the src/dst example into our offscreen bitmap int sc = canvas.saveLayer(x, y, x + W, y + H, null, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); canvas.translate(x, y); canvas.drawBitmap(mDstB, 0, 0, paint); paint.setXfermode(sModes[i]); canvas.drawBitmap(mSrcB, 0, 0, paint); paint.setXfermode(null); canvas.restoreToCount(sc); // draw the label canvas.drawText(sLabels[i], x + W/2, y - labelP.getTextSize()/2, labelP); x += W + 10; // wrap around when we've drawn enough for one row if ((i % ROW_MAX) == ROW_MAX - 1) { x = 0; y += H + 30; } } } } } ~~~ 一點一點看,截取onDraw里面的片段,這里 ~~~ canvas.drawBitmap(mDstB, 0, 0, paint); paint.setXfermode(sModes[i]); canvas.drawBitmap(mSrcB, 0, 0, paint); paint.setXfermode(null); ~~~ 他是畫了兩個bitmap。網上有人說好像只對bitmap生效,那到底是不是這樣呢。我們來試驗一下。 我們新定義一個canvas ?再定義一個bitmap ? 現在bitmap上畫出來src ?然后將bitmap畫到canvas上: ~~~ public TestView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mDstPaint = new Paint(); mSrcPaint = new Paint(); mDstPaint.setColor(Color.YELLOW); mSrcPaint.setColor(Color.BLUE); setLayerType(View.LAYER_TYPE_SOFTWARE, null); mSrcBitmap = Bitmap.createBitmap(50,50, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mSrcBitmap); } ~~~ ~~~ @Override protected void onDraw(Canvas canvas) { //dst canvas.drawRect(20,20,80,80,mDstPaint); //src // mSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); mCanvas.drawCircle(25,25,25,mSrcPaint); canvas.drawBitmap(mSrcBitmap,0,0,null); } ~~~ 現在的效果是這樣的: ![](https://box.kancloud.cn/2016-03-21_56efaea7d551e.jpg) 加一個XOR 試試。。 日了狗了!!!!!沒反應啊,到底是什么鬼。 ![](https://box.kancloud.cn/2016-03-21_56efaea7edd5f.jpg) 是不是兩個都需要bitmap才可以呢,再創建一個dstBitmap和dstCanvas? ~~~ mDstBitmap = Bitmap.createBitmap(50,50, Bitmap.Config.ARGB_8888); mDstCanvas = new Canvas(mDstBitmap); ~~~ 加一個XOR 試試 ~~~ @Override protected void onDraw(Canvas canvas) { //dst mDstCanvas.drawRect(20,20,80,80,mDstPaint); canvas.drawBitmap(mDstBitmap,0,0,mDstPaint); //src mSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); mSrcCanvas.drawCircle(25,25,25,mSrcPaint); canvas.drawBitmap(mSrcBitmap,0,0,mSrcPaint); } ~~~ 效果如下: ![](https://box.kancloud.cn/2016-03-21_56efaea8098dc.jpg) 終于他媽的出來了!!!!那其他效果呢? clear ![](https://box.kancloud.cn/2016-03-21_56efaea81ae65.jpg) 一致的!!!!好激動有沒有!!!!搞了4天 越來越接近結論了!!! **結論2:只有兩個bitmap的時候,才可以生效。** 不要高興太早。。如果坑到這里就完了,那還叫坑么。 繼續試。。嗯 好多模式都是一致的。 直到!!!SRC_IN和DST_IN ,會發現。。。都消失了。 為毛呢?? 檢查代碼 ?發現 在往bitmap畫圓之前就set了mode ?這樣會有影響 糾正 ~~~ @Override protected void onDraw(Canvas canvas) { //dst mDstCanvas.drawRect(20,20,80,80,mDstPaint); canvas.drawBitmap(mDstBitmap,0,0,mDstPaint); //src mSrcCanvas.drawCircle(25,25,25,mSrcPaint); //再畫圓之后 設置mode mSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); canvas.drawBitmap(mSrcBitmap,0,0,mSrcPaint); } ~~~ 發現 ![](https://box.kancloud.cn/2016-03-21_56efaea82df9a.jpg) 艸!!!!!!終于好了!!!!!!!!經過不懈努力!!!撒花!*★,°*:.☆\( ̄▽ ̄)/$:*.°★* 。? 其實我們剛才bitmap的大小是一樣的。 然后都是從0,0開始 完全覆蓋了。 那么錯開一點點 是什么效果呢,調整代碼如下 ~~~ protected void onDraw(Canvas canvas) { //dst mDstCanvas.drawRect(20,20,80,80,mDstPaint); canvas.drawBitmap(mDstBitmap,20,20,mDstPaint); //src mSrcCanvas.drawCircle(25,25,25,mSrcPaint); mSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(mSrcBitmap,0,0,mSrcPaint); } ~~~ 效果如下: ![](https://box.kancloud.cn/2016-03-21_56efaea8421d4.jpg) 可以看有效果了!!!! 但是是一個什么鬼!!! ?矩形缺角??加藍色一點?? 這樣看是很難看出效果的。。來調整一下bitmap的底色 和矩形的大小: 把兩個bitmap的底色都畫成灰色, 矩形不要占滿畫布 留出空間 ~~~ mDstCanvas.drawColor(Color.GRAY); ~~~ ~~~ @Override protected void onDraw(Canvas canvas) { //dst 黃色 mDstCanvas.drawRect(0,0,40,40,mDstPaint); canvas.drawBitmap(mDstBitmap,20,20,mDstPaint); //src 藍色 mSrcCanvas.drawCircle(25,25,25,mSrcPaint); canvas.drawBitmap(mSrcBitmap,0,0,mSrcPaint); } ~~~ 效果如下。。 ?嗯 這樣就是兩個bitmap了。。很明了 ?bitmap的內容 位置, ![](https://box.kancloud.cn/2016-03-21_56efaea851966.jpg) 然后再搞SRC_IN模式 ![](https://box.kancloud.cn/2016-03-21_56efaea8616cf.jpg) dst_in ?![](https://box.kancloud.cn/2016-03-21_56efaea872c07.jpg) 那么把bitmap底色去掉。 改成透明的呢? dst_in: ![](https://box.kancloud.cn/2016-03-21_56efaea886ee8.jpg) SRC_IN: ![](https://box.kancloud.cn/2016-03-21_56efaea89826c.jpg) **總結3:兩個bitmap位置不完全重疊的效果如上,并不能總結出效果,要按實際效果來。** ---------------------------------------------------------------------------------------------------------華麗麗的分割線----------------------------------------------------------------------------------------- **最終大總結,如果想讓PorterDuffXferMode按照預期Demo(或者效果圖)的效果圖像實現,必須滿足以下條件:** 1、關閉硬件加速。 2、兩個bitmap大小盡量一樣。 3、背景色為透明色。 4、如果兩個bitmap位置不完全一樣,可能也是預期效果,只不過你看到的效果和你自己腦補的預期效果不一致。 最后想再說幾句。鼓搗這個模式鼓搗了幾乎一周,每天晚上下班都在搞。查了無數資料。但是好多不完整,甚至有一些誤導性。所以為了避免后來者入坑。親自試驗,盡量總結。 如果有說的不正確的地方請及時向我提出。我會及時改正。 如果本文幫助到了你,請點一個頂,或者評論一下,蟹蟹!!!!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看