Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android圓角圓形圖(支持各種scaleType 一)

Android圓角圓形圖(支持各種scaleType 一)

編輯:關於Android編程

看了看以前的項目,發現用了一個叫RoundImageView的類,當時直接從網上copy的(^__^) 嘻嘻……,今天偶爾看到了,覺得不能一直停留在直接拖別人的代碼了,於是自己實現了一下,發現以前的只支持CENTER_CROP類型的縮放,於是自己看了下ImageView的源碼,實現了下支持所有縮放類型的ImageView.
先上一張效果圖:
這裡寫圖片描述

怎麼樣?效果還不錯吧!接下來我們來一步一步實現一下吧…….

實現圓角圓形的ImageView方式有很多,剛好在復習Paint的Xfermode,所以就先用Xfermode來實現了,

什麼時候Xfermode
我先上一張圖
這裡寫圖片描述

簡單說一下Xfermode的一些模式:
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
取兩圖層全部區域,交集部分變為透明色

思路:
畫一個圓角或圓形當做SRC(模板)然後自己設置的圖片當做DST然後用PorterDuff.Mode.DST_IN讓兩個相交的部分顯示出圖片,這樣說有點抽象,下面我們來一步一步實現以下。

attrs.xml:



    
    
        
        
    
    
        
        
    

然後我我們創建一個自定義View叫RoundImageView然後去獲取attrs中的屬性(想必這都是很簡單的操作了,老司機的你應該都敲爛了(^__^) 嘻嘻……):

package com.yqy.canvasdemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * @author EX_YINQINGYANG
 * @version [Android PABank C01, @2016-10-08]
 * @date 2016-10-08
 * @description
 */
public class RoundImageView extends ImageView {
    /**
     * 圓角ImageView圓角的半徑大小
     */
    private int mRadius=dp2px(10);
    /**
     * 圓形類型
     */
    private int TYPE_CIRCLE=0;
    /**
     * 圓角類型
     */
    private int TYPED_ROUND=1;
    /**
     * 圖片類型
     */
    private int mType=TYPE_CIRCLE;
    /**
     * 圖片縮放模式
     */
    private ScaleType mScaleType;
    public RoundImageView(Context context) {
        this(context,null);
    }

    public RoundImageView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        obtainStyleAttr(context,attrs,defStyleAttr);
        mScaleType=getScaleType();
    }

    private void obtainStyleAttr(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray a=context.getTheme().obtainStyledAttributes(attrs,R.styleable.RoundImageView,defStyleAttr,0);
        mRadius=a.getDimensionPixelSize(R.styleable.RoundImageView_borderRadius,mRadius);
        mType=a.getInteger(R.styleable.RoundImageView_type,mType);
        a.recycle();
    }

    /**
     * dp2px
     * @param value
     * @return px
     */
    private int dp2px(int value) {
        return (int) (value*getContext().getResources().getDisplayMetrics().density+0.5f);
    }
}

然後我們就要實現最重要的一步了,重寫onDraw方法(為了防止多次繪制然後不斷創建bitmap耗內存,我們這使用一個弱引用做一下Bitmap的緩存):

@Override
    protected void onDraw(Canvas canvas) {
        Bitmap bitmap = mWeakReference==null?null:mWeakReference.get();
        if(bitmap==null || bitmap.isRecycled()){
            //獲取一下設置的圖片資源
            Drawable drawable=getDrawable();
            if(drawable!=null){
                //創建一個空白畫布,用來畫模板跟原圖
                bitmap=Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
                Canvas dstCanvas=new Canvas(bitmap);
                //畫原圖
                drawable.draw(dstCanvas);
                //設置畫筆的Xfermode
                mPaint.setXfermode(mXfermode);
                //畫模板
                if(mMaskBitmap==null||mMaskBitmap.isRecycled()){
                    mMaskBitmap=getShapeBitmap();
                }
                dstCanvas.drawBitmap(mMaskBitmap,0,0,mPaint);
                mPaint.setXfermode(null);
            }
        }
       //最後把我們准備好的Bitmap畫在canvas上
        canvas.drawBitmap(bitmap,0,0,null);
    }

 /**
     * 根據Shape類型創建ShapeBitmap
     */
    private Bitmap getShapeBitmap() {
        Bitmap bitmap=Bitmap.createBitmap(getWidth(),getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas =new Canvas(bitmap);
        if(TYPE_CIRCLE==mType){
            canvas.drawCircle(canvas.getWidth()/2,canvas.getHeight()/2,canvas.getWidth()/2,shapePaint);
        } else{
            canvas.drawRound


Rect(new RectF(0,0,canvas.getWidth(),canvas.getHeight()),mRadius,mRadius,shapePaint);
        }
        return bitmap;
    }

代碼比較簡單,都有注釋的,我就不解釋了。

寫到這裡一個簡單的圓角圓形ImageView就可以使用了,是不是很簡單呢?有些東西吧,還是得自己去琢磨琢磨,哪怕是什麼都不會,跟著敲一篇總會有收獲的。(不怕笑話,我一開始連別人代碼都看不懂(^__^) 嘻嘻…… 只會拖著用,然後一個一個查到底什麼意思。)廢話不說了。
我們運行代碼:
這裡寫圖片描述

**問題來了:效果是有了,但有發現麼?我設置的scaleType只有fitxy
是有效果的,其他的都沒有效果了。設置為其他的scaleType都變成matrix那種效果了,也就是圖片默認從控件的左上角開始擺放。**

現附上現階段的源碼:

package com.yqy.canvasdemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

import com.cisetech.circleviewdemo.R;

import java.lang.ref.WeakReference;

/**
 * @author EX_YINQINGYANG
 * @version [Android PABank C01, @2016-10-08]
 * @date 2016-10-08
 * @description
 */
public class RoundImageView extends ImageView {
    /**
     * 圓角ImageView圓角的半徑大小
     */
    private int mRadius=dp2px(10);
    /**
     * 圓形類型
     */
    private int TYPE_CIRCLE=0;
    /**
     * 圓角類型
     */
    private int TYPED_ROUND=1;
    /**
     * 圖片類型
     */
    private int mType=TYPE_CIRCLE;
    /**
     * 圖片縮放模式
     */
    private ScaleType mScaleType;
    /**
     * 緩存bitmap
     */
    private WeakReferencemWeakReference;
    /**
     * 模板Bitmap
     */
    private Bitmap mMaskBitmap;
    /**
     * 畫筆
     */
    private Paint mPaint;
    /**
     * shape paint
     */
    private Paint shapePaint;
    /**
     * 畫筆Xfermode
     */
    private Xfermode mXfermode=new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
    public RoundImageView(Context context) {
        this(context,null);
    }

    public RoundImageView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        obtainStyleAttr(context,attrs,defStyleAttr);
        mScaleType=getScaleType();
        mPaint=new Paint(Paint.ANTI_ALIAS_FLAG|Paint.DITHER_FLAG);
        shapePaint=new Paint(Paint.ANTI_ALIAS_FLAG|Paint.DITHER_FLAG);
    }

    private void obtainStyleAttr(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray a=context.getTheme().obtainStyledAttributes(attrs, R.styleable.RoundImageView,defStyleAttr,0);
        mRadius=a.getDimensionPixelSize(R.styleable.RoundImageView_borderRadius,mRadius);
        mType=a.getInteger(R.styleable.RoundImageView_type,mType);
        a.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Bitmap bitmap = mWeakReference==null?null:mWeakReference.get();
        if(bitmap==null || bitmap.isRecycled()){
            //獲取一下設置的圖片資源
            Drawable drawable=getDrawable();
            if(drawable!=null){
                //創建一個空白畫布,用來畫模板跟原圖
                bitmap=Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
                Canvas dstCanvas=new Canvas(bitmap);
                //畫原圖
                drawable.draw(dstCanvas);
                //設置畫筆的Xfermode
                mPaint.setXfermode(mXfermode);
                //畫模板
                if(mMaskBitmap==null||mMaskBitmap.isRecycled()){
                    mMaskBitmap=getShapeBitmap();
                }
                dstCanvas.drawBitmap(mMaskBitmap,0,0,mPaint);
                mPaint.setXfermode(null);
            }
        }
        //最後把我們准備好的Bitmap畫在canvas上
        canvas.drawBitmap(bitmap,0,0,null);
    }

    /**
     * 根據Shape類型創建ShapeBitmap
     */
    private Bitmap getShapeBitmap() {
        Bitmap bitmap=Bitmap.createBitmap(getWidth(),getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas =new Canvas(bitmap);
        if(TYPE_CIRCLE==mType){
            canvas.drawCircle(canvas.getWidth()/2,canvas.getHeight()/2,canvas.getWidth()/2,shapePaint);
        } else{
            canvas.drawRoundRect(new RectF(0,0,canvas.getWidth(),canvas.getHeight()),mRadius,mRadius,shapePaint);
        }
        return bitmap;
    }

    /**
     * dp2px
     * @param value
     * @return px
     */
    private int dp2px(int value) {
        return (int) (value*getContext().getResources().getDisplayMetrics().density+0.5f);
    }
}

太長了,先到這裡了…….未完待續啊

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