Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 【Android】Android自定義帶board的圓角控件

【Android】Android自定義帶board的圓角控件

編輯:關於Android編程

介紹

圓角控件常用於頭像,按鈕,圖標等,用途十分廣泛,而且常常配合board使用。

\

在IOS中,UIVIew的CALayer層已經提供了圓角和board的方法,所以圓角控件的制作非常簡單,只需要類似以下簡單代碼即可實現:

 

    view.layer.cornerRadius = 20;
    view.layer.borderColor = [UIColor yellowColor].CGColor;
    view.layer.borderWidth = 10;
    view.clipsToBounds = YES;

而在Android中,系統並沒有提供這麼直接的方式,所以想要實現同樣的效果需要費點心了。本文將會介紹一種在Android中實現帶board屬性的圓角控件的方法。該方法定義了一個RoundImageView重寫了ImageView的onDraw方法,並加入了一些自定義的屬性,最後實現以上同樣效果的代碼非常簡潔:
    <com.me.obo.circleboardimage.circleview.roundimageview android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/head" attr:border_width="3dp" attr:corner_y="40dp" attr:corner_x="40dp" attr:border_color="#FFFFFF"></com.me.obo.circleboardimage.circleview.roundimageview>

 

下面就介紹如何實現這樣一個RoundImageView

遮罩

在Android中,遮罩功能非常強大,可以用於生成兩張圖片相互截取的結果。

\

具體參數和遮罩的效果可以見鏈接: Android 實現遮罩

在RoundImageView中,遮罩用於清除控件外圈的內容,從而獲取到圓角的效果。這裡的思路是先獲取到控件本身所繪制的圖片,之後獲取圓角矩形遮罩圖片,然後兩個圖片采用DST_IN遮罩模式來截取中間的遮罩效果,即:

\

代碼實現如下:

        // 獲取imageview原先的圖片
        super.onDraw(mDestCanvas);

        // 創建矩形,表示圓角矩形
        if (mRoundRectClip == null) {
            mRoundRectClip = new RectF(mBorderValue, mBorderValue, getWidth() - mBorderValue, getHeight() - mBorderValue);
        }
        // 繪制圓角矩形
        mSrcCanvas.drawRoundRect(mRoundRectClip,mCornerXValue,mCornerYValue,mNomalPaint);

        // 使用遮罩畫筆扣除原圖中的圓角矩形外面的部分
        mDestCanvas.drawBitmap(mSrcBitmap,0,0,mPaintClip);

 

在獲取到遮罩處理的圖片之後,為其添加board將會變得容易,也就是在外圈繪制出一個帶有寬度的圓即可。

\

代碼實現如下:

        // 創建board的矩形
        if (mRoundRectBorder == null) {
            mRoundRectBorder = new RectF(mBorderValue / 2, mBorderValue / 2, getWidth() - mBorderValue / 2, getHeight() - mBorderValue / 2);
        }
        // 繪制board
        mDestCanvas.drawRoundRect(mRoundRectBorder, mCornerXValue, mCornerYValue, mPaintBoard);

 

整個RoundImageView完整的代碼如下:

package com.me.obo.circleboardimage.circleview;

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

import com.me.obo.circleboardimage.R;


/**
 * Created by obo on 16/5/11.
 * Email:[email protected]
 * Git:https://github.com/OboBear
 * Blog:http://blog.csdn.net/leilba
 */
public class RoundImageView extends ImageView {

    private float mCornerXValue ;
    private float mCornerYValue ;
    private float mBorderValue ;
    private int mBorderColor ;

    public RoundImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 獲取自定義參數
        TypedArray typedArray = context.obtainStyledAttributes(attrs,
                R.styleable.RoundImageView);
        // board顏色
        mBorderColor = typedArray.getColor(R.styleable.RoundImageView_border_color,Color.argb(0,0,0,0));
        // 獲取X方向曲率
        mCornerXValue = typedArray.getDimension(R.styleable.RoundImageView_corner_x,0);
        // 獲取Y方向曲率
        mCornerYValue = typedArray.getDimension(R.styleable.RoundImageView_corner_y,0);
        // board寬
        mBorderValue = typedArray.getDimension(R.styleable.RoundImageView_border_width,0);
        // 用完需要recycle
        typedArray.recycle();

        initPaints();
    }

    private void initPaints() {
        // 創建普通畫筆
        if (mNomalPaint == null) {
            mNomalPaint = new Paint();
        }

        // 創建遮罩畫筆
        if (mPaintClip == null) {
            mPaintClip = new Paint();
            mPaintClip.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            mPaintClip.setAntiAlias(true);
        }

        // 創建board的畫筆
        if (mPaintBoard == null) {
            mPaintBoard = new Paint();
            mPaintBoard.setColor(mBorderColor);
            mPaintBoard.setStyle(Paint.Style.STROKE);
            mPaintBoard.setStrokeWidth(mBorderValue);
        }
    }

    Bitmap mDestBitmap;
    Bitmap mSrcBitmap;
    Canvas mDestCanvas;
    Canvas mSrcCanvas;
    Paint mPaintClip;
    Paint mNomalPaint;
    Paint mPaintBoard;
    RectF mRoundRectClip;
    RectF mRoundRectBorder;

    @Override
    protected void onDraw(Canvas canvas) {
        // 創建遮罩圖片和畫布
        if (mDestBitmap == null) {
            mDestBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
            mSrcBitmap = Bitmap.createBitmap(getWidth(),getHeight(), Bitmap.Config.ARGB_8888);
            mDestCanvas = new Canvas(mDestBitmap);
            mSrcCanvas = new Canvas(mSrcBitmap);
        }
        // 獲取imageview原先的圖片
        super.onDraw(mDestCanvas);

        // 創建矩形,表示圓角矩形
        if (mRoundRectClip == null) {
            mRoundRectClip = new RectF(mBorderValue, mBorderValue, getWidth() - mBorderValue, getHeight() - mBorderValue);
        }
        // 繪制圓角矩形
        mSrcCanvas.drawRoundRect(mRoundRectClip,mCornerXValue,mCornerYValue,mNomalPaint);

        // 使用遮罩畫筆扣除原圖中的圓角矩形外面的部分
        mDestCanvas.drawBitmap(mSrcBitmap,0,0,mPaintClip);

        // 創建board的矩形
        if (mRoundRectBorder == null) {
            mRoundRectBorder = new RectF(mBorderValue / 2, mBorderValue / 2, getWidth() - mBorderValue / 2, getHeight() - mBorderValue / 2);
        }
        // 繪制board
        mDestCanvas.drawRoundRect(mRoundRectBorder, mCornerXValue, mCornerYValue, mPaintBoard);

        // 繪制最終的圓角帶有board的圖
        canvas.drawBitmap(mDestBitmap,0,0,mNomalPaint);
    }

}


 

自定義Attribute

可能有人要問,圓角彎曲度和board的參數是如何傳遞到RoundImageView裡的。實際上,這裡采用了自定義Attribute的方式,該操作需要到res/values 目錄下創建 attr.xml 文件,在裡面寫上自定義的參數名稱以及類型:

<resources>
    <declare-styleable name="RoundImageView">
        <attr name="border_width" format="dimension">
        <attr name="border_color" format="color">
        <attr name="corner_x" format="dimension">
        <attr name="corner_y" format="dimension">
    </attr></attr></attr></attr></declare-styleable>
</resources>

有了這個,就可以在RoundImageView的構造方法裡面,獲取到自定義attri的值了
    public RoundImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 獲取自定義參數
        TypedArray typedArray = context.obtainStyledAttributes(attrs,
                R.styleable.RoundImageView);
        // board顏色
        mBorderColor = typedArray.getColor(R.styleable.RoundImageView_border_color,Color.argb(0,0,0,0));
        // 獲取X方向曲率
        mCornerXValue = typedArray.getDimension(R.styleable.RoundImageView_corner_x,0);
        // 獲取Y方向曲率
        mCornerYValue = typedArray.getDimension(R.styleable.RoundImageView_corner_y,0);
        // board寬
        mBorderValue = typedArray.getDimension(R.styleable.RoundImageView_border_width,0);
        // 用完需要recycle
        typedArray.recycle();

        initPaints();
    }

在layout裡使用的時候,需要在layout的xml開頭裡面申請自定義的參數即可
xmlns:attr="http://schemas.android.com/apk/res-auto"
最後,在layout裡面調用RoundImageView的代碼非常簡潔:

 

 

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:attr="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/darker_gray" android:orientation="vertical">

    <com.me.obo.circleboardimage.circleview.roundimageview android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/head" attr:border_width="3dp" attr:corner_y="40dp" attr:corner_x="40dp" attr:border_color="#FFFFFF">

    <com.me.obo.circleboardimage.circleview.roundimageview android:layout_width="180dp" android:layout_height="180dp" android:src="@drawable/head" attr:border_width="2dp" attr:corner_y="40dp" attr:corner_x="40dp" attr:border_color="#FF0000" android:scaletype="fitXY">
    
</com.me.obo.circleboardimage.circleview.roundimageview></com.me.obo.circleboardimage.circleview.roundimageview></linearlayout>
效果如下:

 

\
 

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