您的位置:首页 > 移动开发 > Android开发

【Android】Android自定义带board的圆角控件

2016-05-12 00:51 453 查看

介绍

圆角控件常用于头像,按钮,图标等,用途十分广泛,而且常常配合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"/>


下面就介绍如何实现这样一个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:obo1993@gmail.com
* 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();
mNomalPaint.setAntiAlias(true);
}

// 创建遮罩画笔
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);
mPaintBoard.setAntiAlias(true);
}
}

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 文件,在里面写上自定义的参数名称以及类型:

<?xml version="1.0" encoding="utf-8"?>
<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"/>
</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的代码非常简洁:

<?xml version="1.0" encoding="utf-8"?>
<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"/>

</LinearLayout>
效果如下:



资源下载

RoundImageView
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android imageview 控件