Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 自定義View時,用到Paint Canvas的一些溫故,講講平時一些效果是怎麼畫的(基礎篇 二,圖像遮蓋,Canvas靜態變化)

自定義View時,用到Paint Canvas的一些溫故,講講平時一些效果是怎麼畫的(基礎篇 二,圖像遮蓋,Canvas靜態變化)

編輯:關於Android編程

上一篇把簡單的一些概念理一理,還畫了個圈,那這一篇講一下圖像遮蓋“Xfermode”和Canvas的旋轉。平移等效果

Xfermode:

AvoidXfermode 指定了一個顏色和容差,強制Paint避免在它上面繪圖(或者只在它上面繪圖)。

PixelXorXfermode 當覆蓋已有的顏色時,應用一個簡單的像素異或操作。

PorterDuffXfermode 這是一個非常強大的轉換模式,使用它,可以使用圖像合成的16條Porter-Duff規則的任意一條來控制Paint如何與已有的Canvas圖像進行交互。

我們今天的呈現就是在PorterDuffXfermode 這部分實現的

PorterDuff.Mode為枚舉類,一共有16個枚舉值分別是

1.PorterDuff.Mode.CLEAR
所繪制不會提交到畫布上。
2.PorterDuff.Mode.SRC
顯示上層繪制圖片
3.PorterDuff.Mode.DST
顯示下層繪制圖片
4.PorterDuff.Mode.SRC_OVER
正常繪制顯示,上下層繪制疊蓋。
5.PorterDuff.Mode.DST_OVER
上下層都顯示。下層居上顯示。
6.PorterDuff.Mode.SRC_IN
取兩層繪制交集。顯示上層。
7.PorterDuff.Mode.DST_IN
取兩層繪制交集。顯示下層。
8.PorterDuff.Mode.SRC_OUT
取上層繪制非交集部分。
9.PorterDuff.Mode.DST_OUT
取下層繪制非交集部分。
10.PorterDuff.Mode.SRC_ATOP
取下層非交集部分與上層交集部分
11.PorterDuff.Mode.DST_ATOP
取上層非交集部分與下層交集部分
12.PorterDuff.Mode.XOR
異或:去除兩圖層交集部分
13.PorterDuff.Mode.DARKEN
取兩圖層全部區域,交集部分顏色加深
14.PorterDuff.Mode.LIGHTEN
取兩圖層全部,點亮交集部分顏色
15.PorterDuff.Mode.MULTIPLY
取兩圖層交集部分疊加後顏色
16.PorterDuff.Mode.SCREEN
取兩圖層全部區域,交集部分變為透明色

在將這一系列的效果之前我們先把我們昨天畫圓的例子改一下

public class TestView extends View {
    Paint paint;
    Context context;
    Bitmap bitmap;

    public TestView(Context context) {
        super(context);
        this.context = context;
    }

    public TestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public TestView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public TestView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        paint = new Paint();
//        paint.setColor(getResources().getColor(R.color.SlateBlue));
        paint.setColor(getResources().getColor(R.color.Gold));
        paint.setStrokeWidth(3);                        //粗細
        paint.setAntiAlias(true);                       //設置畫筆為無鋸齒
        bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.bg);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d("--->onDraw", "onDraw()");
//        canvas.drawCircle(0, 0, 90, paint);
        canvas.drawBitmap(bitmap,0,0,paint);
        canvas.drawCircle(100, 100, 90, paint);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        Log.d("--->onLayout", "changed = " + changed + " left = " + left + " top = " + top + " right = " + right + " bottom " + bottom);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.d("--->onMeasure", "  widthMeasureSpec =" + widthMeasureSpec + "  heightMeasureSpec = " + heightMeasureSpec);
        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    }
}

我們在畫圓之後又畫了個背景圖,效果如下:

這裡寫圖片描述

在我們的圓下面有一個妹子,並且圓是會蓋掉妹子那一塊圓的塗抹面積的。

那我們把onDraw()方法裡執行的順序換一下呢?

   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d("--->onDraw", "onDraw()");
//        canvas.drawCircle(0, 0, 90, paint);
          canvas.drawCircle(100, 100, 90, paint);
          canvas.drawBitmap(bitmap,0,0,paint);   
    }

如果改成這樣,我們的圓就沒了(效果不貼了)

利用PorterDuff.Mode就可以很好的解決這個問題當然,可能你得多繪制一次然後再做覆蓋的操作了,所以在你決定先畫什麼後畫什麼之前一定理清誰在前誰在後

本來想寫個大致的例子,但是想想16個都好麻煩,就拿了一個市面上比較多的圖吧

這裡寫圖片描述


Canvas靜態變化

上面的代碼不變,我們在新建一個Canvas然後把他裡面話一點東西,來模擬我們想要的效果。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d("--->onDraw", "onDraw()");
//        canvas.drawCircle(0, 0, 90, paint);
        canvas.drawCircle(100, 100, 90, paint1);
        canvas.drawBitmap(bitmap, 120, 120, paint1);
        Canvas canvas1=new Canvas(bitmap);

        Paint paint2=new Paint();
        paint2.setColor(getResources().getColor(R.color.LightPink));
        paint2.setTextSize(50);
        canvas1.drawText("Ezreal", 0, 200, paint2);

        canvas1.drawText("Malzahar ",0,300,paint2);
    }

效果如下:

這裡寫圖片描述

P1.我們用畫布又畫了2個字。那麼我們來試下各種效果(分析和方法,會分兩部分羅列)

平移:1.void translate(float dx, float dy)<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPsa90sayzsr9o7oyuPbX+LHqteNY1f3P8tPSIFnV/c/yz8KjrLi6yv23tNauoaM8L3A+DQo8cD48c3Ryb25nPtD916o8L3N0cm9uZz6jujxiciAvPg0KMS52b2lkIHJvdGF0ZShmbG9hdCBkZWdyZWVzKTxiciAvPg0KMi52b2lkIHJvdGF0ZSAoZmxvYXQgZGVncmVlcywgZmxvYXQgcHgsIGZsb2F0IHB5KTwvcD4NCjxwPtD916qyzsr9o7rS1Nf4serUrbXjo6jX88nPo6nOqtD916rW0NDE16pkZWdyZWVztsijqNX9tcTOqtX916qjrLi6tcTOqre016qjqaOscHgscHnOqtLUKHB4LHB5Kc6q1tDQxND916pkZWdyZWVztsguPC9wPg0KPHA+PHN0cm9uZz7L9bfFPC9zdHJvbmc+o7o8YnIgLz4NCjEucHVibGljIHZvaWQgc2NhbGUgKGZsb2F0IHN4LCBmbG9hdCBzeSk8YnIgLz4NCjIucHVibGljIGZpbmFsIHZvaWQgc2NhbGUgKGZsb2F0IHN4LCBmbG9hdCBzeSwgZmxvYXQgcHgsIGZsb2F0IHB5KTwvcD4NCjxwPsv1t8Wyzsr9o7pzeM6qy67Gvcv1t8WjrDGx7cq+srux46OstPPT2jG3xbTzo6zQodPrMcv10KGjqLi6tcTO0sO7ytS5/aOpo7tzedTyse3KvrS51rGjrMLfvK3NrMuuxr0uPC9wPg0KPHA+PHN0cm9uZz7QscfQPC9zdHJvbmc+o7o8L3A+DQo8cD4xLnZvaWQgc2tldyAoZmxvYXQgc3gsIGZsb2F0IHN5KTwvcD4NCjxwPtCxx9Cyzsr9o7pzeDq9q7utsrzU2ni3vc/yyc/H49Cxz+DTprXEvce2yKOsc3jH49Cxvce2yLXEdGFu1rWju3N5Or2ru62yvNTaedbht73P8snPx+PQsc/g06a1xL3HtsijrHN5zqrH49Cxvce2yLXEdGFu1rUuPC9wPg0KPGhyIC8+DQo8cD5QMi7Ktc/W0tS8sL3iys2jujwvcD4NCjxwPjEuxr3SxqO6PGJyIC8+DQo8aW1nIGFsdD0="這裡寫圖片描述" src="/uploadfile/Collfiles/20151230/20151230092039134.png" title=""http://zz.2cto.com/seo/" target="_blank" class="keylink">seorMzAwo6xZ1/ix6iszMDCjqaGjPC9wPg0KPHA+tavKxyDQp7n7ysfV4tH5wvCjvzwvcD4NCjxwPs6qwcvR6dakyLfKtcjntMvO0sPH1NnU2dPSsuC7rdK7uPYmbGRxdW87QWthbGkmcmRxdW87PC9wPg0KPHByZSBjbGFzcz0="brush:java;"> //並且是在平移前執行 canvas1.drawText("Akali ",200,400,paint2);

這裡寫圖片描述

然後我們在平移之後再畫一個Katarina Du Couteau

並且跟平移前的阿卡麗是用以坐標

  canvas1.drawText("Katarina Du Couteau ", 200, 400, paint2);

這裡寫圖片描述

效果是卡特跟著整個坐標系走了而不是之前的坐標相加的結果。

所以:

1.每次調用canvas.drawXXXX系列函數來繪圖進,都會產生一個全新的Canvas畫布。
2.在Canvas與屏幕合成時,超出屏幕范圍的圖像是不會顯示出來的。

2.旋轉

我們還是回到最初的螞蚱和EZ的樣子

  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d("--->onDraw", "onDraw()");
//        canvas.drawCircle(0, 0, 90, paint);
        canvas.drawCircle(100, 100, 90, paint1);
        canvas.drawBitmap(bitmap, 120, 120, paint1);
        Canvas canvas1 = new Canvas(bitmap);

        Paint paint2 = new Paint();
        paint2.setColor(getResources().getColor(R.color.LightPink));
        paint2.setTextSize(50);
//        canvas1.drawText("Akali ", 200, 400, paint2);

//        canvas1.translate(300, 300);
        canvas1.drawText("Ezreal", 0, 200, paint2);
        canvas1.rotate(30);
        canvas1.drawText("Malzahar ", 0, 300, paint2);

//        canvas1.drawText("Katarina Du Couteau ", 200, 400, paint2);
    }

然後把螞蚱旋轉30度,效果如圖

這裡寫圖片描述

EZ位置沒變,螞蚱轉了,並且有一部分超出了我們的妹子Bitmap所以它不見了。

然後此時此刻,我們的阿卡麗回來了,並且在螞蚱之後

這裡寫圖片描述

我們的啊卡裡也跟著螞蚱轉走了,說明旋轉和平移是一樣的整個位圖轉走了。

如下圖向著箭頭方向偏了30度然後創建了一個新的Canvas

這裡寫圖片描述

3.縮放

縮放的圖我就不畫了,代碼就是canvas.scale(1, 1.5f); 就是Y方向縮放1.5f

也是重繪了一個Canvas和上面都一樣。

4.斜切
其實也就是可以實現我們的一個斜體的效果,這裡就貼一下執行效果

這裡寫圖片描述

還有就是int save () void restore()相對比較簡單,對堆棧的概念清晰的小伙伴一看就懂,不需要過多試驗,這裡就不明說了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved