利用 BitmapShader 制作自带边框圆形头像
目前为止,已经掌握了两种制作圆形头像的方法,一种是利用 PorterDuffXfermode
,一种是 Shader
工具。至于选择哪一种方法因人而异,但幸运的是这两种方法的使用都并不难。好了,现在介绍一下如何利用 BitmapShader
制作圆形头像,为了演示,我做了一个 Demo ,可以自定义要显示的图片,边框颜色,边框宽度,效果如下图所示。
BitmapShader 的简单介绍
关于 Shader
是什么,Shader
的种类有哪几种以及如何使用不属于本文范畴,对这方面不是很了解的同学,建议先去学习一下 Shader
的基本使用。
BitmapShader
主要的作用就是 通过 Paint
对象,对 画布进行指定的 Bitmap 填充
,实现一系列效果,可以有以下三种模式进行选择
CLAMP - 拉伸,这里拉伸的是图片的最后一个元素,不断地重复,这个效果,在图片比较小,而所要画的面积比较大的时候会比较明显。
REPEAT - 重复,横向纵向不断地重复,不同于上一模式,这种模式在图片比较小不能满足要求是,会在横向纵向不断重复绘制图形。
MIRROR - 翻转,这种模式和 REPEAT 是类似的,只不过这里的重复是翻转着重复,和折纸的效果差不多。
而我们将要使用的是 CLAMP 模式,因为只要我们对图形的大小进行控制,就可以避免图像进行拉伸。
具体实现
为了自定义 图像,边框宽度和颜色,我们首先在 res/values 目录下,新建一个 attrs.xml文件,里面要书写的内容如下所示
<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="MyCustomView"><attr name="mborder_color" format="color"></attr><attr name="mborder_width" format="dimension"></attr><attr name="msrc" format="reference"></attr></declare-styleable>
</resources>
当然,在这里还可以添加一些其他的特性。既然定义了我们想要使用的特性,那么我们就要在自定义 View
里面 解析这些属性并且加以利用,解析过程如下所示
TypedArray type = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);mBorderColor = type.getColor(R.styleable.MyCustomView_mborder_color,0);mDrawable = type.getDrawable(R.styleable.MyCustomView_msrc);//将获得的 Drawable 转换成 BitmapBitmapDrawable bitmapDrawable = (BitmapDrawable) mDrawable;mBitmap = bitmapDrawable.getBitmap();mBorderWidth = type.getDimensionPixelSize(R.styleable.MyCustomView_mborder_width, 2);
值得注意的是 mSrc 属性的解析,由于获得是 Drawable
对象,所以我们需要将其转换为 Bitmap
对象。
下面就利用我们获得的 Bitmap
对象进行圆形头像的绘制,对 BitmapShader
和 Paint
的初始化如下所示
mSrcBitmap = Bitmap.createScaledBitmap(mBitmap, mWidth, mHeight, false);mShader = new BitmapShader(mSrcBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);mPaint = new Paint();mPaint.setShader(mShader);mRadius = (mWidth - mBorderWidth * 2 - 4) / 2;mCircleX = (mWidth) / 2;mCircleY = (mHeight) / 2;
mSrcBitmap 是对获得的图像进行适当的缩小或者放大,以适应我们对图形的要求,而这里的 mWidth 和 mHeight 又是什么呢?实际上就是我们在 定义视图在 layout_width
和 layout_height
中传递进来的值,不过在这里我对他们进行了处理,也就是选取最小值操作,这样的话就可以避免由于宽大于高或者高大于宽而造成图像填充不满指定区域的现象。值得注意的是,自定义视图,需要对 wrap_content
进行特殊处理,否则系统对该属性的视图不予以显示。至于如何进行处理,可以看看本例的源码,很简单,相信很多人一看就知道或者说早就了然于胸。
还有一点需要强调的是这里的 mRadius ,也就是将要绘制的圆的半径,为什么要减去边框的宽度 乘 2 呢? 要知道,我们的圆是根据 视图指定的宽度或者高度来画的,如果我们所画 的圆恰好是指定视图的内切圆,那么边框放在哪里呢?它肯定要被画在视图的外面,那样我们就看不到完整的边框了。所以,这么减去的意义在于为边框腾出空间。
经过以上操作,我们就已经将圆形头像绘制出来了,下面来绘制边框,其实非常简单,我只不过是又定义了一个 Paint
对象,并且利用它画了一个圆而已,画笔的初始化操作如下所示
mBorderPaint = new Paint();mBorderPaint.setStyle(Paint.Style.STROKE);mBorderPaint.setStrokeWidth(mBorderWidth);mBorderPaint.setColor(mBorderColor);mBorderPaint.setStrokeCap(Paint.Cap.ROUND);
好了,下面就可以在 onDraw()
函数中,进行绘制了,如下所示
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawCircle(mCircleX, mCircleY, mRadius, mPaint);canvas.drawCircle(mCircleX, mCircleY, mRadius, mBorderPaint);}
这样,整个效果就算实现完毕了。下面来看看如何使用
<com.example.hwaphon.patheffecttest.MyViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="16dp"android:layout_marginRight="8dp"app:mborder_color="@android:color/holo_green_light"app:mborder_width="4dp"app:msrc="@drawable/myview_test"/>
注意,一定要在容器中加上这么一句
xmlns:app="http://schemas.android.com/apk/res-auto"
具体实现的核心代码
package com.example.hwaphon.patheffecttest;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;/*** Created by Hwaphon on 2016/5/12.*/
public class MyView extends View {private Bitmap mBitmap;private Drawable mDrawable;private Bitmap mSrcBitmap;private BitmapShader mShader;private Paint mPaint;private int mWidth, mHeight;private int mRadius;private int mCircleX, mCircleY;private int mBorderColor;private Paint mBorderPaint;private int mBorderWidth;public MyView(Context context) {this(context, null);}public MyView(Context context, AttributeSet attrs) {super(context, attrs);TypedArray type = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);mBorderColor = type.getColor(R.styleable.MyCustomView_mborder_color,0);mDrawable = type.getDrawable(R.styleable.MyCustomView_msrc);//将获得的 Drawable 转换成 BitmapBitmapDrawable bitmapDrawable = (BitmapDrawable) mDrawable;mBitmap = bitmapDrawable.getBitmap();mBorderWidth = type.getDimensionPixelSize(R.styleable.MyCustomView_mborder_width, 2);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth = measureWidth(widthMeasureSpec);mHeight = measureHeight(heightMeasureSpec);int temp = mWidth > mHeight ? mHeight : mWidth;mWidth = mHeight = temp;initView();setMeasuredDimension(mWidth, mHeight);}private int measureHeight(int heightMeasureSpec) {int size = MeasureSpec.getSize(heightMeasureSpec);int sizeMode = MeasureSpec.getMode(heightMeasureSpec);int result = 0;if (sizeMode == MeasureSpec.EXACTLY) {result = size;} else {result = 200;if (sizeMode == MeasureSpec.AT_MOST) {result = Math.min(result, size);}}return result;}private int measureWidth(int widthMeasureSpec) {int size = MeasureSpec.getSize(widthMeasureSpec);int sizeMode = MeasureSpec.getMode(widthMeasureSpec);int result = 0;if (sizeMode == MeasureSpec.EXACTLY) {result = size;} else {result = 200;if (sizeMode == MeasureSpec.AT_MOST) {result = Math.min(result, size);}}return result;}private void initView() {mSrcBitmap = Bitmap.createScaledBitmap(mBitmap, mWidth, mHeight, false);mShader = new BitmapShader(mSrcBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);mPaint = new Paint();mPaint.setShader(mShader);mRadius = (mWidth - mBorderWidth * 2) / 2;mCircleX = (mWidth) / 2;mCircleY = (mHeight) / 2;mBorderPaint = new Paint();mBorderPaint.setStyle(Paint.Style.STROKE);mBorderPaint.setStrokeWidth(mBorderWidth);mBorderPaint.setColor(mBorderColor);mBorderPaint.setStrokeJoin(Paint.Join.ROUND);mBorderPaint.setStrokeCap(Paint.Cap.ROUND);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawCircle(mCircleX, mCircleY, mRadius, mPaint);canvas.drawCircle(mCircleX, mCircleY, mRadius, mBorderPaint);}
}
利用 BitmapShader 制作自带边框圆形头像相关推荐
- 前端素材解析—利用linear制作复杂的边框效果
在网上看到一种利用linear-gradient属性制作绚丽边框效果的方法.首先给出代码,大家可以在自己的电脑中查看效果: <!DOCTYPE html><html lang=&qu ...
- Android CircleImageView自定义圆形与边框(圆形头像)详解
背景: 当前我们在使用图片过程中,都知道正常的ImageView是一个矩形RectF,RectF只需要知道两个对角坐标就可以确定该图形的大小 RectF rect=new RectF(int left ...
- android圆形头像边框,Android Studio实现带边框的圆形头像
本文实例为大家分享了Android Studio实现带边框的圆形头像的具体代码,供大家参考,具体内容如下 效果显示: (没有边框的) (有边框的) 1.创建自定义ImagView控件 (1).没有边框 ...
- Android Studio 圆形头像带边框的
效果显示: (没有边框的) (有边框的) 1.创建自定义ImagView控件 (1).没有边框的 package chenglong.activitytest.pengintohospital.uti ...
- 圆形头像及带边框的圆形头像实现_若雪似风_新浪博客
先上效果图 一个带边框 一个不带.用的同一个自定义控件 就在布局文件加几个属性就好了. 首先是自定义类CircleImageView import android.content.Context ; ...
- Android实现带圆环的圆形头像(转载)
其实设置圆头像很交单,一行代码: Glide.with(mContext).load("url").centerCrop().into(binding.supermarketIvH ...
- Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...
- Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习...
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...
- Android 圆形头像/有外边框的圆形头像CircleImageView自定义控件使用详解
现在很主流使用圆形头像,还要带边框的一个圆圈圈,自己做的项目里就有这样的需求,大大小小好多地方. 本着能懒则懒的原则,把使用详解总结出来,(PS:不是控件详解). 基本上可以拿来就用,注释我也添加的比 ...
最新文章
- 一款非常好用的Linux下的C/C++ IDE
- OpenCV在图像上添加边框borders
- 3个常考的SQL数据分析题(含数据和代码)
- thinkphp5 异步调用方法_thinkphp5 swoole 执行异步任务
- laravel 检测sql_在Laravel PHP应用程序中轻松进行面部检测
- 为什么你的数据分析成果总是难以落地?
- OpenStack第十四个版本及14项重要事实
- 【Elasticsearch】 elasticsearch之Recovery
- android编译的tool版本有多少,android gradle tool版本从3.3升级到3.6.3问题记录
- .NET基础编程之特性 - Attribute
- 明源云客微信抢房技巧_抢房明源系统是什么意思_明源云客抢房软件
- oracle 19c ORA-00942: 表或视图不存在 ORA-02063: 紧接着 line
- 看了 web.dev 的 631 篇博客,我总结了这些内容
- 徐文长传奇李舟楫的博客新浪博客
- arcgis标注转为注记后,如何批量修改注记及牵引线颜色
- RepeatMasker的安装与使用(一)
- 玩转Jetson Nano(一)烧写系统
- 第1章 多媒体技术概要
- 利用小米手环记录并生成心率图
- poi导出Excel文件下载数据