(用别人的代码进行分析) 不知道在开发中有没有经常使用到这种效果,所谓的遮罩层就是给一张图片不是我们想要的形状,这个时候我们就可以使用遮罩效果把这个图片变成我们想要的形状,一般使用最多就是圆形的效果,如下图:

上面这个图片是圆形的,而我们这个原图是正方形的,所以我们可能就需要这么一个遮罩的效果使它变为圆形,这种一般就是我们图片从网络上获取的,形状不是由我们自己定的,所以才会加上这么一个效果,看下面的原图:

这个是一个正方形的,那么要弄这么一个圆形,我们还需要一个圆形全黑的图片,如下

就是这个图片,其实简单的来说就是两个图片相结合,只显示被黑色图片覆盖的区域,外面的区域就不显示,这样就成一个圆形的图片了(上面的图片都是采用从别的应用程序来的),其实这个主要的技术还是涉及到了PorterDuffXfermode类的使用方法,

  1. PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);

上面就是PorterDuffXfermode类的创建,那么里面的参数PorterDuff.Mode.SRC_IN其实有很多中情况,好像有达到16中情况,下面介绍一下常用的:

PorterDuff.Mode.SRC_IN:取两层绘制交集。显示上层。就是如果上面两张图片相叠,那么取这两张图片的交集而且显示的是上层那种图片

PorterDuff.Mode.DST_IN:  取两层绘制交集。显示下层。

其它可以到网上可以查询得到,这两个用得也比较多。下面还有一张图片是外围那层图片的效果

好,我们现在来看看这个代码是如何来写的

  1. package com.example.myimageview;
  2.  
  3. import android.content.Context;
  4. import android.graphics.Bitmap;
  5. import android.graphics.BitmapFactory;
  6. import android.graphics.Canvas;
  7. import android.graphics.Paint;
  8. import android.graphics.PorterDuff;
  9. import android.graphics.PorterDuffXfermode;
  10. import android.util.AttributeSet;
  11. import android.view.View;
  12.  
  13. public class MyImageView extends View {
  14.  
  15. private Context context;
  16.  
  17. private Bitmap bitmapBorder;
  18. private Bitmap bitmapMask;
  19. private Paint paint;
  20. private PorterDuffXfermode xfermode;
  21.  
  22. private Bitmap bitmap;
  23.  
  24. private int _width;
  25. private int _height;
  26.  
  27. public MyImageView(Context context){
  28. this(context, null);
  29. }
  30.  
  31. public MyImageView(Context context, AttributeSet attrs) {
  32. super(context, attrs);
  33. this.context = context;
  34.  
  35. bitmapBorder = decodeBitmap(R.drawable.border);
  36. bitmapMask = decodeBitmap(R.drawable.mask);
  37.  
  38. _width = bitmapBorder.getWidth();
  39. _height = bitmapBorder.getHeight();
  40.  
  41. paint = new Paint();
  42. xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
  43. }
  44.  
  45. public MyImageView(Context context, AttributeSet attrs, int defStyle) {
  46. this(context, attrs);
  47. }
  48.  
  49. @Override
  50. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  51. setMeasuredDimension(_width, _height);
  52. }
  53.  
  54. private Bitmap decodeBitmap(int resId) {
  55. return BitmapFactory.decodeResource(context.getResources(), resId);
  56. }
  57.  
  58. public void setResourseId(int resourseId) {
  59. bitmap = decodeBitmap(resourseId);
  60. invalidate();
  61. }
  62.  
  63. public void setResourseBitmap(Bitmap bitmap){
  64. this.bitmap = bitmap;
  65. invalidate();
  66. }
  67.  
  68. @Override
  69. protected void onDraw(Canvas canvas) {
  70. if(bitmap == null){
  71. return;
  72. }
  73. canvas.drawBitmap(bitmapBorder, 0, 0, paint);
  74. int saveFlags = Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG;
  75. canvas.saveLayer(0, 0, _width, _height, null, saveFlags);
  76. canvas.drawBitmap(bitmapMask, 0, 0, paint);
  77. paint.setXfermode(xfermode);
  78. int left = _width/2 - bitmap.getWidth() /2;
  79. int top = _height/2 - bitmap.getHeight()/2;
  80. canvas.drawBitmap(bitmap, left, top, paint);
  81. paint.setXfermode(null);
  82. canvas.restore();
  83. }
  84. }

下面我们来分析一下代码的结构:

MyImageView是继承view的一个子类,在构造函数中我们看到设置两张图片bitmapBorder就是我上面贴出来的最下面外围的图片,bitmapMask就是那个全黑圆形的图片,_width和_height是bitmapBorder(外围那张图片的宽度和高度),因为那张图片是最大的我们需要定义这个view的大小所以需这个宽和高,下面

  1. @Override
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  3. setMeasuredDimension(_width, _height);
  4. }

就是使用宽和高来处理的,同时我们还看到了画笔Paint和PorterDuffXfermode创建,要说明一下这个PorterDuffXfermode对象是通过画笔Paint来设置的,下面有说明的

  1. public void setResourseId(int resourseId) {
  2. bitmap = decodeBitmap(resourseId);
  3. invalidate();
  4. }

这个代码就是需要我们手动传入想要变为圆形的图片,这个是在Avtivity中设置就行,最主要的代码来看onDraw()方法里面的。

  1. @Override
  2. protected void onDraw(Canvas canvas) {
  3. if(bitmap == null){
  4. return;
  5. }
  6. canvas.drawBitmap(bitmapBorder, 0, 0, paint);
  7. int saveFlags = Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG;
  8. canvas.saveLayer(0, 0, _width, _height, null, saveFlags);
  9. canvas.drawBitmap(bitmapMask, 0, 0, paint);
  10. paint.setXfermode(xfermode);
  11. int left = _width/2 - bitmap.getWidth() /2;
  12. int top = _height/2 - bitmap.getHeight()/2;
  13. canvas.drawBitmap(bitmap, left, top, paint);
  14. paint.setXfermode(null);
  15. canvas.restore();
  16. }

我们来看有三个地方使用了canvas.drawBitmap这个方法,简单理解就是谁先那么该图片就显示在最下面,最后使用的drawBitmap()方法就显示在最上面

canvas.saveLayer()方法和canvas.restore()是成对出现的,

Canvas 在一般的情况下可以看作是一张画布,所有的绘图操作如drawBitmap, drawCircle都发生在这张画布上,这张画板还定义了一些属性比如Matrix,颜色等等。但是如果需要实现一些相对复杂的绘图操作,比如多层动 画,地图(地图可以有多个地图层叠加而成,比如:政区层,道路层,兴趣点层)。Canvas提供了图层(Layer)支持,缺省情况可以看作是只有一个图 层Layer。如果需要按层次来绘图,Android的Canvas可以使用SaveLayerXXX, Restore 来创建一些中间层,对于这些Layer是按照“栈结构“来管理的:

创建一个新的Layer到“栈”中,可以使 用saveLayer, savaLayerAlpha, 从“栈”中推出一个Layer,可以使用restore,restoreToCount。但Layer入栈时,后续的DrawXXX操作都发生在这个 Layer上,而Layer退栈时,就会把本层绘制的图像“绘制”到上层或是Canvas上,在复制Layer到Canvas上时,可以指定Layer的 透明度(Layer),这是在创建Layer时指定的:public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags);

具体点可以到http://blog.csdn.net/linghu_java/article/details/8939952这个网站了解一下。

paint.setXfermode(xfermode);这个就是设置了画笔的效果了,left和top不用说了就是该图片要显示在中心的位置。canvas.drawBitmap(bitmap, left, top, paint);这个是最后那个canvas.drawBitmap方法,而且使用的PorterDuff.Mode.SRC_IN参数,表示的是取两层绘制交集。显示上层,那就是显示最后一张图片。

其实从上面来看效果是不错的,但是在真正的应用中我们不难会发现有些图片可能很大,这个时候就需要我们对图片进行等比的放大效果

http://bbs.csdn.net/topics/310218516这个网址就看到有介绍等比缩放图片的例子,我们来看下面的图片效果

上面两张图对比,第一张就是原来的效果,第二张就是对图片进行等比的缩放效果,看看第二张图片代码的:

  1. package com.example.myimageview;
  2.  
  3. import android.content.Context;
  4. import android.graphics.Bitmap;
  5. import android.graphics.BitmapFactory;
  6. import android.graphics.Canvas;
  7. import android.graphics.Paint;
  8. import android.graphics.PorterDuffXfermode;
  9. import android.graphics.RectF;
  10. import android.graphics.PorterDuff.Mode;
  11. import android.util.AttributeSet;
  12. import android.view.View;
  13.  
  14. public class itchqImageView extends View{
  15.  
  16. private Bitmap bg;
  17. private Bitmap photo;
  18.  
  19. private int bg_width;
  20. private int bg_height;
  21. public itchqImageView(Context context, AttributeSet attrs) {
  22. super(context, attrs);
  23. // TODO Auto-generated constructor stub
  24. init();
  25. }
  26.  
  27. private void init(){
  28. bg=BitmapFactory.decodeResource(getResources(),R.drawable.mask);
  29. bg_width=bg.getWidth();
  30. bg_height=bg.getHeight();
  31. }
  32.  
  33. public void setImageView(int imgId){
  34. photo=BitmapFactory.decodeResource(getResources(), imgId);
  35. scaleImage();
  36. }
  37. @Override
  38. protected void onDraw(Canvas canvas) {
  39. // TODO Auto-generated method stub
  40. super.onDraw(canvas);
  41. Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
  42.  
  43. paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
  44.  
  45. RectF rectf=new RectF(0,0,bg_width,bg_height);
  46.  
  47. canvas.saveLayer(rectf, null, Canvas.ALL_SAVE_FLAG);
  48. canvas.drawBitmap(photo, 0,0, null);
  49. canvas.drawBitmap(bg, 0, 0,paint);
  50. canvas.restore();
  51. }
  52.  
  53. private void scaleImage(){
  54.  
  55. if(photo!=null){
  56.  
  57. int widht=photo.getWidth();
  58. int height=photo.getHeight();
  59.  
  60. int new_width=0;
  61. int new_height=0;
  62.  
  63. if(widht!=height){
  64. if(widht>height){
  65. new_height=bg_height;
  66. new_width=widht*new_height/height;
  67. }else{
  68. new_width=bg_width;
  69. new_height=height*new_width/widht;
  70. }
  71. }else{
  72. new_width=bg_width;
  73. new_height=bg_height;
  74. }
  75. photo = Bitmap.createScaledBitmap(photo, new_width, new_height, true);
  76. }
  77. }
  78.  
  79. }
  1. scaleImage()这个方法里面就是对图片进行等比的缩放效果,缩放的大小就和我们全黑色的图片大小一样(这里我们原来外面圆形效果去掉了,就是上面第三张全白色的图片)
    如果图片不是正方形的我们就需要进行判断对比,最后得出的宽和高就是我们要等比缩放的大小。

Android 遮罩层效果--制作圆形头像的更多相关文章

  1. Android 遮罩层效果

    (用别人的代码进行分析) 不知道在开发中有没有经常使用到这种效果,所谓的遮罩层就是给一张图片不是我们想要的形状,这个时候我们就可以使用遮罩效果把这个图片变成我们想要的形状,一般使用最多就是圆形的效果, ...

  2. Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...

  3. 纯CSS3写的10个不同的酷炫图片遮罩层效果【转】

    这个是纯CSS3实现的的10个不同的酷炫图片遮罩层效果,可以欣赏一下 在线预览 下载地址 实例代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...

  4. 纯CSS3写的10个不同的酷炫图片遮罩层效果

    这个是纯CSS3实现的的10个不同的酷炫图片遮罩层效果,可以欣赏一下 在线预览 下载地址 实例代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...

  5. Android特效专辑(五)——自定义圆形头像和仿MIUI卸载动画—粒子爆炸

    Android特效专辑(五)--自定义圆形头像和仿MIUI卸载动画-粒子爆炸 好的,各位亲爱的朋友,今天讲的特效还是比较炫的,首先,我们会讲一个自定义圆形的imageView,接着,我们会来实现粒子爆 ...

  6. 利用div实现遮罩层效果

    利用div实现遮罩层效果就是利用一个全屏.半透明的div遮住页面上其它元素,典型的例子就是百度的登录界面.下面贴出示例代码: <!DOCTYPE html> <html> &l ...

  7. html+css源码之实现登录弹出框遮罩层效果

    在web开发中,很多网站都做了一些特别炫丽的效果,比如用户登录弹框遮罩层效果,本文章向大家介绍css如何实现登录弹出框遮罩层效果,需要的朋友可以参考一下本文章的源代码. html+css实现登录弹出框 ...

  8. jquery图片放大镜和遮罩层效果

    图片放大镜效果将借助于jqzoom插件,遮罩层借助于thickbox插件. 1.引入样式表 /*整体样式*/ <link rel="stylesheet" href=&quo ...

  9. WordPress制作圆形头像友情链接页面的方法

    网上看见过很多种友情链接页面,我比较喜欢的是圆形头像的这种,先看看效果吧:传送门 就是这种上面是圆形的友链用户头像,下面是友链用户网站名,然后鼠标移上去头像会旋转,怎么实现这种效果呢?我在网上找了很多 ...

随机推荐

  1. WPF启动屏幕SplashScreen

    SplashScreen类为WPF应用程序提供启动屏幕. 方法一:设置图片属性 1. 添加启动图片到项目中 2. 设置图片属性的Build Action为SplashScreen 方法二:编写代码 1 ...

  2. 在线O(1)求逆元

    怎么还有厉害的在线O(1)求逆元,不过常数确实有点儿太大了 本文大部分搬运于这里 相信大家都做过 POJ2478 这道题吧,这道题的 Farey 序列 \(F_n\) 包含了分子分母不大于 \(n\) ...

  3. LGP6240题解

    题解 我们可以发现,背包有结合律. 也就是先加入元素 \(a\) 再加入元素 \(b\) 和 \(c\),与先加入元素 \(a\) 后再与只有元素 \(b\) 和元素 \(c\) 的背包合并,得到的背 ...

  4. 安装Win7与Ubuntu16.04双系统操作教程

    安装主要分为以下几步: 一. 下载Ubuntu 16.04镜像软件: 二. 制作U盘启动盘使用ultraISO: 三. 安装Ubuntu系统: 四. 用EasyBCD 创建启动系统启动引导: (根据个 ...

  5. 嵌入式无操作系统下管理内存和队列(类UCOS II思想)

    例子:存储日志,最多存128条,每条最大1MB. 内存方面 因为嵌入式不适合用动态内存,会产生碎片.这里我们用 u8 data[LOG_SIZE];开辟固定128MB的内存区,再对其分为128个1MB ...

  6. 关于python很好的网站和书籍

    https://python-patterns.guide/ https://docs.python-guide.org/ https://www.amazon.com/_/dp/1491946008 ...

  7. CodeUp Problem D: More is better

    根据题目意思,输入的每一对A.B都是直接朋友,并且最后只会得到一个集合,该集合就是Mr Wang选择的男孩. 因此很容易写出代码,甚至不需要自己构建一个并查集,只需要使用C++的set模板,每次读入一 ...

  8. 问鼎杯预赛web writeup

    1. php的一个精度问题,具体什么精度自己查. 2017.000000000001=2017 2016.999999999999=2017 直接拿谷歌浏览器访问那个链接就可以拿到flag 2. 访问 ...

  9. SpringCloud项目中接入Nacos作为注册中心

    具体demo         https://blog.csdn.net/qq_33619378/article/details/95212754 <?xml version="1.0 ...

  10. java-开发规约

    public class TenTen { /** * 代码中的命名不能用下划线或美元符号开始和结束:例如 _name name_ $name name$ */ /** * 类名必须使用UpperCa ...