一、概述

看见猎豹清理大师的内存开口圆环比例进度 挺有意思的,于是就是想自己实现下这样的效果,于是反编译了猎豹清理

大师的app看了下,原来是有两张图,于是脑子里就过了下思路,利用上下两张图,旋转上面张图以及使用

PorterDuffXfermode  来设置合适的渲染模式,就可以达到效果。下面看看咱们的效果吧

二、效果图

三、Xfermode渲染模式简介:

xfermode影响在Canvas已经有的图像上绘制新的颜色的方式 
* 正常的情况下,在图像上绘制新的形状,如果新的Paint不是透明的,那么会遮挡下面的颜色. 
* 如果新的Paint是透明的,那么会被染成下面的颜色

下面的Xfermode子类可以改变这种行为:

AvoidXfermode  指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。

PixelXorXfermode  当覆盖已有的颜色时,应用一个简单的像素XOR操作。

PorterDuffXfermode  这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。

这里不得不提到那个经典的图:

上面的16种模式的说明如下:

从上面我们可以看到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

取两图层全部区域,交集部分变为透明色

四、自定义开口圆环View的实现

1、初始化绘制所需的画笔,字体颜色、大小等变量

public XCArcProgressBar(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub degrees = 0;
paint = new Paint();
//从attrs.xml中获取自定义属性和默认值
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.XCRoundProgressBar);
textColor =typedArray.getColor(R.styleable.XCRoundProgressBar_textColor, Color.RED);
textSize = typedArray.getDimension(R.styleable.XCRoundProgressBar_textSize, 15);
max = typedArray.getInteger(R.styleable.XCRoundProgressBar_max, 100);
isDisplayText =typedArray.getBoolean(R.styleable.XCRoundProgressBar_textIsDisplayable, true);
typedArray.recycle(); }

2、在onDraw()中绘制出来

在onDraw()方法中利用PorterDuffXfermode渲染模式绘制两张开口圆环Bitmap,并计算前景图的旋转角度,从而达到效果图效果。

首先先绘制底部背景图,然后绘制进度前景图,最后利用PorterDuffXfermode的渲染模式和旋转角度比例来进行前景图和背景图的遮罩处理。

@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
int centerX = getWidth() / 2;// 获取中心点X坐标
int centerY = getHeight() / 2;// 获取中心点Y坐标 Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas can = new Canvas(bitmap);
// 绘制底部背景图
bmpTemp = Utils.decodeCustomRes(getContext(), R.drawable.arc_bg);
float dstWidth = (float) width;
float dstHeight = (float) height;
int srcWidth = bmpTemp.getWidth();
int srcHeight = bmpTemp.getHeight(); can.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG
| Paint.FILTER_BITMAP_FLAG));// 抗锯齿 Bitmap bmpBg = Bitmap.createScaledBitmap(bmpTemp, width, height, true);
can.drawBitmap(bmpBg, 0, 0, null); // 绘制进度前景图
Matrix matrixProgress = new Matrix();
matrixProgress.postScale(dstWidth / srcWidth, dstHeight / srcWidth);
bmpTemp = Utils.decodeCustomRes(getContext(), R.drawable.arc_progress); Bitmap bmpProgress = Bitmap.createBitmap(bmpTemp, 0, 0, srcWidth,
srcHeight, matrixProgress, true);
degrees = progress * 270 / max - 270;
//遮罩处理前景图和背景图
can.save();
can.rotate(degrees, centerX, centerY);
paint.setAntiAlias(true);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));
can.drawBitmap(bmpProgress, 0, 0, paint);
can.restore(); if ((-degrees) >= 85) {
int posX = 0;
int posY = 0;
if ((-degrees) >= 270) {
posX = 0;
posY = 0;
} else if ((-degrees) >= 225) {
posX = centerX / 2;
posY = 0;
} else if ((-degrees) >= 180) {
posX = centerX;
posY = 0;
} else if ((-degrees) >= 135) {
posX = centerX;
posY = 0;
} else if ((-degrees) >= 85) {
posX = centerX;
posY = centerY;
} if ((-degrees) >= 225) { can.save();
Bitmap dst = bitmap
.createBitmap(bitmap, 0, 0, centerX, centerX);
paint.setAntiAlias(true);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));
Bitmap src = bmpBg.createBitmap(bmpBg, 0, 0, centerX, centerX);
can.drawBitmap(src, 0, 0, paint);
can.restore(); can.save();
dst = bitmap.createBitmap(bitmap, centerX, 0, centerX, height);
paint.setAntiAlias(true);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));
src = bmpBg.createBitmap(bmpBg, centerX, 0, centerX, height);
can.drawBitmap(src, centerX, 0, paint);
can.restore(); } else {
can.save();
Bitmap dst = bitmap.createBitmap(bitmap, posX, posY, width
- posX, height - posY);
paint.setAntiAlias(true);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));
Bitmap src = bmpBg.createBitmap(bmpBg, posX, posY,
width - posX, height - posY);
can.drawBitmap(src, posX, posY, paint);
can.restore();
}
}
//绘制遮罩层位图
canvas.drawBitmap(bitmap, 0, 0, null); // 画中间进度百分比字符串
paint.reset();
paint.setStrokeWidth(0);
paint.setColor(textColor);
paint.setTextSize(textSize);
paint.setTypeface(Typeface.DEFAULT_BOLD);
int percent = (int) (((float) progress / (float) max) * 100);// 计算百分比
float textWidth = paint.measureText(percent + "%");// 测量字体宽度,需要居中显示 if (isDisplayText && percent != 0) {
canvas.drawText(percent + "%", centerX - textWidth / 2, centerX
+ textSize / 2 - 25, paint);
}
//画底部开口处标题文字
paint.setTextSize(textSize/2);
textWidth = paint.measureText(title);
canvas.drawText(title, centerX-textWidth/2, height-textSize/2, paint);
}

3、设置比例进度的同步接口方法,主要供刷新进度比例用。

/**
* 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步
* 刷新界面调用postInvalidate()能在非UI线程刷新
* @author caizhiming
*/
public synchronized void setProgress(int progress) {
if(progress < 0){
throw new IllegalArgumentException("progress must more than 0");
}
if(progress > max){
this.progress = progress;
}
if(progress <= max){
this.progress = progress;
postInvalidate();
}
}

五、源码下载

真题园网http://www.zhentiyuan.com

源码下载:http://www.demodashi.com/demo/14680.html

Android 自定义View修炼-高仿猎豹清理大师自定义内存开口圆环比例进度View的更多相关文章

  1. Android 自定义控件-高仿猎豹清理大师自定义内存开口圆环控件

    技术:Android+java   概述 看见猎豹清理大师的内存开口圆环比例进度 挺有意思的,于是就是想自己实现下这样的效果,于是反编译了猎豹清理 大师的app看了下,原来是有两张图,于是脑子里就过了 ...

  2. [Android源码]Android源码之高仿飞鸽传书WIFI热点搜索与创建(一)

    (本文详情来源:android源码 http://www.eoeandroid.com/thread-296427-1-1.html   转载请注明出处!)  [Android源码分享]飞鸽传书的An ...

  3. Android自定义View,高仿QQ音乐歌词滚动控件!

    最近在以QQ音乐为样板做一个手机音乐播放器,源码下篇博文放出.今天我想聊的是这个QQ音乐播放器中歌词显示控件的问题,和小伙伴们一起来探讨怎么实现这个歌词滚动的效果.OK,废话不多说,先来看看效果图: ...

  4. Android项目实战之高仿网易云音乐项目介绍

    这一节我们来讲解这个项目所用到的一些技术,以及一些实现的效果图,让大家对该项目有一个整体的认识,推荐大家收藏该文章,因为我们发布文章后会在该文章里面加入链接,这样大家找着就很方便. 目录 第1章 前期 ...

  5. Android项目实战之高仿网易云音乐创建项目和配置

    这一节我们来讲解创建项目:说道大家可能就会说了,创建项目还有谁不会啊,还需要讲吗,别急听我慢慢到来,肯定有你不知道的. 使用项目Android Studio创建项目我们这里就不讲解了,主要是讲解如何配 ...

  6. Lance老师UI系列教程第九课->高仿比特币监控大师

    http://blog.csdn.net/lancees/article/details/22898971

  7. android高仿抖音、点餐界面、天气项目、自定义view指示、爬取美女图片等源码

    Android精选源码 一个爬取美女图片的app Android高仿抖音 android一个可以上拉下滑的Ui效果 android用shape方式实现样式源码 一款Android上的新浪微博第三方轻量 ...

  8. Android 自定义View修炼-自定义HorizontalScrollView视图实现仿ViewPager效果

    开发过程中,需要达到 HorizontalScrollView和ViewPager的效果,于是直接重写了HorizontalScrollView来达到实现ViewPager的效果. 实际效果图如下: ...

  9. Android 自定义View修炼-仿360手机卫士波浪球进度的实现

    像360卫士的波浪球进度的效果,一般最常用的方法就是 画线的方式,先绘sin线或贝塞尔曲线,然后从左到右绘制竖线,然后再裁剪圆区域. 今天我这用图片bitmap的方式,大概的方法原理是: (1)首先用 ...

随机推荐

  1. Apache Mina原理及典型例子分析

    Apache Mina ,一个高性能 Java 异步并发网络通讯框架.利用 Mina 可以高效地完成以下任务: TCP/IP 和 UDP/IP 通讯 串口通讯 VM 间的管道通讯 SSL/TLS JX ...

  2. C#数据上传方法

    /// <summary> /// 连接成功后开始调用数据上传程序 /// </summary> public void CallDataUpload() { //指定上传日期 ...

  3. VS2008编写MFC程序--使用opencv2.4()

    开始记录VS2008环境下学习OPENCV2.4 头文件: #pragma once #include "CvvImage.h" #include "opencv/cv. ...

  4. 解决JSP页面无法使用EasyUI里面class="easyui-dialog"的问题

    当使用MyEclipse新建一个JSP页面的时候,MyEclipse会自动添加一些标记,这些标记也许不一定会在工程中使用到.比如<base href="<%=basePath%& ...

  5. 第四章:ARP 地址解析协议

    网络接口有一个硬件地址,48bit的值,在硬件层次上进行的数据帧交换必须有正确的接口地址.tcp/ip有自己的地址,32bit的IP地址. 但是知道主机的IP地址并不能让内核发送一帧数据给主机.内核( ...

  6. bzoj 1095 [ZJOI2007]Hide 捉迷藏(括号序列+线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1095 [题意] 给定一棵树,树上颜色或白或黑而且可以更改,多个询问求最远黑点之间的距离 ...

  7. 【转载】计算机视觉(CV)前沿国际国内期刊与会议

    计算机视觉(CV)前沿国际国内期刊与会议这里的期刊大部分都可以通过上面的专家们的主页间接找到1.国际会议 2.国际期刊 3.国内期刊 4.神经网络 5.CV 6.数字图象 7.教育资源,大学 8.常见 ...

  8. 【C语言】-条件语句-switch语句

    switch语句: 用于直接处理不同情况下的多路问题. switch语句又可称为开关语句,其执行流程和多分支if语句类似. switch (表达式) { case 常量表达式1:语句组1;break; ...

  9. [OC Foundation框架 - 6] NSMutableString

    NSString是不可变的 NSMutableString是可变字符串   1.初始化 2.串联字符串 3.替换字符串 4.插入字符串 5.删除字符串   #pragma mark buffer st ...

  10. .Net中的Placeholder控件

    NET中的placeholder控件用来做什么的?其实PLACEHOLDER控件,是用来做动态加载用户自定义控件时,一个占位置作用的控件,比如 在从一个Web页面转换到另一个Web页面时,你的ASP. ...