Android 遮罩层效果
(用别人的代码进行分析) 不知道在开发中有没有经常使用到这种效果,所谓的遮罩层就是给一张图片不是我们想要的形状,这个时候我们就可以使用遮罩效果把这个图片变成我们想要的形状,一般使用最多就是圆形的效果,如下图:
上面这个图片是圆形的,而我们这个原图是正方形的,所以我们可能就需要这么一个遮罩的效果使它变为圆形,这种一般就是我们图片从网络上获取的,形状不是由我们自己定的,所以才会加上这么一个效果,看下面的原图:
这个是一个正方形的,那么要弄这么一个圆形,我们还需要一个圆形全黑的图片,如下
就是这个图片,其实简单的来说就是两个图片相结合,只显示被黑色图片覆盖的区域,外面的区域就不显示,这样就成一个圆形的图片了(上面的图片都是采用从别的应用程序来的),其实这个主要的技术还是涉及到了PorterDuffXfermode类的使用方法,
PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
上面就是PorterDuffXfermode类的创建,那么里面的参数PorterDuff.Mode.SRC_IN其实有很多中情况,好像有达到16中情况,下面介绍一下常用的:
PorterDuff.Mode.SRC_IN:取两层绘制交集。显示上层。就是如果上面两张图片相叠,那么取这两张图片的交集而且显示的是上层那种图片
PorterDuff.Mode.DST_IN: 取两层绘制交集。显示下层。
其它可以到网上可以查询得到,这两个用得也比较多。下面还有一张图片是外围那层图片的效果
好,我们现在来看看这个代码是如何来写的
package com.example.myimageview; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View; public class MyImageView extends View { private Context context; private Bitmap bitmapBorder;
private Bitmap bitmapMask;
private Paint paint;
private PorterDuffXfermode xfermode; private Bitmap bitmap; private int _width;
private int _height; public MyImageView(Context context){
this(context, null);
} public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context; bitmapBorder = decodeBitmap(R.drawable.border);
bitmapMask = decodeBitmap(R.drawable.mask); _width = bitmapBorder.getWidth();
_height = bitmapBorder.getHeight(); paint = new Paint();
xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
} public MyImageView(Context context, AttributeSet attrs, int defStyle) {
this(context, attrs);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(_width, _height);
} private Bitmap decodeBitmap(int resId) {
return BitmapFactory.decodeResource(context.getResources(), resId);
} public void setResourseId(int resourseId) {
bitmap = decodeBitmap(resourseId);
invalidate();
} public void setResourseBitmap(Bitmap bitmap){
this.bitmap = bitmap;
invalidate();
} @Override
protected void onDraw(Canvas canvas) {
if(bitmap == null){
return;
}
canvas.drawBitmap(bitmapBorder, 0, 0, paint);
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;
canvas.saveLayer(0, 0, _width, _height, null, saveFlags);
canvas.drawBitmap(bitmapMask, 0, 0, paint);
paint.setXfermode(xfermode);
int left = _width/2 - bitmap.getWidth() /2;
int top = _height/2 - bitmap.getHeight()/2;
canvas.drawBitmap(bitmap, left, top, paint);
paint.setXfermode(null);
canvas.restore();
}
}
下面我们来分析一下代码的结构:
MyImageView是继承view的一个子类,在构造函数中我们看到设置两张图片bitmapBorder就是我上面贴出来的最下面外围的图片,bitmapMask就是那个全黑圆形的图片,_width和_height是bitmapBorder(外围那张图片的宽度和高度),因为那张图片是最大的我们需要定义这个view的大小所以需这个宽和高,下面
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(_width, _height);
}
就是使用宽和高来处理的,同时我们还看到了画笔Paint和PorterDuffXfermode创建,要说明一下这个PorterDuffXfermode对象是通过画笔Paint来设置的,下面有说明的
public void setResourseId(int resourseId) {
bitmap = decodeBitmap(resourseId);
invalidate();
}
这个代码就是需要我们手动传入想要变为圆形的图片,这个是在Avtivity中设置就行,最主要的代码来看onDraw()方法里面的。
@Override
protected void onDraw(Canvas canvas) {
if(bitmap == null){
return;
}
canvas.drawBitmap(bitmapBorder, 0, 0, paint);
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;
canvas.saveLayer(0, 0, _width, _height, null, saveFlags);
canvas.drawBitmap(bitmapMask, 0, 0, paint);
paint.setXfermode(xfermode);
int left = _width/2 - bitmap.getWidth() /2;
int top = _height/2 - bitmap.getHeight()/2;
canvas.drawBitmap(bitmap, left, top, paint);
paint.setXfermode(null);
canvas.restore();
}
我们来看有三个地方使用了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这个网址就看到有介绍等比缩放图片的例子,我们来看下面的图片效果
上面两张图对比,第一张就是原来的效果,第二张就是对图片进行等比的缩放效果,看看第二张图片代码的:
package com.example.myimageview; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.PorterDuff.Mode;
import android.util.AttributeSet;
import android.view.View; public class itchqImageView extends View{ private Bitmap bg;
private Bitmap photo; private int bg_width;
private int bg_height;
public itchqImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
} private void init(){
bg=BitmapFactory.decodeResource(getResources(),R.drawable.mask);
bg_width=bg.getWidth();
bg_height=bg.getHeight();
} public void setImageView(int imgId){
photo=BitmapFactory.decodeResource(getResources(), imgId);
scaleImage();
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG); paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); RectF rectf=new RectF(0,0,bg_width,bg_height); canvas.saveLayer(rectf, null, Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(photo, 0,0, null);
canvas.drawBitmap(bg, 0, 0,paint);
canvas.restore();
} private void scaleImage(){ if(photo!=null){ int widht=photo.getWidth();
int height=photo.getHeight(); int new_width=0;
int new_height=0; if(widht!=height){
if(widht>height){
new_height=bg_height;
new_width=widht*new_height/height;
}else{
new_width=bg_width;
new_height=height*new_width/widht;
}
}else{
new_width=bg_width;
new_height=bg_height;
}
photo = Bitmap.createScaledBitmap(photo, new_width, new_height, true);
}
} }
scaleImage()这个方法里面就是对图片进行等比的缩放效果,缩放的大小就和我们全黑色的图片大小一样(这里我们原来外面圆形效果去掉了,就是上面第三张全白色的图片)
如果图片不是正方形的我们就需要进行判断对比,最后得出的宽和高就是我们要等比缩放的大小。
Android 遮罩层效果的更多相关文章
- Android 遮罩层效果--制作圆形头像
(用别人的代码进行分析) 不知道在开发中有没有经常使用到这种效果,所谓的遮罩层就是给一张图片不是我们想要的形状,这个时候我们就可以使用遮罩效果把这个图片变成我们想要的形状,一般使用最多就是圆形的效果, ...
- 纯CSS3写的10个不同的酷炫图片遮罩层效果【转】
这个是纯CSS3实现的的10个不同的酷炫图片遮罩层效果,可以欣赏一下 在线预览 下载地址 实例代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...
- 纯CSS3写的10个不同的酷炫图片遮罩层效果
这个是纯CSS3实现的的10个不同的酷炫图片遮罩层效果,可以欣赏一下 在线预览 下载地址 实例代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...
- 利用div实现遮罩层效果
利用div实现遮罩层效果就是利用一个全屏.半透明的div遮住页面上其它元素,典型的例子就是百度的登录界面.下面贴出示例代码: <!DOCTYPE html> <html> &l ...
- html+css源码之实现登录弹出框遮罩层效果
在web开发中,很多网站都做了一些特别炫丽的效果,比如用户登录弹框遮罩层效果,本文章向大家介绍css如何实现登录弹出框遮罩层效果,需要的朋友可以参考一下本文章的源代码. html+css实现登录弹出框 ...
- jquery图片放大镜和遮罩层效果
图片放大镜效果将借助于jqzoom插件,遮罩层借助于thickbox插件. 1.引入样式表 /*整体样式*/ <link rel="stylesheet" href=&quo ...
- jQuery弹出遮罩层效果完整示例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 简单的遮罩层效果,user登陆显示效果
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- js+html实现遮罩层效果(收藏哦)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script ty ...
随机推荐
- 2016-12-14:通过static关键字,使用类成员函数作为回调函数
#include <iostream> using namespace std; class Callee { public: void PrintInfo(int i) { cout & ...
- Ubuntu ssh 服务
安装ssh-serversudo apt-get install openssh-server安装ssh-clientsudo apt-get install openssh-client 修改ssh ...
- PHP中获取当前页面的完整URL
//获取域名或主机地址 echo $_SERVER['HTTP_HOST']."<br>"; #localhost//获取网页地址 echo $_SERVER['PHP ...
- Web后台技术趋势
今天使用Google Trend比较了一下服务器端的程序开发语言技术ASP/ASP.NET Core, PHP, Node.Js的变化趋势,发现一下特点. ASP.NET最近几年一直再下降. ASP和 ...
- Lua学习笔记(一)-----C#和lua的交互
一直以来对Lua热更新技术很感兴趣,在上周开始了对Lua的学习,主要学的是uLua. 直接上干货 准备工作: LuaInterface包括两个核心库一个是LuaInterface.dll,一个是Lua ...
- egret.Tween、egret.Ease
循环调用.只能设置boolean,不能设置循环次数. egret.Tween.).call(()=>{ console.log("循环调用"); }) 每次改变时,调用onC ...
- Druid Monitor监控JavaSE,杀cmd端口进程
1.需要在启动命令添加相关jvm参数 -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname -Dcom.sun.management.jm ...
- 类似于QQ的简单的聊天代码
先编辑页面 package com.lovo.feichun; import java.awt.Color;import java.awt.Component;import java.awt.Cont ...
- php:微信公众号token验证失败原因、验证码显示不出来的问题
ob_clean(); 问题描述: 用微信官方提供的demo验证token是成功的,但是放到自己网站的框架上进行token验证老是提示"token验证失败",经过检查(用生成日志的 ...
- 程序员能力矩阵 Programmer Competency Matrix
[译文]程序员能力矩阵 Programmer Competency Matrix [译文]程序员能力矩阵 Programmer Competency Matrix 注意:每个层次的知识都是渐增的,位于 ...