Android View高仿猎豹清理大师自定义开口圆环比例进度

一、概述

Android下的 猎豹清理大师的内存开口圆环比例进度 挺不错的,于是反编译了猎豹清理大师的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();
    }
}

最后,自己试玩着感觉良好,可以直接应用到实际项目中

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, bitmap
, canvas
模式
具有一个开口的圆环套、css3 圆环进度条、圆环进度条html5效果、android 圆环进度条、圆环进度条,以便于您获取更多的相关知识。

时间: 2024-08-02 00:52:27

Android View高仿猎豹清理大师自定义开口圆环比例进度的相关文章

猎豹清理大师解读谷歌Android L为什么选中ART?

2014谷歌I/O大会已经于北京时间今日凌晨,正式在位于加州旧金山的Moscone中心举行.有人戏称此次大会的宗旨就是"安卓接管一切",在最重磅的AndroidL部分,除了推出全平台的"材料设计语言",谷歌还就安卓底层核心技术进行了方向性的部署,包括ART.安全.省电等重点优化领域.Android L默认采用ART运行环境,完全兼容64位移动处理器.谷歌称这将比此前的Dalvik模式性能提高两倍, 但是会占用更多的内存空间.Android有三种运行模式:JNI.Da

Android开发高仿课程表的布局实例详解_Android

先说下这个demo,这是一个模仿课程表的布局文件,虽然我是个菜鸟,但我还是想留给学习的人一些例子,先看下效果   然后再来看一下我们学校的app 布局分析 先上一张划分好了的布局图 首先整个页面放在一个LinearLayout布局下面,分为上面和下面两个部分,下面一个是显示课程表的详细信息 1:这个没什么好讲的,就是直接一个LinearLayout布局,然后将控件一个TextView用来显示年份,一个View用来当作竖线,一个Spinner用来显示选择周数 2:这个是显示星期几的部件,是我自定义

Android开发高仿课程表的布局实例详解

先说下这个demo,这是一个模仿课程表的布局文件,虽然我是个菜鸟,但我还是想留给学习的人一些例子,先看下效果 然后再来看一下我们学校的app 布局分析 先上一张划分好了的布局图 首先整个页面放在一个LinearLayout布局下面,分为上面和下面两个部分,下面一个是显示课程表的详细信息 1:这个没什么好讲的,就是直接一个LinearLayout布局,然后将控件一个TextView用来显示年份,一个View用来当作竖线,一个Spinner用来显示选择周数 2:这个是显示星期几的部件,是我自定义的V

好声音来袭 猎豹清理大师带来畅快视频体验

<中国好声音>第三季首播,就引来赞扬.吐槽无数,顺带着破了多项观看纪录.尤其是其网络播放量,http://www.aliyun.com/zixun/aggregation/11632.html">24小时就突破1.5亿次,有数据显示,这其中大部分播放量都来自移动终端.但有研究者表示,并不是所有主流手机都能完全胜任1080P高清视频播放的,由于内存不足,或多开应用情况下观看视频时常会遇到卡顿.声画不同步.高发热等问题,所以导致不能播放的关键因素大都不是"硬件"

猎豹清理大师报告称:清理隐私次数和离婚率成反比

<2014一季度各省手机使用习惯报告>由猎豹清理大师团队根据全国34个省份6万名手机用户的问卷调研.深度访谈等数据撰写而成.本报告主要反映全国各省用户在清理手机垃圾文件和手机隐私等行为上的差异,以引起社会大众对手机垃圾和手机隐私重要性的关注.一.清理手机垃圾频率:第一名和最后一名相差4倍猎豹清理大师的垃圾清理功能,可以一键删除拖慢手机运行速度的缓存垃圾文件.2014年第一季度,猎豹清理大师为全国用户总共删除了34268 TB手机垃圾文件,相当于85亿首MP3歌曲或1200多万部高清电影.根据使

猎豹清理大师发布一季度各省手机使用习惯报告

报告显示,越常清理手机隐私的省份,离婚率越低.尽管如此,仍然有85%以上的男女受访者承认一有机会就想要偷看伴侣的手机,女性付诸行动的比率远高于男性.越经常清理手机隐私的省份,离婚率越低手机隐私包括微信.QQ.短信记录,以及信用卡账号密码.浏览器历史记录.私密照等涉及个人秘密的信息.猎豹清理大师的隐私清理功能,可以一键清理以上私密信息.通过调研各省用户使用该功能的频率,猎豹清理大师发现了一个有趣的现象:越经常清理手机隐私的省份,离婚率越低.其中,云南.贵州.湖北.湖南.重庆等5省市的手机用户,最爱

猎豹清理大师推cpu降温 成手机降温神器

8月8日消息,猎豹移动今日正式推出猎豹清理大师V5.8版.据官方介绍,此版主要针对手机CPU被异常占用而产生的发热问题进行的功能升级,新增发热检测功能和CPU异常状态侦测与提醒功能,进一步优化提升了CPU运行效率,有效降低手机温度.猎豹移动工程师称:猎豹清理大师新版在研发过程中,团队对上万款APP进行了分析测试.结果显示,大量软件发生异常时会过多占用CPU,导致手机发热.卡顿.耗电严重等问题.为此,猎豹移动特推出了V5.8版清理大师,优化CPU进程,实现手机降温.戳此下载:http://www.

猎豹清理大师怎么给软件分类

  当我们在使用猎豹清理大师时,可以通过"软件管理"选项对已安装的软件进行卸载 备份.搬家等管理,不过,APP一多起来,就不好管理了,为此,对软件进行分类很有必要. 那么在猎豹清理大师上怎么给软件分类呢?如果你还不清楚的话,可以来看看下面的方法. 1.打开猎豹清理大师,进入[软件管理] 2.可选择[按日期].[按频率].[按软件大小]等分类查看方式 3.还可以在[更多]里选择其他分类方式 4.比如[按类别]就是按照软件的功能来分类

猎豹清理大师怎么添加白名单

  进入猎豹清理大师,选择[手机加速] 方法一 1.在[正在运行的程序]下长按某个程序 2.在弹出选项里选择[加入白名单] 3.系统提示加入成功 方法二 1.选择右上角的[菜单] 2.在下拉框里选择[进程白名单] 3.点击右上角的[+] 4.选择需要添加至白名单的程序 5.系统提示添加成功