【Android】绘制圆角图片

1.概述     

       有时候为了个性、美观,我们需要将一张图片以圆角图片的形式显示,比如想微信等图片很多是圆角矩形,而最新的QQ5.0直接是圆形的,估计考虑到用户看多了再美也庸俗了吧,其实实现这个效果不难,而且一旦了解其中的原理可以按照自己的想法随心所欲的绘制出别出心裁的图片效果来。废话少说,先看一下效果图吧。

2.原理

      实现图片圆角等效果使两张图片做一定的集合运算,具体而言是使用了Paint的Xfermode。我们介绍下setXfermode方法,setXfermode方法用来设置两张图片相交时的模式。


         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 取两层图像的非交集部门

3.代码实例

1.自定义属性文件:attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="RoundImageView">
        <attr name="radius" format="float" />
    </declare-styleable>

</resources>
2.实现圆角图片的自定义控件RoundImageView
package com.example.listviewdemo.view;

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

import com.example.listviewdemo.R;

/**
 * Description: 自定义的可显示圆角的ImageView
 * 
 * @author danDingCongRong
 * @Version 1.0.0
 * @Created at 2014-8-11 10:56:38
 * @Modified by [作者] on [修改日期]
 */
public class RoundImageView extends ImageView {

	private int paddingTop = 0;
	private int paddingBottom = 0;
	private int paddingLeft = 0;
	private int paddingRight = 0;

	private float radius = 0.0f;
	private float defaultRadius = 0.0f;

	public RoundImageView(Context context) {
		super(context);

		init(context, null);
	}

	public RoundImageView(Context context, AttributeSet attrs) {
		super(context, attrs);

		init(context, attrs);
	}

	public RoundImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		init(context, attrs);
	}

	private void init(Context context, AttributeSet attrs) {
		TypedArray array = context.obtainStyledAttributes(attrs,
				R.styleable.RoundImageView);

		radius = array.getFloat(R.styleable.RoundImageView_radius,
				defaultRadius);

		// 现在有个问题是:为什么获取的值是实际设置值的1.5倍呢?
		paddingTop = getPaddingTop();
		paddingBottom = getPaddingBottom();
		paddingLeft = getPaddingLeft();
		paddingRight = getPaddingRight();

		array.recycle();
	}

	private int measureWidth(int widthMeasureSpec) {
		int width = 0;

		int specMode = MeasureSpec.getMode(widthMeasureSpec);
		int spectSize = MeasureSpec.getSize(widthMeasureSpec);

		if (MeasureSpec.EXACTLY == specMode) {// match_parent
			width = spectSize;
		} else {
			width = spectSize - paddingLeft - paddingRight;
			if (MeasureSpec.AT_MOST == specMode) {// wrap_content
				width = Math.min(width, spectSize);
			}

		}

		return width;
	}

	private int measureHeight(int heightMeasureSpec) {
		int height = 0;

		int specMode = MeasureSpec.getMode(heightMeasureSpec);
		int specSize = MeasureSpec.getSize(heightMeasureSpec);

		if (MeasureSpec.EXACTLY == specMode) {
			height = specSize;
		} else {
			height = specSize - paddingBottom - paddingTop;
			if (MeasureSpec.AT_MOST == specMode) {
				height = Math.min(height, specSize);
			}
		}

		return height;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		widthMeasureSpec = measureWidth(widthMeasureSpec);
		heightMeasureSpec = measureHeight(heightMeasureSpec);
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// 如果调用父类的Draw()将会绘制两张图片
		// super.onDraw(canvas);

		// 分别获取当前View的宽度和高度
		int width = getWidth();
		int height = getHeight();

		// 获取原始图片资源
		Drawable drawable = getDrawable();
		Bitmap source = ((BitmapDrawable) drawable).getBitmap();

		// 将原始图片变换为圆角图片
		Bitmap distance = getRoundConerImage(source);

		// 为了让图片资源位于Center,调整图片绘制的位置
		int top = (width - distance.getWidth()) / 2;
		int left = (height - distance.getHeight()) / 2;

		canvas.drawBitmap(distance, top, left, null);
	}

	protected Bitmap getRoundConerImage(Bitmap source) {
		int width = source.getWidth();
		int height = source.getHeight();

		// 根据指定宽度、高度和图片格式创建Bitmap
		Bitmap outputRoundBitmap = Bitmap.createBitmap(width, height,
				Config.ARGB_8888);

		final Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);

		// 使用一个Bitmap初始化一个画布,其密度等特征与Bitmap一致
		Canvas canvas = new Canvas(outputRoundBitmap);
		canvas.drawARGB(0, 0, 0, 0);

		// 初始化要绘制的没有圆角的矩形
		Rect rect = new Rect(0, 0, width, height);
		RectF rectF = new RectF(rect);
		// 绘制一个指定圆角半径的圆角矩形
		canvas.drawRoundRect(rectF, radius, radius, paint);

		// 设置图片绘制时采用的模式
		PorterDuffXfermode porterDuffXfermode = new PorterDuffXfermode(
				Mode.SRC_IN);
		paint.setXfermode(porterDuffXfermode);
		canvas.drawBitmap(source, 0, 0, paint);

		return outputRoundBitmap;
	}

}
3.测试代码的布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.example.listviewdemo"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:background="#DEE0E1"
    android:orientation="vertical"
    android:padding="10dp" >


    <com.example.listviewdemo.view.RoundImageView
        android:id="@+id/roundImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#8d0000"
        android:clickable="true"
        android:src="@drawable/ic_launcher" />

    <com.example.listviewdemo.view.RoundImageView
        android:id="@+id/roundImageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:background="#8d0000"
        android:clickable="true"
        android:padding="2dp"
        android:src="@drawable/ic_launcher"
        app:radius="10" />

    <com.example.listviewdemo.view.RoundImageView
        android:id="@+id/roundImageView2"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="20dp"
        android:background="#008d00"
        android:clickable="true"
        android:padding="5dp"
        android:scaleType="fitXY"
        android:src="@drawable/ic_launcher"
        app:radius="30" />

    <com.example.listviewdemo.view.RoundImageView
        android:id="@+id/roundImageView3"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_marginTop="20dp"
        android:background="#00008d"
        android:clickable="true"
        android:padding="10dp"
        android:scaleType="fitXY"
        android:src="@drawable/ic_launcher"
        app:radius="45" />

</LinearLayout>

4.测试代码

package com.example.listviewdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;

import com.example.listviewdemo.view.RoundImageView;

/**
 * Description: 测试圆角图片效果
 * 
 * @author danDingCongRong
 * @Version 1.0.0
 * @Created at 2014-8-11 14:37:14
 * @Modified by [作者] on [修改日期]
 */
public class TestRoundImageViewActivity extends Activity {

	private RoundImageView roundImageView;
	private RoundImageView roundImageView1;
	private RoundImageView roundImageView2;
	private RoundImageView roundImageView3;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.test_round_imageview_activity);

		initView();
	}

	private void initView() {
		roundImageView = (RoundImageView) findViewById(R.id.roundImageView);
		roundImageView1 = (RoundImageView) findViewById(R.id.roundImageView1);
		roundImageView2 = (RoundImageView) findViewById(R.id.roundImageView2);
		roundImageView3 = (RoundImageView) findViewById(R.id.roundImageView3);

		roundImageView.setImageResource(R.drawable.test_round_image);
		roundImageView1.setImageResource(R.drawable.test_round_image);
		roundImageView2.setImageResource(R.drawable.test_round_image);
		roundImageView3.setImageResource(R.drawable.test_round_image);
	}

}

Demo下载







参考:

1.http://blog.csdn.net/xyz_lmn/article/details/22745997

2.http://blog.csdn.net/alan_biao/article/details/17379925

3.http://blog.csdn.net/lmj623565791/article/details/24555655



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值