Android自定义view利用Xfermode实现动态文字加载动画
对于Xfermode 可能很多人看了一些就放弃了,今天我就个人理解,举简单的我们生活中的例子,让大家更容易理解这是个什么东西。其实并不是你们想象的那么难,你只要懂三步就够了。先来看一看这次的效果图,这个gif大家凑合看。
不要把Xfermode 想的这么难,我把Xfermode 理解成中学时 学的“集合” ,我们知道“集合”是处理 数据的。例如:
集合 A={1,2,3,4},集合B={3,4,5,6}。这两个集合 有三个属性,交集,并集,补集。
那么 Xfermode 我个人理解就是图形集合,就是图形A,图形B 之间可以取,交集,并集,补集。当然这个 A和 B 之间取那种类型,形成什么样的 效果,其实就是我们选取的 Xformode 的 属性类型。
这个就引出了我们今天 的 第一步,虽然是三步,但是前提是你要对自定义view 有一定的了解比如你要知道 ondraw(),onmesure(),Paint 画笔,canvars画布这些内容你要了解,对自定义不是很清楚的朋友可以去 看我的同类文章,文章从入门一步一步带大家进入自定义view:
第一步:我们要熟悉一下这个图
16个图形结果,其实现在有18中。这个图 我们也不用记,只要在用的时候选择对应得 我们的目标图形就行了。具体怎么使用 我们要引出我们今天主要的类 PorterDuffXfermode 这个类就是我们的Xformode 的类了,他还有另外被废弃的两兄弟,被废弃了就不谈了。既然是各类我们要使用就要创建对象,如下:
PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
这里就是我们的 对象,在这里他的构造参数中就是我们上图 选择的类型,最终图形是两个图形的交集部分。当然你可以根据你的目标图形 的效果自己选择,两个图片的混排类型。
这就是 第一步,我们只要了解一下图片的意义,和 PorterDuffXfermode 这个类的用法就够了。我这里提到的 所有图不只是图片,还有我们绘制出来的 圆,矩形等绘制的图。
第二步:
我们了解了 图形 混排的模式,所以第二步我们要有两个图,不然怎么混排,从图中我们可以看出这两个图,分别是 Src ,Dst。接下来我会介绍这两个名字对应我们手机上那个图形。因为我们要画图所以 我们就要来到 ondraw()方法了,这个方法有个类叫canvas 图层,所以这就到了我们第二步的关键点:那就是设置图层,调用方法
canvas.saveLayer( left, top, right, bottom, paint, saveFlags)
首先前四个方法比较简单,就是我们要设置这个图层 的大小,第5个方法就是我们的 画笔,第6个方法我们使用:Canvas.ALL_SAVE_FLAG ,这是一个 flag。
注意:我们在绘制图形之前必须调用上面的方法,不然没有效果。
下面是这个绘制的先后顺序:
/** * 设置图层 */ int layer = canvas.saveLayer(0,0,w,h,paint,Canvas.ALL_SAVE_FLAG); //绘制背景图片 canvas.drawBitmap(bitmap,0,0,paint); //设置 xformode 模式 paint.setXfermode(xfermode); //绘制矩形 paint.setColor(Color.RED); RectF rectF = new RectF(0,y,bitmap.getWidth(),bitmap.getHeight()); canvas.drawRect(rectF,paint); //最后设置为空 paint.setXfermode(null); canvas.restoreToCount(layer);
第三步:
第三步我们还是围绕着上边的代码讲,因为就这几行代码,因为很简单。设置好图层之后,就要绘制图形了,我们这里用canvas绘制了一个 bitmap 图片。大家注意了我们此时 用的 paint 只是普通的 画笔,到这个时候我们的 PorterDuffXfermode 模式还没有使用呢!
再往下看 我们的画笔调用了:
paint.setXfermode(xfermode);
这个方法,所以 如果我们再绘制图形的画,再用到的 画笔 就和我们之前 绘制的图形 不一样了。这个方法可以说是一个分界点,在这个方法之前绘制的图形 和 之后绘制的图形 就分别对应了 我们 图中 Src 和 Dst 的图。这就决定我们最终的目标图形是什么样的。
最后就是 把画笔 的 xformode 模式设置为空。再调用 canvas 的这个方法
canvas.restoreToCount(layer);
我们的绘制就结束了。我这里使用动画动态的改变了 矩形 的高度。我把这个 图片 贴给大家,图片还是盗 别人的。哈哈。
大家可以下载使用。
把代码也贴出来,大家参考。以上 都是我个人的理解 ,包括给大家举的例子,如果有不妥之处请指出,谢谢。
public class XformodeView extends View { Paint paint ; //屏幕宽高 int w; int h; //定义一个矩形的高度变化 float y; //xformode 的 类型 选择 PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN); //图片 Bitmap bitmap; public XformodeView(Context context) { this(context,null); } public XformodeView(Context context, @Nullable AttributeSet attrs) { this(context,attrs,0); } public XformodeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //画笔 paint = new Paint(); paint.setAntiAlias(true); paint.setDither(true); init(context); } /** * 初始化 * @param context */ public void init(Context context){ //获得屏幕宽高 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); w = wm.getDefaultDisplay().getWidth(); h = wm.getDefaultDisplay().getHeight(); //加载bitmap 图片 bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.xxx); //开始动画 animator(); } /** * 测量view */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(bitmap.getWidth(),bitmap.getHeight()); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /** * 绘制 图片 剪切 画布 控制图片显示 */ // Path path = new Path(); // path.moveTo(0,y); // // path.lineTo(bitmap.getWidth(),y); // path.lineTo(bitmap.getWidth(),bitmap.getHeight()); // path.lineTo(0,bitmap.getHeight()); // canvas.clipPath(path); /** * 设置图层 */ int layer = canvas.saveLayer(0,0,w,h,paint,Canvas.ALL_SAVE_FLAG); //绘制背景图片 canvas.drawBitmap(bitmap,0,0,paint); //设置 xformode 模式 paint.setXfermode(xfermode); //绘制矩形 paint.setColor(Color.RED); RectF rectF = new RectF(0,y,bitmap.getWidth(),bitmap.getHeight()); canvas.drawRect(rectF,paint); //最后设置为空 paint.setXfermode(null); canvas.restoreToCount(layer); } /** * 动画 */ public void animator(){ ValueAnimator animator = ValueAnimator.ofFloat(bitmap.getHeight(),0); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { y = (float) animation.getAnimatedValue(); invalidate(); } }); animator.setDuration(3000); animator.start(); } }
你也可以做一些 复杂的 效果 比如 你不用矩形,你可以用 波浪 的效果 让他 充满。发挥想象力去做吧。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
- 【Java学习笔记之三十二】浅谈Java中throw与throws的用法及异常抛出处理机制剖析
- Linux上访问SQL Server数据库
- 2017 Multi-University Training Contest - Team 9 1001&&HDU 6161 Big binary tree【树形dp+hash】
- 【Java学习笔记之三十三】详解Java中try,catch,finally的用法及分析
- 【Java学习笔记之二十九】Java中的"equals"和"=="的用法及区别
- NET跨平台:在Ubuntu下搭建ASP.NET 5开发环境
- 【Code】关关的刷题日记22——Leetcode 53. Maximum Subarray
- 【Java学习笔记之三十四】超详解Java多线程基础
- Codeforces 842B Gleb And Pizza【几何,水】
- Python3希尔排序
- Codeforces 842A Kirill And The Game【暴力,水】
- Wannafly模拟赛 A.矩阵(二分答案+hash)
- 【Java数据结构学习笔记之一】线性表的存储结构及其代码实现
- Comparison of Apache Stream Processing Frameworks: Part 1
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Python 技术篇-index()字符串倒叙匹配获取索引,字符串切片反向输出,逆向输出字符串
- JavaScript 技术篇-navigator.permissions读取chrome剪切板权限获取不生效原因:只有在https协议下使用有效。手动设置chrome页面剪切板读取权限方法
- 生产prometheus-operator 监控二进制kubernetes
- Excel 技术篇-跨页签统计某一区域下符合条件值的数量方法,COUNTIF函数、数量统计公式的用法实例演示
- Oracle 数据库用户锁定与解锁,用户锁定最大密码失败次数设置方法,ORA-28000: the account is locked问题解决方法
- TypeScript 注意事项
- Linux下MySQL数据库的备份与还原,mysql快速导入导出数据库实例演示,解决mysql大数据量数据库导出慢的问题
- 前端如何分片上传文件?
- PL/SQL 工具远程连接Oracle数据库方法,plsql免安装oracle客户端直接配置oci实战演示
- Python 技巧篇-官方网站打不开的情况下通过官方获取最新python安装包方法
- MySQL 技术篇- linux下mysql数据库利用binlog文件进行数据回滚实例演示,binlog恢复数据库的两种方式
- Oracle 数据库表空间不足拓展方法实例演示,表空间剩余大小查看,通过新增表空间文件拓展表空间,表空间文件路径查看
- dbvis 数据库连接工具-更新数据库驱动方法示例演示,驱动与数据库版本不匹配问题:Unknown system variable ‘query_cache_size‘解决方法
- Chrome 插件开发-主动获取所有页签的tabid,background.js直接向所有页签同步传递消息
- Python 技术篇-httpClient库连接服务器发送请求解析响应实例演示,No module named ‘httplib‘问题解决方法