今天重点内容是我们学习自己定义view里面的混合模式。事实上我们的画布就跟photoshop一样。是个图层关系,一层盖着一层。这样就导致有非常多种覆盖模式,这就是我们今天的主题。“混合模式”。


好,如今我们来看下这个模式的说明图:

canvas原有的图片 能够理解为背景 就是dst
新画上去的图片 能够理解为前景 就是src

从上面我们能够看到PorterDuff.Mode为枚举类,一共同拥有16个枚举值:
1.PorterDuff.Mode.CLEAR
所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC
显示上层绘制图片
3.PorterDuff.Mode.DST
显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER
正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER
上下层都显示。

下层居上显示。

6.PorterDuff.Mode.SRC_IN
取两层绘制交集。显示上层。

7.PorterDuff.Mode.DST_IN
取两层绘制交集。

显示下层。
8.PorterDuff.Mode.SRC_OUT
取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT
取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP
取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP
取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR
异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN
取两图层所有区域。交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN
取两图层所有,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY
取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN
取两图层所有区域,交集部分变为透明色


我决定以以下2个效果来作为联系和实现以下请看效果。1、一个是进度条转完以波纹动画的方式显示实物。2、是一款进度条,当进度覆盖文字的时候,覆盖到哪里,哪里的文字的一部分就显示成白色:

第一种效果:

接下来我们就来看这个gif的代码,事实上非常easy主要实现方式呢就是圆形载入条是以Canvas画扇形的方式画出,仅仅是圆心空心而已。载入完之后呢外面的大圆就是Canvas以画圆的方式画出。仅仅是混合模式是CLEAR也是清除的意思。占用大小刚好就是载入条的大小,然后小圆的大小也是载入条的大小,刚好覆盖在大圆上面。

接着就启动循环载入知道所有显示。大圆扩散显示(由于是CLEAR模式所以,覆盖到的地方全是透明的)。小圆缩小显示:

package com.wyw.lodingdemo;import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;public class LoadingView extends View {public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}public LoadingView(Context context, AttributeSet attrs) {super(context, attrs);init();}public LoadingView(Context context) {super(context);init();}private Paint paint;/** 设置矩阵的坐标点 */private RectF rectF;/** 当前进度 */private int current = 0;/** 横向中心X轴 */private float centerX = 0;/** 竖向中心Y轴 */private float centerY = 0;/** 园半径 */private float circleRadius;/** 是否完毕 */private boolean isComplete = false;/** 完毕之后显示的图片 */private Bitmap bitmap;private Matrix matrix;// 缩放比率private float widthRate;private float heightRate;/** bitmap画笔 */private Paint Bpaint;private int size;/** 白屏显示的画布 */private Canvas mCanvas;/** 消失画笔(大圆) */private Paint Gpaint_big;/** 消失画笔(小圆) */private Paint Gpaint_small;private Bitmap fgBitmap;private Bitmap frontBitmap;/** 消失的园半径 */private float gone_circleRadius_big = 0;/** 消失的园半径 */private float gone_circleRadius_small = 0;@SuppressLint("DrawAllocation")@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {centerX = (right - left) / 2;centerY = (bottom - top) / 2;rectF = new RectF(centerX - circleRadius, centerY - circleRadius,centerX + circleRadius, centerY + circleRadius);// 弧形super.onLayout(changed, left, top, right, bottom);}private void init() {size = Math.min(getResources().getDisplayMetrics().widthPixels,getResources().getDisplayMetrics().heightPixels);paint = new Paint();// 布局xml里面引用paint.setColor(Color.parseColor("#fe871a"));paint.setAntiAlias(true);// 设置抗锯齿paint.setStrokeWidth(getInt(1f, size));paint.setStyle(Style.STROKE);// 设置圆心掏空// 设置画笔形状 圆形,须要先设置画笔样式 SYROKE 或者 FILL_AND_STROKEpaint.setStrokeCap(Paint.Cap.ROUND);circleRadius = getInt(7f, size);}/** 获取传入颜色,高度。宽度的Bitmap */public Bitmap CreateBitmap(int color, int width, int height) {int[] rgb = new int[width * height];for (int i = 0; i < rgb.length; i++) {rgb[i] = color;}return Bitmap.createBitmap(rgb, width, height, Config.ARGB_4444);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (!isComplete) {// 没完毕canvas.drawArc(rectF, 0, current, false, paint);} else {// 已完毕if (bitmap != null && isComplete) {if (matrix == null) {initParameters();matrix.reset();matrix.postScale(widthRate, heightRate);// 绘制白色背景图mCanvas.drawBitmap(frontBitmap, 0, 0, null);}canvas.drawBitmap(bitmap, matrix, Bpaint);// 绘制前景canvas.drawBitmap(fgBitmap, 0, 0, null);// mCanvas.drawArc(left, top, right, bottom, startAngle,// sweepAngle, useCenter, Gpaint);mCanvas.drawCircle(centerX, centerY, gone_circleRadius_big,Gpaint_big);// 绘制前景canvas.drawCircle(centerX, centerY, gone_circleRadius_small,Gpaint_small);if (gone_circleRadius_big < centerX * 1.5f|| gone_circleRadius_small > 0) {handler.post(drawRunnable);}}}}private Handler handler = new Handler();private Runnable drawRunnable = new Runnable() {@Overridepublic void run() {gone_circleRadius_big += centerX * 1.5f / 50f;gone_circleRadius_small -=  circleRadius / 50f;invalidate();}};/** 初始化matrix */private void initParameters() {matrix = new Matrix();Bpaint = new Paint();Bpaint.setAntiAlias(true);gone_circleRadius_big = circleRadius;gone_circleRadius_small = circleRadius;Gpaint_small = new Paint();// 防锯齿Gpaint_small.setAntiAlias(true);Gpaint_small.setColor(Color.BLACK);Gpaint_big = new Paint();// 防锯齿Gpaint_big.setAntiAlias(true);// 设置混合模式为DST_INGpaint_big.setXfermode(new PorterDuffXfermode(Mode.CLEAR));// 生成前景图Bitmap 这里拿的宽高要在onDraw里面才干拿到哦。fgBitmap = Bitmap.createBitmap(getWidth(), getHeight(),Config.ARGB_4444);frontBitmap = CreateBitmap(Color.BLACK, getWidth(), getHeight());mCanvas = new Canvas(fgBitmap);if (bitmap != null) {float iw = bitmap.getWidth();float ih = bitmap.getHeight();float width = this.getWidth();float height = this.getHeight();// 初始放缩比率widthRate = width / iw;heightRate = height / ih;}}/** 是否完毕 */public void setComplete(boolean isComplete, Bitmap bitmap) {this.isComplete = isComplete;this.bitmap = bitmap;invalidate();}/*** 设置当前进度* * @param current*            进度*/public void setCurrentProgress(float current, float max) {this.current = (int) ((360f / max) * current);invalidate();}/*** 获取占屏幕的百分比* * @param value*            使用size的百分比* @param size*            最大值* @return 依据百分算出的大小*/private int getInt(float value, int size) {try {return Math.round(value * (float) size / 100f);} catch (Exception ignore) {return 0;}}
}

另外一种效果:

好,我们来看下代码,我这里的默认模式是SCREEN。SCREEN呢就是覆盖的时候覆盖部分会是白色。这里我的文字是SCREEN模式。所以呢当我的进度条覆盖到文字的时候。覆盖的部分就会变成白色。

这里呢我把所有的模式和不同的颜色都加上了,详细怎么理解怎么定义能够下载demo亲自去尝试,去切换看看。那些混合模式究竟都是哪些效果。

package com.wyw.loadingdemob;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.PorterDuffXfermode;
import android.graphics.Paint.Style;
import android.graphics.PorterDuff.Mode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;public class LoadingViewb extends View {public LoadingViewb(Context context) {super(context);init();}public LoadingViewb(Context context, AttributeSet attrs) {super(context, attrs);init();}public LoadingViewb(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}// 背景圆角矩形画笔private Paint paint_bg;// 背景圆角矩形private RectF rect_bg;// 字体画笔private Paint paint_txt;// 前景圆角private Paint paint_front;// 前景圆角矩形private RectF rect_front;// 结束位置private int endX;// 起始位置private int startX;// 当前位置private int currentX;// 竖向中间位置private int centerY;// 横向中间位置private int centerX;// 要显示的文字private String text = "0%";// 文字竖向居中的数值private int txt_center_y = 0;@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {//開始位置(由于是圆角所以会突出一部分所以開始位置得加上屏幕的百分之5)startX = 0 + getInt(5f);//结束位置(由于是圆角所以会突出一部分所以開始位置得减去屏幕的百分之5)endX = right - left - getInt(5f);//拿到y轴中心点centerY = (bottom - top) / 2;//拿到x轴中心点centerX = (right - left) / 2;super.onLayout(changed, left, top, right, bottom);}private void init() {paint_bg = new Paint();paint_bg.setColor(Color.parseColor("#fe871a"));// 设置抗锯齿paint_bg.setAntiAlias(true);paint_bg.setStrokeWidth(getInt(1f));// 设置圆心掏空paint_bg.setStyle(Style.STROKE);// 设置画笔形状 圆形。须要先设置画笔样式 STROKE 或者 FILL_AND_STROKEpaint_bg.setStrokeCap(Paint.Cap.ROUND);paint_txt = new Paint();paint_txt.setColor(Color.parseColor("#fe871a"));paint_txt.setTextSize(getInt(5f));// 设置抗锯齿paint_txt.setAntiAlias(true);// 设置混合模式为SCREENpaint_txt.setXfermode(new PorterDuffXfermode(Mode.SCREEN));// 以下这行是实现字体水平居中paint_txt.setTextAlign(Paint.Align.CENTER);paint_front = new Paint();paint_front.setColor(Color.parseColor("#fe871a"));// 设置抗锯齿paint_front.setAntiAlias(true);// 设置混合模式为SRC_ATOPpaint_front.setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (rect_bg == null) {rect_bg = new RectF(startX, centerY - getInt(5f), endX, centerY+ getInt(5f));rect_front = new RectF(startX, centerY - getInt(5f), currentX,centerY + getInt(5f));// 实现字体竖向居中FontMetricsInt fontMetrics = paint_txt.getFontMetricsInt();txt_center_y = (centerY * 2 - fontMetrics.bottom - fontMetrics.top) / 2;}canvas.drawRoundRect(rect_bg, getInt(10f), getInt(10f), paint_bg);canvas.drawRoundRect(rect_front, getInt(10f), getInt(10f), paint_front);canvas.drawText(text, centerX, txt_center_y, paint_txt);}// 设置当前进度public void setCurrentProgress(float current, float max) {//由于起点不是0,所以总长度须要减去起点 (endX-startX)currentX = (int) (((float) (endX-startX) / max) * current);text = (int) ((float) currentX / (float) (endX-startX) * 100) + "%";//由于起点不是0所以须要加上起点的rect_front.right = currentX+startX;invalidate();}// 设置字体颜色public void setTextColor(int color) {paint_txt.setColor(color);//重置数据currentX = 0;text = "0%";if (rect_front != null) {rect_front.right = currentX;}invalidate();}// 设置重叠模式public void setMode(String mode) {if (mode.equals("clear")) {// 设置混合模式为CLEARpaint_txt.setXfermode(new PorterDuffXfermode(Mode.CLEAR));} else if (mode.equals("Src")) {// 设置混合模式为SRCpaint_txt.setXfermode(new PorterDuffXfermode(Mode.SRC));} else if (mode.equals("Dst")) {// 设置混合模式为DSTpaint_txt.setXfermode(new PorterDuffXfermode(Mode.DST));} else if (mode.equals("srcOver")) {// 设置混合模式为SRC_OVERpaint_txt.setXfermode(new PorterDuffXfermode(Mode.SRC_OVER));} else if (mode.equals("DstOver")) {// 设置混合模式为DST_OVERpaint_txt.setXfermode(new PorterDuffXfermode(Mode.DST_OVER));} else if (mode.equals("SrcIn")) {// 设置混合模式为SRC_INpaint_txt.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));} else if (mode.equals("DstIn")) {// 设置混合模式为DST_INpaint_txt.setXfermode(new PorterDuffXfermode(Mode.DST_IN));} else if (mode.equals("SrcOut")) {// 设置混合模式为SRC_OUTpaint_txt.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));} else if (mode.equals("DstOutr")) {// 设置混合模式为DST_OUTpaint_txt.setXfermode(new PorterDuffXfermode(Mode.DST_OUT));} else if (mode.equals("SrcATop")) {// 设置混合模式为SRC_ATOPpaint_txt.setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));} else if (mode.equals("DstATop")) {// 设置混合模式为DST_ATOPpaint_txt.setXfermode(new PorterDuffXfermode(Mode.DST_ATOP));} else if (mode.equals("Xor")) {// 设置混合模式为XORpaint_txt.setXfermode(new PorterDuffXfermode(Mode.XOR));} else if (mode.equals("Darken")) {// 设置混合模式为DARKENpaint_txt.setXfermode(new PorterDuffXfermode(Mode.DARKEN));} else if (mode.equals("Lighten")) {// 设置混合模式为LIGHTENpaint_txt.setXfermode(new PorterDuffXfermode(Mode.LIGHTEN));} else if (mode.equals("Multiply")) {// 设置混合模式为MULTIPLYpaint_txt.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));} else if (mode.equals("Screen")) {// 设置混合模式为SCREENpaint_txt.setXfermode(new PorterDuffXfermode(Mode.SCREEN));}//重置数据currentX = 0;text = "0%";if (rect_front != null) {rect_front.right = currentX;}invalidate();}/*** 获取占屏幕的百分比* * @param value*            使用size的百分比* @param size*            最大值* @return 依据百分算出的大小*/private int getInt(float value) {int size = Math.min(getResources().getDisplayMetrics().widthPixels,getResources().getDisplayMetrics().heightPixels);try {return Math.round(value * (float) size / 100f);} catch (Exception ignore) {return 0;}}
}

本篇博客就到这里,假设有有疑问的欢迎留言讨论。同一时候希望大家多多关注我的博客。多多支持我。

尊重原创转载请注明:(http://blog.csdn.net/u013895206) !


以下是地址传送门:

第一种效果下载地址:http://download.csdn.net/detail/u013895206/9479008

另外一种效果下载地址:http://download.csdn.net/detail/u013895206/9479013

转载于:https://www.cnblogs.com/claireyuancy/p/7346597.html

自己定义View学习之12/7(进度条之混合模式)相关推荐

  1. 精通Android自定义View(十二)绘制圆形进度条

    1 绘图基础简析 1 精通Android自定义View(一)View的绘制流程简述 2 精通Android自定义View(二)View绘制三部曲 3 精通Android自定义View(三)View绘制 ...

  2. Android 自定义View实现环形带刻度的进度条

    本篇文章讲的是自定义View实现环形带刻度的进度条.和往常一样,主要还是想总结一下自定义View实现环形带刻度的进度条的开发过程以及一些需要注意的地方. 按照惯例,我们先来看看效果图 一.我们如何来实 ...

  3. android 自定义音乐圆形进度条,Android自定义View实现音频播放圆形进度条

    本篇文章介绍自定义View配合属性动画来实现如下的效果 实现思路如下: 根据播放按钮的图片大小计算出圆形进度条的大小 根据音频的时间长度计算出圆形进度条绘制的弧度 通过Handler刷新界面来更新圆形 ...

  4. android+属性动画+高度,android 自定义view+属性动画实现充电进度条

    近期项目中需要使用到一种类似手机电池充电进度的动画效果,以前没学属性动画的时候,是用图片+定时器的方式来完成的,最近一直在学习动画这一块,再加上复习一下自定义view的相关知识点,所以打算用属性动画和 ...

  5. android 动态进度条,Android实用view系列------炫酷的进度条

    不知不觉距离上次写文章已经过去大半个月了,原本计划每周写一篇的想法在坚持几周之后最终还是被生活中各种各样的琐事打乱,无奈中夹杂这对自己的一点失望. 心痛.jpg 当初的愿望实现了吗 事到如今只好祭奠吗 ...

  6. 自定义View之王者荣耀等级进度条

    Demo效果 这里用王者荣耀的等级做了一个demo 实现思路 由进度条想到ProgressBar,继承自ProgressBar,可以在onDraw()中通过getProgress()和getMax() ...

  7. Android学习笔记之progressBar(进度条)

    一.说明 <1>在某项延续性工作的进展过程中为了不让用户觉得程序死掉了,需要有个活动的进度条,表示此过程正在进行中. <2>在某些操作的进度中的可视指示器,为用户呈现操作的进度 ...

  8. python有哪两种表现形式小练笔_Python学习小练笔—文本进度条

    1.简单文本进度条 import time scale=10 print("-----执行开始-----") for i in range(scale+1): a,b='**'*i ...

  9. Android拖动进度条画面随动,ftk学习记录(一个进度条文章)

    [ 声明:版权全部,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 首先.在開始今天的文章之前.我们还是给朋友们展示一下前面一段代码的执行效果.效果例如以下, w ...

最新文章

  1. 无线渗透--wifiphisher之wifi钓鱼获取wifi密码
  2. 数组中a和a 的区别?
  3. 实现原理_Condition 实现原理
  4. 自己搭建的邮件系统不能发往gmail、hotmail等问题解决
  5. 机器学习实战--决策树算法
  6. 使用encodeURl()进行编解码
  7. 我对软件测试的理解以及我的职业规划
  8. java calendar clear_java.util.Calendar clear()方法
  9. Bailian2722 学分绩点【序列处理】
  10. WCF消息传输的几个基本概念(知识点整理)
  11. lingo姜启源数学模型接力队选拔问题实现实例
  12. MAC终端命令自动补全
  13. JPG/PNG转真SVG,非base64
  14. w10怎么自动锁定计算机,教你如何设置Win10系统自动锁屏?
  15. 短视频剪辑的九大技巧分享
  16. 最小二乘法的几何意义
  17. java 判断当前时间节气,请问js获取阴历节气后根据节气判断春夏秋冬四季?该怎么写呢...
  18. 百度BAE平台使用(一)注册开发者BAE环境
  19. 怎么还原计算机系统还原,怎么还原以前版本的windows?Win7/Win10系统还原方法
  20. 如何快速判断一个数是否是素数

热门文章

  1. python怎么打开程序管理器_python进程管理工具supervisor的安装与使用教程
  2. 笨方法学python第四版当当_“笨办法”学Python(第3版)
  3. MYSQL:Error Code: 1786 Statement violates GTID consistency: CREATE TABLE ... SELECT.
  4. SpringBoot中修改tomcat最大连接数、最大线程数、最大等待数
  5. C# 操作List集合报错:集合被修改,枚举操作可能不会执行(Collection was modified, enumeration operation may not execute)
  6. Visual Studio Code 支持TensorFlow配置支持
  7. 客户端程序调用zookeeper报len4807928异常
  8. ScrollView
  9. 第一个关于selenium项目
  10. java多线程(二)——锁机制synchronized(同步方法)