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

来源:http://www.cnblogs.com/r-decade/archive/2017/01/04/6250450.html
-Advertisement-
Play Games

看下效果先 下麵有完整的示例代碼 使用BitmapShader(著色器) 我們在繪製view 的時候 就是小學上美術課 用水彩筆在本子上畫畫 使用著色器繪製圓形圖片最簡單的理解方式 就是把bitmap當做一種顏色 設置給paint ,paint都已經有顏色了 你想讓它方了,圓了,扁了 還不是看你心情 ...


看下效果先

下麵有完整的示例代碼

使用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);
    }
}




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • html 代碼<div id="outer"> <span>#</span> <div id="inner"> 德國名企德司達被中國上市公司龍盛集團收購後,其下屬的德司達(南京)染料有限公司因夜間向運河偷排廢酸2698.1噸,公司被揚州中級法院判決構成污染環境罪 </div></div>JavaSc ...
  • 舉個慄子<script> var now = new Date();// now.setDate(now.getDate()-num);// var result = '';// result+=now.getFullYear()+'-'+// (now.getMonth()+1)+'-'+// ( ...
  • Javascript 2016年12月19日整理 JS基礎 Chapter1 1. JS是一門運行在瀏覽器客戶端的腳本編程語言,前臺語言 1. 組成部分 1. ECMAscript JS標準 2. DOM 通過JS操作網頁元素 3. BOM 通過調用API操作瀏覽器 2. 特點: 封裝,繼承,多態 ...
  • 什麼是應用程式緩存(Application Cache)? HTML5 引入了應用程式緩存,這意味著 web 應用可進行緩存,並可在沒有網際網路連接時進行訪問。 應用程式緩存為應用帶來三個優勢: 離線瀏覽 - 用戶可在應用離線時使用它們 速度 - 已緩存資源載入得更快 減少伺服器負載 - 瀏覽器將只從 ...
  • CSS學習筆記 2016年12月15日整理 CSS基礎 Chapter1 在console輸入escape("宋體") ENTER 就會出現unicode編碼 顯示"%u5B8B%u4F53" 就是\5B8B\4F53 font family: 中文,英文,最好的是unicode編碼 eg. fon ...
  • HTML學習筆記 2016年12月15日整理 Chapter1 1. 1. scheme: 定義網際網路服務的類型,常見的為http 2. host: 定義域主機(http的預設主機是www) 3. domain: 定義網際網路功能變數名稱 4. port: 定義埠號,預設是埠80 5. path: 網頁在 ...
  • attribute 是原生js dom 對象上的一個屬性,這個屬性有很多子屬性,比如 isId(判斷屬性是否是Id) , name (獲取屬性名稱) , value (獲取屬性值),attributes 用來獲取dom元素 的所有屬性集合。 話不多說,上例子了: attrs 中就包含 input 所 ...
  • 文本超出部分隱藏,總結兩種方法。 1、單行隱藏 html代碼 css代碼 結果 當文字超過範圍的時候,超出部分會隱藏起來。 2、多行隱藏 css代碼 結果 當文字超過範圍的時候,超出部分會隱藏起來。可以設置第幾行開始隱藏。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...