Android使用BitmapShader图形渲染实现圆形、圆角和椭圆自定义图片View

来源:互联网 发布:老布的淘宝店 编辑:程序博客网 时间:2024/06/05 07:30

一、概述

Android实现圆角矩形,圆形或者椭圆等图形,一般主要是个自定义View加上使用Xfermode实现的。实现圆角图片的方法其实不少,常见的就是利用Xfermode,Shader。本文直接继承ImageView,使用BitmapShader方法来实现圆形、圆角和椭圆的绘制,等大家看我本文的方法后,其他的类似形状也就都能举一反三来来画出来了。

二、效果图:


三、BitmapShader简介

BitmapShader是Shader的子类,可以通过Paint.setShader(Shader shader)进行设置、

我们这里只关注BitmapShader,构造方法:

mBitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);

参数1:bitmap

参数2,参数3:TileMode;

TileMode的取值有三种:

CLAMP 拉伸

REPEAT 重复

MIRROR 镜像

如果大家给电脑屏幕设置屏保的时候,如果图片太小,可以选择重复、拉伸、镜像;

重复:就是横向、纵向不断重复这个bitmap

镜像:横向不断翻转重复,纵向不断翻转重复;

拉伸:这个和电脑屏保的模式应该有些不同,这个拉伸的是图片最后的那一个像素;横向的最后一个横行像素,不断的重复,纵项的那一列像素,不断的重复;

public BitmapShader(Bitmap bitmap,Shader.TileMode tileX,Shader.TileMode tileY)

调用这个方法来产生一个画有一个位图的渲染器(Shader)。

bitmap 在渲染器内使用的位图

tileX The tiling mode for x to draw the bitmap in. 在位图上X方向花砖模式

tileY The tiling mode for y to draw the bitmap in. 在位图上Y方向花砖模式

TileMode:(一共有三种)

CLAMP :如果渲染器超出原始边界范围,会复制范围内边缘染色。

REPEAT :横向和纵向的重复渲染器图片,平铺。

MIRROR :横向和纵向的重复渲染器图片,这个和REPEAT 重复方式不一样,他是以镜像方式平铺。

四、自定义圆形、圆角和椭圆的图片View的实现

import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapShader;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Shader;import android.graphics.Shader.TileMode;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.widget.ImageView;public class CustomImageView1 extends ImageView {public final static int TYPE_CIRCLE = 0;public final static int TYPE_ROUND = 1;public final static int TYPE_OVAL = 2;private int mType=0;private int mWidth;private int mRadius;private int mRoundRadius =50;private Paint mPaint;private RectF mRectF;private Matrix mMatrix;private Shader mBitmapShader;public CustomImageView1(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);mPaint = new Paint();mPaint.setAntiAlias(true);mMatrix = new Matrix();}public CustomImageView1(Context context, AttributeSet attrs, int defStyleAttr) {this(context, attrs, defStyleAttr, 0);}public CustomImageView1(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CustomImageView1(Context context) {this(context, null);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);if (mType == TYPE_CIRCLE) {mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());mRadius = mWidth / 2;setMeasuredDimension(mWidth, mWidth);}}@SuppressLint("DrawAllocation")@Overrideprotected void onDraw(Canvas canvas) {if (null == getDrawable()) {return;}setBitmapShader();mRectF = new RectF(0, 0, getWidth(), getHeight());//mRectF = new RectF((float)getLeft(),(float)getTop(),(float)getRight(),(float)getBottom());if (mType == TYPE_CIRCLE) {canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);} else if (mType == TYPE_ROUND) {mPaint.setColor(Color.RED);canvas.drawRoundRect(mRectF, mRoundRadius, mRoundRadius, mPaint);} else if (mType == TYPE_OVAL) {canvas.drawOval(mRectF, mPaint);}}private void setBitmapShader() {Drawable drawable = getDrawable();if (null == drawable) {return;}Bitmap bitmap = drawableToBitmap(drawable);// 将bitmap作为着色器来创建一个BitmapShadermBitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);float scale = 1.0f;if (mType == TYPE_CIRCLE) {// 拿到bitmap宽或高的小值int bSize = Math.min(bitmap.getWidth(), bitmap.getHeight());scale = mWidth * 1.0f / bSize;} else if (mType == TYPE_ROUND || mType == TYPE_OVAL) {// 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值;scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight() * 1.0f / bitmap.getHeight());}// shader的变换矩阵,我们这里主要用于放大或者缩小mMatrix.setScale(scale, scale);// 设置变换矩阵mBitmapShader.setLocalMatrix(mMatrix);mPaint.setShader(mBitmapShader);}private Bitmap drawableToBitmap(Drawable drawable) {return ((BitmapDrawable) drawable).getBitmap();}}


0 0