利用Android中BitmapShader制作自带边框的圆形头像

效果如下:

BitmapShader 的简单介绍

关于 Shader是什么,Shader的种类有哪几种以及如何使用不属于本文范畴,对这方面不是很了解的同学,建议先去学习一下 Shader 的基本使用。

BitmapShader主要的作用就是 通过Paint对象,对 画布进行指定的Bitmap填充,实现一系列效果,可以有以下三种模式进行选择

1.CLAMP - 拉伸,这里拉伸的是图片的最后一个元素,不断地重复,这个效果,在图片比较小,而所要画的面积比较大的时候会比较明显。

2.REPEAT - 重复,横向纵向不断地重复,不同于上一模式,这种模式在图片比较小不能满足要求是,会在横向纵向不断重复绘制图形。

3.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 转换成 Bitmap
 BitmapDrawable 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()函数中,进行绘制了,如下所示

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawCircle(mCircleX, mCircleY, mRadius, mPaint);
  canvas.drawCircle(mCircleX, mCircleY, mRadius, mBorderPaint);
 }

这样,整个效果就算实现完毕了。下面来看看如何使用

 <com.example.hwaphon.patheffecttest.MyView
   android: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 转换成 Bitmap
  BitmapDrawable bitmapDrawable = (BitmapDrawable) mDrawable;
  mBitmap = bitmapDrawable.getBitmap();

  mBorderWidth = type.getDimensionPixelSize(R.styleable.MyCustomView_mborder_width, 2);
 }

 @Override
 protected 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);
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawCircle(mCircleX, mCircleY, mRadius, mPaint);
  canvas.drawCircle(mCircleX, mCircleY, mRadius, mBorderPaint);
 }
}

总结

以上就是Android利用BitmapShader制作自带边框圆形头像的全部内容,希望这篇文章对大家开发Android的时候能有所帮助,如果有疑问大家可以留言交流。

(0)

相关推荐

  • Android一行代码实现圆形头像

    效果图 在开发APP中,经常要实现圆形头像,那么该如何实现呢? 要裁剪吗,要重写draw函数吗?不用,只用一行代码就可以实现 Glide实现圆形图像 Glide.with(mContext) .load(R.drawable.iv_image_header) .error(R.drawable.ic_error_default) .transform(new GlideCircleTransform(mContext)) .into(mImage); 其中load后为载入的图像,error后为出

  • Android使用CircleImageView实现圆形头像的方法

    有时我们在应用中会用到圆形头像,下面是利用CircleImageView实现圆形头像的演示,下面效果和代码,效果如图 实现起来也比较简单,先在项目中建一个circleimageview包用来存放CircleImageView类,待会直接把CircleImageView类复制到包里就可以使用了 然后,再建一个attrs.xml,其代码相当简单,定义了圆形边框宽度和颜色 <?xml version="1.0" encoding="utf-8"?> <r

  • Android中使用CircleImageView和Cardview制作圆形头像的方法

    圆形头像在我们的日常使用的app中很常见,因为圆形的头像比较美观. 使用圆形图片的方法可能有我们直接将图片裁剪成圆形再在app中使用,还有就是使用自定义View对我们设置的任何图片自动裁剪成圆形. 效果图: 这里使用github上CircleImageView github:https://github.com/hdodenhof/CircleImageView CardView顾名思义卡片式的View,CardView继承的是FrameLayout,所以摆放内部控件的时候需要注意一下 可以设置

  • Android自定义控件仿QQ编辑和选取圆形头像

    android大家都有很多需要用户上传头像的需求,有的是选方形,有的是圆角矩形,有的是圆形. 首先我们要做一个处理图片的自定义控件,把传入的图片,经过用户选择区域,处理成一定的形状. 有的app是通过在图片上画一个矩形区域表示选中的内容,有的则是通过双指放大缩小,拖动图片来选取图片.圆形头像,还是改变图片比较好 圆形区域可调节大小. 这个自定义View的图像部分分为三个,背景图片,半透明蒙层,和亮色区域--还是直接贴代码得了 package com.example.jjj.widget; imp

  • Android仿QQ圆形头像个性名片

    先看看效果图: 中间的圆形头像和光环波形讲解请看:http://www.jb51.net/article/96508.htm 周围的气泡布局,因为布局RatioLayout是继承自ViewGroup,所以布局layout就可以根据自己的需求来布局其子view,view.layout(int l,int t,int r,int b);用于布局子view在父ViewGroup中的位置(相对于父容器),所以在RatioLayout中计算所有子view的left,top,right,bottom.那么头

  • Android实现本地上传图片并设置为圆形头像

    先从本地把图片上传到服务器,然后根据URL把头像处理成圆形头像. 因为上传图片用到bmob的平台,所以要到bmob(http://www.bmob.cn)申请密钥. 效果图: 核心代码: 复制代码 代码如下: public class MainActivity extends Activity {         private ImageView iv;         private String appKey="";                //填写你的Applicatio

  • Android Studio实现带边框的圆形头像

    本文实例为大家分享了Android Studio实现带边框的圆形头像的具体代码,供大家参考,具体内容如下 效果显示: (没有边框的) (有边框的) 1.创建自定义ImagView控件 (1).没有边框的 package chenglong.activitytest.pengintohospital.utils; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitma

  • Android 自定义圆形头像CircleImageView支持加载网络图片的实现代码

    在Android开发中我们常常用到圆形的头像,如果每次加载之后再进行圆形裁剪特别麻烦.所以在这里写一个自定义圆形ImageView,直接去加载网络图片,这样的话就特别的方便. 先上效果图 主要的方法 1.让自定义 CircleImageView 继承ImageView /** * 自定义圆形头像 * Created by Dylan on 2015/11/26 0026. */ public class CircleImageView extends ImageView { } 2.在构造方法中

  • Android利用CircleImageView实现圆形头像的方法

    CircleImageView实现圆形头像代码分享,供大家参考,具体内容如下 一.创建属性文件(attrs.xml) 具体操作: 1.在项目的values文件底下创建一新的属性文件,文件名为attrs:New->XML->Values XML File:  2.补充attrs.xml代码: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleabl

  • Android应用中绘制圆形头像的方法解析

    要画这种圆形带阴影的头像,个人分解成三个图层 1,先画头像边缘的渐变 RadialGradient gradient = new RadialGradient(j/2,k/2,j/2,new int[]{0xff5d5d5d,0xff5d5d5d,0x00ffffff},new float[]{0.f,0.8f,1.0f}, Shader.TileMode.CLAMP); paint.setShader(gradient); canvas.drawCircle(j/2,k/2,j/2,paint

随机推荐