Android 遮罩層效果

來源:互聯網
上載者:User

標籤:android   style   blog   http   color   使用   java   io   ar   

(用別人的代碼進行分析) 不知道在開發中有沒有經常使用到這種效果,所謂的遮罩層就是給一張圖片不是我們想要的形狀,這個時候我們就可以使用遮罩效果把這個圖片變成我們想要的形狀,一般使用最多就是圓形的效果,如:

上面這個圖片是圓形的,而我們這個原圖是正方形的,所以我們可能就需要這麼一個遮罩的效果使它變為圓形,這種一般就是我們圖片從網路上擷取的,形狀不是由我們自己定的,所以才會加上這麼一個效果,看下面的原圖:

這個是一個正方形的,那麼要弄這麼一個圓形,我們還需要一個圓形全黑的圖片,如下

就是這個圖片,其實簡單的來說就是兩個圖片相結合,只顯示被黑色圖片覆蓋的地區,外面的地區就不顯示,這樣就成一個圓形的圖片了(上面的圖片都是採用從別的應用程式來的),其實這個主要的技術還是涉及到了PorterDuffXfermode類的使用方法,

PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);

上面就是PorterDuffXfermode類的建立,那麼裡面的參數PorterDuff.Mode.SRC_IN其實有很多中情況,好像有達到16中情況,下面介紹一下常用的:

PorterDuff.Mode.SRC_IN:取兩層繪製交集。顯示上層。就是如果上面兩張圖片相疊,那麼取這兩張圖片的交集而且顯示的是上層那種圖片

PorterDuff.Mode.DST_IN:  取兩層繪製交集。顯示下層。

其它可以到網上可以查詢得到,這兩個用得也比較多。下面還有一張圖片是外圍那層圖片的效果

好,我們現在來看看這個代碼是如何來寫的

package com.example.myimageview;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.util.AttributeSet;import android.view.View;public class MyImageView extends View {        private Context context;        private Bitmap bitmapBorder;    private Bitmap bitmapMask;    private Paint paint;    private PorterDuffXfermode xfermode;        private Bitmap bitmap;        private int _width;    private int _height;    public MyImageView(Context context){        this(context, null);    }    public MyImageView(Context context, AttributeSet attrs) {        super(context, attrs);        this.context = context;                bitmapBorder = decodeBitmap(R.drawable.border);        bitmapMask = decodeBitmap(R.drawable.mask);                _width = bitmapBorder.getWidth();        _height = bitmapBorder.getHeight();                paint = new Paint();        xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);    }    public MyImageView(Context context, AttributeSet attrs, int defStyle) {        this(context, attrs);    }        @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(_width, _height);    }        private Bitmap decodeBitmap(int resId) {        return BitmapFactory.decodeResource(context.getResources(), resId);    }        public void setResourseId(int resourseId) {        bitmap = decodeBitmap(resourseId);        invalidate();    }        public void setResourseBitmap(Bitmap bitmap){        this.bitmap = bitmap;        invalidate();    }        @Override    protected void onDraw(Canvas canvas) {        if(bitmap == null){            return;        }        canvas.drawBitmap(bitmapBorder, 0, 0, paint);        int saveFlags = 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.saveLayer(0, 0, _width, _height, null, saveFlags);        canvas.drawBitmap(bitmapMask, 0, 0, paint);        paint.setXfermode(xfermode);        int left = _width/2 - bitmap.getWidth() /2;        int top = _height/2 - bitmap.getHeight()/2;        canvas.drawBitmap(bitmap, left, top, paint);        paint.setXfermode(null);        canvas.restore();    }}

下面我們來分析一下代碼的結構:

MyImageView是繼承view的一個子類,在建構函式中我們看到設定兩張圖片bitmapBorder就是我上面貼出來的最下面外圍的圖片,bitmapMask就是那個全黑圓形的圖片,_width和_height是bitmapBorder(外圍那張圖片的寬度和高度),因為那張圖片是最大的我們需要定義這個view的大小所以需這個寬和高,下面

    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(_width, _height);    }

就是使用寬和高來處理的,同時我們還看到了畫筆Paint和PorterDuffXfermode建立,要說明一下這個PorterDuffXfermode對象是通過畫筆Paint來設定的,下面有說明的

    public void setResourseId(int resourseId) {        bitmap = decodeBitmap(resourseId);        invalidate();    }

這個代碼就是需要我們手動傳入想要變為圓形的圖片,這個是在Avtivity中設定就行,最主要的代碼來看onDraw()方法裡面的。

    @Override    protected void onDraw(Canvas canvas) {        if(bitmap == null){            return;        }        canvas.drawBitmap(bitmapBorder, 0, 0, paint);        int saveFlags = 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.saveLayer(0, 0, _width, _height, null, saveFlags);        canvas.drawBitmap(bitmapMask, 0, 0, paint);        paint.setXfermode(xfermode);        int left = _width/2 - bitmap.getWidth() /2;        int top = _height/2 - bitmap.getHeight()/2;        canvas.drawBitmap(bitmap, left, top, paint);        paint.setXfermode(null);        canvas.restore();    }

我們來看有三個地方使用了canvas.drawBitmap這個方法,簡單理解就是誰先那麼該圖片就顯示在最下面,最後使用的drawBitmap()方法就顯示在最上面

canvas.saveLayer()方法和canvas.restore()是成對出現的,

Canvas 在一般的情況下可以看作是一張畫布,所有的繪圖操作如drawBitmap, drawCircle都發生在這張畫布上,這張畫板還定義了一些屬性比如Matrix,顏色等等。但是如果需要實現一些相對複雜的繪圖操作,比如多層動 畫,地圖(地圖可以有多個地圖層疊加而成,比如:政區層,道路層,興趣點層)。Canvas提供了圖層(Layer)支援,預設情況可以看作是只有一個圖 層Layer。如果需要按層次來繪圖,Android的Canvas可以使用SaveLayerXXX, Restore 來建立一些中介層,對於這些Layer是按照“棧結構“來管理的:   

 建立一個新的Layer到“棧”中,可以使用saveLayer, savaLayerAlpha, 從“棧”中推出一個Layer,可以使用restore,restoreToCount。但Layer入棧時,後續的DrawXXX操作都發生在這個 Layer上,而Layer退棧時,就會把本層繪製的映像“繪製”到上層或是Canvas上,在複製Layer到Canvas上時,可以指定Layer的 透明度(Layer),這是在建立Layer時指定的:public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags);

具體點可以到http://blog.csdn.net/linghu_java/article/details/8939952這個網站瞭解一下。

paint.setXfermode(xfermode);這個就是設定了畫筆的效果了,left和top不用說了就是該圖片要顯示在中心的位置。canvas.drawBitmap(bitmap, left, top, paint);這個是最後那個canvas.drawBitmap方法,而且使用的PorterDuff.Mode.SRC_IN參數,表示的是取兩層繪製交集。顯示上層,那就是顯示最後一張圖片。

其實從上面來看效果是不錯的,但是在真正的應用中我們不難會發現有些圖片可能很大,這個時候就需要我們對圖片進行等比的放大效果

http://bbs.csdn.net/topics/310218516這個網址就看到有介紹等比縮放圖片的例子,我們來看下面的圖片效果

上面兩張圖對比,第一張就是原來的效果,第二張就是對圖片進行等比的縮放效果,看看第二張圖片代碼的:

package com.example.myimageview;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PorterDuffXfermode;import android.graphics.RectF;import android.graphics.PorterDuff.Mode;import android.util.AttributeSet;import android.view.View;public class itchqImageView extends View{    private Bitmap bg;    private Bitmap photo;        private int bg_width;    private int bg_height;    public itchqImageView(Context context, AttributeSet attrs) {        super(context, attrs);        // TODO Auto-generated constructor stub        init();    }        private void init(){        bg=BitmapFactory.decodeResource(getResources(),R.drawable.mask);        bg_width=bg.getWidth();        bg_height=bg.getHeight();    }    public void setImageView(int imgId){        photo=BitmapFactory.decodeResource(getResources(), imgId);        scaleImage();    }    @Override    protected void onDraw(Canvas canvas) {        // TODO Auto-generated method stub        super.onDraw(canvas);        Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);                paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));                RectF rectf=new RectF(0,0,bg_width,bg_height);                canvas.saveLayer(rectf, null, Canvas.ALL_SAVE_FLAG);        canvas.drawBitmap(photo, 0,0, null);        canvas.drawBitmap(bg, 0, 0,paint);        canvas.restore();    }        private void scaleImage(){                if(photo!=null){                        int widht=photo.getWidth();            int height=photo.getHeight();                        int new_width=0;            int new_height=0;                        if(widht!=height){                if(widht>height){                    new_height=bg_height;                    new_width=widht*new_height/height;                }else{                    new_width=bg_width;                    new_height=height*new_width/widht;                }            }else{                new_width=bg_width;                new_height=bg_height;            }            photo = Bitmap.createScaledBitmap(photo, new_width, new_height, true);        }    }    }
scaleImage()這個方法裡面就是對圖片進行等比的縮放效果,縮放的大小就和我們全黑色的圖片大小一樣(這裡我們原來外面圓形效果去掉了,就是上面第三張全白色的圖片)
如果圖片不是正方形的我們就需要進行判斷對比,最後得出的寬和高就是我們要等比縮放的大小。

Android 遮罩層效果

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.