android自定义view-打造圆形ImageView(四)终结篇

前言:

说实话,这段时间忙着修改毕业论文,好长时间没有碰代码了,真是罪过呀。今天我们就来奉上我们打造圆形ImageView的终结篇,以后如果还有新的创意再说啦。本文是在前面三篇的基础上得来的,详细请戳android自定义view-打造圆形ImageView(一)、android自定义view-打造圆形ImageView(二)、android自定义view-打造圆形ImageView(三)。

效果图:

android自定义view-打造圆形ImageView(四)终结篇_第1张图片

正文:

其实看了上面的效果图,大家应该都一目了然了,就是很多应用经常见到的带有白色边缘的渐变头像ImageView。我们今天采用的就是第二篇采用的Xfermode去处理图片,其实代码都是差不多的,只要在那基础上做简单修改即可。不过,只是画了圆形的,没有圆角的...见谅哈闭嘴

在我们开始之前的知识准备有哪些呢?之前给大家讲过线性渐变,然而今天我们需要用到是球型渐变可怜RadialGradient。

android.graphics.RadialGradient.RadialGradient(float x, float y, float radius, int[] colors, float[] positions, TileMode tile)

  1. 第一个,第二个参数表示渐变圆中心坐标 
  2. 第三个参数表示半径 
  3. 第四个,第五个,第六个与线性渲染相同 
绘制这样的ImageView分为三步:

  1. 画圆形边缘渐变色-即用球型渐变
  2. 绘制圆形图片
  3. 绘制白色边缘
好了, step1:绘制球形渐变
	// 创建画笔
		Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		paint.setDither(true);
		RadialGradient gradient = new RadialGradient(getWidth() / 2, getHeight() / 2, getWidth() / 2, new int[] { 0xff5d5d5d, 0xff5d5d5d, 0x00ffffff }, new float[] { 0.f, 0.9f, 1.0f }, Shader.TileMode.CLAMP);
		paint.setShader(gradient);
在绘制Mask蒙板图层的时候,即形状绘制的时候进行渐变处理,其实也很简单,没什么好解释的。
step2:绘制圆形图片
代码其实和之前第二篇的是一样的。
@Override
	protected void onDraw(Canvas canvas) {
		// 从缓存中取出图片
		Bitmap bitmap = mWeakBitmap == null ? null : mWeakBitmap.get();
		// 如果没有缓存或者被回收了,则重新绘制
		if (bitmap == null || bitmap.isRecycled()) {
			// 获取背景drawable
			Drawable drawable = getDrawable();
			// 如果有背景图则绘制
			if (drawable != null) {
				// 拿到drawable的长度和宽度
				int dWidth = drawable.getIntrinsicWidth();
				int dHeight = drawable.getIntrinsicHeight();
				bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
				// 创建画布
				Canvas canvas1 = new Canvas(bitmap);
				// 设置图片缩放比率
				float scale = 1.0f;
				scale = Math.max(getWidth() * 1.0f / dWidth, getHeight() * 1.0f / dHeight);
				// 缩放图片
				drawable.setBounds(0, 0, (int) (scale * dWidth), (int) (scale * dHeight));
				// 绘制DST图片
				drawable.draw(canvas1);
				// 绘制SRC图片
				if (mMaskBitmap == null || mMaskBitmap.isRecycled()) {
					mMaskBitmap = drawType();
				}
				// 重置画笔
				mPaint.reset();
				// 不采用滤波
				mPaint.setFilterBitmap(false);
				mPaint.setXfermode(xfermode);
				canvas1.drawBitmap(mMaskBitmap, 0, 0, mPaint);
				Paint paint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
				paint1.setColor(0xffffffff);
				paint1.setStrokeWidth(mGradientBorder);
				paint1.setStyle(Paint.Style.STROKE);
				paint1.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
				canvas1.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2 - mGradientGap, paint1);
				// drawable.draw(canvas);
				// 绘制处理好的图形
				mPaint.setXfermode(null);
				canvas.drawBitmap(bitmap, 0, 0, mPaint);
				// 缓存图片
				mWeakBitmap = new WeakReference<Bitmap>(bitmap);
			}
		}
		if (bitmap != null) {
			mPaint.setXfermode(null);
			canvas.drawBitmap(bitmap, 0.0f, 0.0f, mPaint);
		}
	}
这里唯一的区别就是在canvas.drawBitmap(bitmap,0,0,mPaint)之前需要进行白色边缘处理,说白了,就是再加一个步骤啦。
Paint paint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
				paint1.setColor(0xffffffff);
				paint1.setStrokeWidth(mGradientBorder);
				paint1.setStyle(Paint.Style.STROKE);
				paint1.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
				canvas1.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2 - mGradientGap, paint1);
这段就是处理白色边缘的代码,其实也没啥好说的,至于Xfermode不懂,回头看我之前的三篇博客吧。
好了,贴一下所有代码。
package com.beyole.view;

import java.lang.ref.WeakReference;

import android.content.Context;
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.RadialGradient;
import android.graphics.Shader;
import android.graphics.Xfermode;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class GradientImageView extends ImageView {
	// 白色边缘大小
	private int mGradientBorder = 7;
	// 设置白色边缘与渐变间距
	private int mGradientGap = 5;
	// 画笔
	private Paint mPaint;
	// 使用缓存机制来保存处理好的bitmap,便于GC
	private WeakReference<Bitmap> mWeakBitmap;
	// 设置Xfermode的模式为DST_IN
	private Xfermode xfermode = new PorterDuffXfermode(Mode.DST_IN);
	// 蒙板图层
	private Bitmap mMaskBitmap;

	public GradientImageView(Context context) {
		this(context, null);
	}

	public GradientImageView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public GradientImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// 初始化画笔
		mPaint = new Paint();
		mPaint.setAntiAlias(true);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 强制宽高一致,以最小的值为准
		int mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
		setMeasuredDimension(mWidth, mWidth);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// 从缓存中取出图片
		Bitmap bitmap = mWeakBitmap == null ? null : mWeakBitmap.get();
		// 如果没有缓存或者被回收了,则重新绘制
		if (bitmap == null || bitmap.isRecycled()) {
			// 获取背景drawable
			Drawable drawable = getDrawable();
			// 如果有背景图则绘制
			if (drawable != null) {
				// 拿到drawable的长度和宽度
				int dWidth = drawable.getIntrinsicWidth();
				int dHeight = drawable.getIntrinsicHeight();
				bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
				// 创建画布
				Canvas canvas1 = new Canvas(bitmap);
				// 设置图片缩放比率
				float scale = 1.0f;
				scale = Math.max(getWidth() * 1.0f / dWidth, getHeight() * 1.0f / dHeight);
				// 缩放图片
				drawable.setBounds(0, 0, (int) (scale * dWidth), (int) (scale * dHeight));
				// 绘制DST图片
				drawable.draw(canvas1);
				// 绘制SRC图片
				if (mMaskBitmap == null || mMaskBitmap.isRecycled()) {
					mMaskBitmap = drawType();
				}
				// 重置画笔
				mPaint.reset();
				// 不采用滤波
				mPaint.setFilterBitmap(false);
				mPaint.setXfermode(xfermode);
				canvas1.drawBitmap(mMaskBitmap, 0, 0, mPaint);
				Paint paint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
				paint1.setColor(0xffffffff);
				paint1.setStrokeWidth(mGradientBorder);
				paint1.setStyle(Paint.Style.STROKE);
				paint1.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
				canvas1.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2 - mGradientGap, paint1);
				// drawable.draw(canvas);
				// 绘制处理好的图形
				mPaint.setXfermode(null);
				canvas.drawBitmap(bitmap, 0, 0, mPaint);
				// 缓存图片
				mWeakBitmap = new WeakReference<Bitmap>(bitmap);
			}
		}
		if (bitmap != null) {
			mPaint.setXfermode(null);
			canvas.drawBitmap(bitmap, 0.0f, 0.0f, mPaint);
		}
	}

	/**
	 * 绘制形状,作为src
	 * 
	 * @return
	 */
	private Bitmap drawType() {
		Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(bitmap);
		// 创建画笔
		Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		paint.setDither(true);
		RadialGradient gradient = new RadialGradient(getWidth() / 2, getHeight() / 2, getWidth() / 2, new int[] { 0xff5d5d5d, 0xff5d5d5d, 0x00ffffff }, new float[] { 0.f, 0.9f, 1.0f }, Shader.TileMode.CLAMP);
		paint.setShader(gradient);
		canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2, paint);
		return bitmap;
	}

	// 在重绘中进行mask和dst的内存回收
	@Override
	public void invalidate() {
		mWeakBitmap = null;
		if (mMaskBitmap != null) {
			mMaskBitmap.recycle();
			mMaskBitmap = null;
		}
		super.invalidate();
	}

	// 对外公布白色边缘宽度
	public void setGradientBorder(int gradientBorder) {
		this.mGradientBorder = gradientBorder;
	}

	// 对外公布白色边缘与渐变间距
	public void setGradientGap(int gradientGap) {
		this.mGradientGap = gradientGap;
	}
}
上面公布了两个对外方法,如果用的时候觉得丑,就重新设置一下数值就会看到意想不到的效果:
// 对外公布白色边缘宽度
	public void setGradientBorder(int gradientBorder) {
		this.mGradientBorder = gradientBorder;
	}

	// 对外公布白色边缘与渐变间距
	public void setGradientGap(int gradientGap) {
		this.mGradientGap = gradientGap;
	}
如何使用就很简单了:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.beyole.view.GradientImageView
        android:id="@+id/id_img"
        android:layout_width="100.0dip"
        android:layout_height="100.0dip"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/demo" />

</LinearLayout>

后语:
好了,今天的代码教程到此结束。赶着去改论文了,忙里偷着写这一篇博客,我真的不适合搞论文写作。。抓狂
csdn下载地址:http://download.csdn.net/detail/smarticeberg/9493659
github地址: https://github.com/xuejiawei/beyole_roundimageview  欢迎fork or star

题外话:

android交流群:279031247(广告勿入)

新浪微博:SmartIceberg







你可能感兴趣的:(android自定义view-打造圆形ImageView(四)终结篇)