问题概述
对于进度条我相信大家不陌生,这里我就不再多说什么了。因为这个不是重点。我们要说的是如何去自定义一个不一样的进度条。这里用到两张图片(背景和前景),其实是三张(背景、前景和蒙图)。当我们的蒙图在移动的时候,动态地去显示背景和前景。被蒙图挡住的部分显示前景,没有挡住的部分显示背景。而蒙图的图片大小,则需要不小于背景和前景图片大小(如果你不是用来做进度条,就无所谓了),蒙图的图片内容没有要求。
Android中对图片的操作,很多时候都用到了位图——Bitmap。
思路分析
想一想,我们应该怎么来实现这个功能?
抛开蒙板不提,单是做一个自定义的进度条的话,是不是应该让一张背景图保持不动,然后用一张同等大小、不同样式的图片来盖在上面,最后写一个方式来动态改变前景图片需要显示的长度即可。想法是好的,不过我想Android应该还没有只去显示一张图片一部分的方式。如果你说你用的是纯色的前景图片,然后动态改变图片的长度,这个是可以,不过还有一个问题,那就是如果我的类进度条是不规则的图形呢?例如,圆、小车、房子、等等。。。
其实能想上面的这种方式,离真相就已经很接近了。下面我给一张我用画图工具画的原理图,图画得有点粗糙,不过还能看,大家请见谅。
也就是说我们的蒙板其实是由三张图,经过两次合成生成的。第一次是把前景图和蒙板合成,第二是把背景图和刚刚第一次合成好的前置图再一次合成。三张图从上到下的叠放顺序是:蒙板图、前景图、背景图。是不是想说既然蒙板在最上面,那么蒙板不是要把下面两张图给挡住了吗?是这样吗?如果我们只是普通地叠放,的确是这样,如果是这样那这篇博客也就没什么意义了。其实前面我也有一点铺垫的描述,那就是我们的蒙板图片只要大小合适,图片里的内容是无关痛痒的。想想为什么?因为我们的蒙板图片在这里根本不显示出来。你可以把它想像成一片区域,在这片区域里面,我们背景或前景(本程序我们显示背景,其实是A图和蒙板图片合成Bitmap后,有蒙板图的区域就不显示A。这样一来,是不是有蒙板的区域就露出了背景的马脚了?哈哈,就是这样。。。)。
看到这里,大家是不是想问,为什么蒙板图片会不显示呢?是不是Android有一个控件有这样的一个效果呢?没有!不过我们可以自己写,这就是为什么我们要用到Bitmap,一看名字就是它是对位进行操作。这里,我们是对像素进行一个控制。如下:
for (int i = 0; i < maskPixels.length; i++) {
if (maskPixels[i] == 0xff000000) {
showPicturePixels[i] = 0;
} else if (maskPixels[i] == 0) {
} else {
maskPixels[i] &= 0xff000000;
maskPixels[i] = 0xff000000 - maskPixels[i];
showPicturePixels[i] &= 0x00ffffff;
showPicturePixels[i] |= maskPixels[i];
}
}
那我们又如何控制蒙板要显示的长度呢?可以先看看如下代码:
int batteryLevel = 50; // 这里我定了一个50%的电量值,用来调节显示百分之多少
int showWidth = (int)(((double)batteryLevel / 100.0) * showBitmap.getWidth());
maskBitmap.getPixels(maskPixels, 0, w, 0, 0, showWidth, h);
这里,我假设有一个手机电量的参数值。且自定义其数值为剩余50%的电量。通过这个50%来计算我需要显示蒙板图片到什么位置,即showWidth参数值。
关于蒙板的关键技术问题,以上已经做了一个简单的说明。
程序效果图.
最后我给出一张效果图(绿色为背景、黄色为前景、蒙板为黑色,这里不可见。):