android繪制圓形圖片的兩種方式


看下效果先

下面有完整的示例代碼

使用BitmapShader(着色器)

我們在繪制view 的時候 就是小學上美術課 用水彩筆在本子上畫畫 使用着色器繪制圓形圖片最簡單的理解方式 就是把bitmap當做一種顏色 設置給paint ,paint都已經有顏色了 你想讓它方了,圓了,扁了 還不是看你心情 canvas調用那個方法咯

實現的大致思路如下:
1. 創建一個類 繼承imageView 重寫onDraw()
2. 獲取到bitmap圖片
3. 計算圖片的縮放比例 使用矩陣matrix 進行縮放
4. 創建BitmapShader着色器 設置縮放矩陣
5. paint設置着色器 繪制

具體實現 注釋也標注的很清楚

   private void shaderCircle(Canvas canvas){
        //獲取Drawable
        Drawable resources=getDrawable();
        float scale = 1.0f;//縮放比例
        int mRadius=0;//圓的半徑
        if (resources instanceof BitmapDrawable){
            //獲取bitmap
            Bitmap bitmap=((BitmapDrawable) resources).getBitmap();
            if (bitmap==null) return;
            // 獲取bitmap寬高中的小值
            int minBitMap = Math.min(bitmap.getWidth(), bitmap.getHeight());
            //取view寬高中的小值 盡量保證圖片內容的顯示
            int minValue=Math.min(getWidth(),getHeight());
            //設置半徑
            mRadius=minValue/2;
            //計算縮放比例  一定要*1.0f 因為int之間的計算結果會四舍五入0或1 效果就不美麗了
            scale=minValue*1.0f/minBitMap;
            //設置縮放比例
            matrix.setScale(scale,scale);
            /**
             * 創建着色器 設置着色模式
             * TileMode的取值有三種:
             *  CLAMP 拉伸  REPEAT 重復   MIRROR 鏡像
             */
            BitmapShader shader=new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            //設置矩陣
            shader.setLocalMatrix(matrix);
            paint.setShader(shader);
            canvas.drawCircle(mRadius, mRadius, mRadius, paint);
        }
    }

使用Xfermode 設置圖片相交模式

簡單說呢 在一張畫布上畫了兩張圖片 這兩張圖的以怎樣的方式顯示出來 例如:只顯示上層圖片,只顯示下層圖片 ,顯示兩張圖的交集部分 等等等

實現思路

  1. 創建一個空bitmap 根據這個bitmap創建一個Canvas
  2. 設置Canvas透明 畫一個想要實現的形狀
  3. 設置圖形相交模式
  4. 獲取圖片資源 繪制到Canvas

實現代碼

 private Bitmap getCircleBitmap(){
        Drawable drawable=getDrawable();

        if (drawable instanceof BitmapDrawable) {
            Paint paint=new Paint();
            paint.setAntiAlias(true);
            //獲取資源圖片
            Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
            //創建空位圖
            Bitmap output=Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
            //創建畫板
            Canvas canvas=new Canvas(output);
            //繪制整個畫板為透明
            canvas.drawColor(Color.TRANSPARENT);
            paint.setColor(Color.WHITE);
            //繪制圓角圖片
            if (type==ROUND){
                canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()), mRound, mRound,paint);
            }else{
				//繪制圓形圖片
			
                //取view寬高中的小值 盡量保證圖片內容的顯示
                int minValue = Math.min(getWidth(), getHeight());
                //設置半徑
                mRadius = minValue / 2;
                canvas.drawCircle(mRadius,mRadius,mRadius,paint);
            }
            //設置圖形相交模式
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

            Rect src=new Rect(0,0,bitmap.getWidth(),bitmap.getHeight());
            Rect dst=new Rect(0,0,output.getWidth(),output.getHeight());
            canvas.drawBitmap(bitmap,src,dst,paint);
            return output;
        }
        return null;

    }

這個特別經典的圖......

PorterDuff.Mode.CLEAR 清除畫布上圖像
PorterDuff.Mode.SRC 顯示上層圖像
PorterDuff.Mode.DST 顯示下層圖像
PorterDuff.Mode.SRC_OVER上下層圖像都顯示,上層居上顯示
PorterDuff.Mode.DST_OVER 上下層都顯示,下層居上顯示
PorterDuff.Mode.SRC_IN 取兩層圖像交集部分只顯示上層圖像
PorterDuff.Mode.DST_IN 取兩層圖像交集部分,只顯示下層圖像
PorterDuff.Mode.SRC_OUT 取上層圖像非交集部分
PorterDuff.Mode.DST_OUT 取下層圖像非交集部分
PorterDuff.Mode.SRC_ATOP 取下層圖像非交集部分與上層圖像交集部分
PorterDuff.Mode.DST_ATOP 取上層圖像非交集部分與下層圖像交集部分
PorterDuff.Mode.XOR 取兩層圖像的非交集部分

參考文檔

講Shader類非常非常屌的帖子
詳解Paint的setXfermode

繼承ImageVIew完成圓形和圓角圖片控件的實現過程(使用着色器)

    <declare-styleable name="CircleImage">
        <attr name="imageRound" format="dimension"/>
        <attr name="imageType">
            <enum name="circle" value="0"/>
            <enum name="round" value="1"/>
        </attr>

    </declare-styleable>
public class CircleImage extends ImageView {

    private Matrix matrix;
    private Paint paint;
    private int mRound;//圓角度數
    private int mRadius;//圓的半徑
    private int type;//控件類型
    private final int CIRCLE=0;//圓形
    private final int ROUND=1;//圓角

    public CircleImage(Context context) {
        super(context,null);
    }

    public CircleImage(Context context, AttributeSet attrs) {
        super(context, attrs);
        matrix=new Matrix();
        paint=new Paint();
        paint.setAntiAlias(true);
        initAttrValues(context,attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (getDrawable() == null) {
            return;
        }
        setShader();
        if (type==CIRCLE){
            canvas.drawCircle(mRadius, mRadius, mRadius, paint);
        }else{
            canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()), mRound, mRound,paint);
        }
    }

    /**
     * 初始化屬性集合
     * @param context
     * @param attrs
     */
    private void initAttrValues(Context context, AttributeSet attrs){
        TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.CircleImage);
        for (int i=0;i<typedArray.getIndexCount();i++){
            int index=typedArray.getIndex(i);
            switch (index){
                case R.styleable.CircleImage_imageRound:
                    mRound =typedArray.getDimensionPixelSize(index,
                            (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,getResources().getDisplayMetrics()));
                    break;
                case R.styleable.CircleImage_imageType:
                    type=typedArray.getInt(index,CIRCLE);
                    break;
            }
        }
    }

    /**
     * 設置着色器
     */
    private void setShader() {
        //獲取Drawable
        Drawable resources=getDrawable();
        float scale = 1.0f;//縮放比例
        if (resources instanceof BitmapDrawable) {
            //獲取bitmap
            Bitmap bitmap = ((BitmapDrawable) resources).getBitmap();
            if (bitmap == null) return;
            //圓形
            if (type==CIRCLE){
                // 獲取bitmap寬高中的小值
                int minBitMap = Math.min(bitmap.getWidth(), bitmap.getHeight());
                //取view寬高中的小值 盡量保證圖片內容的顯示
                int minValue = Math.min(getWidth(), getHeight());
                //設置半徑
                mRadius = minValue / 2;
                //計算縮放比例  一定要*1.0f 因為int之間的計算結果會四舍五入0或1 效果就不美麗了
                scale = minValue * 1.0f / minBitMap;
            }else{
                //比較view和圖片寬高比例大的 要讓縮放后的圖片大於view
                scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight()
                        * 1.0f / bitmap.getHeight());
            }
            //設置縮放比例
            matrix.setScale(scale, scale);
            /**
             * 創建着色器 設置着色模式
             * TileMode的取值有三種:
             *  CLAMP 拉伸  REPEAT 重復   MIRROR 鏡像
             */
            BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            //設置矩陣
            shader.setLocalMatrix(matrix);
            //設置着色
            paint.setShader(shader);
        }
    }


    /**
     * 測試轉換效果 沒什么卵用 可以刪除
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction()==MotionEvent.ACTION_DOWN){
            if (type==CIRCLE){
                mRound =10;
                type=ROUND;
            }else{
                type=CIRCLE;
            }
            invalidate();
        }
        return super.onTouchEvent(event);
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM