您的位置:首页 > 移动开发 > Android开发

Android进阶篇之RoundProgress(圆形进度条)使用两张图片叠加实现

2015-01-28 13:00 756 查看
本篇主要介绍怎么利用两张图片去实现圆形进度条

其实实现圆形进度条很简单,自定义View,画出一个环,然后控制遮罩环就可以了

但是用画笔画的环很不好控制大小,

<因为适配这个问题,所以用像素控制不很乐观>

所以最好使用两张图片去控制进度条的显示岂不是就解决了适配的问题

问题来了,那要怎么实现啊,小伙伴们肯定火大了,那不废话嘛,明显用图片遮罩啊!

嗯,对,就是用遮罩,可是在网上找了一圈也没发现使用两张图片遮罩实现圆形进度条,都是各种画圆。


也是悲催了,于是乎,笔者就耐不住了,自己动手,丰衣足食

首先呢,看看效果图吧!,触屏增加进度



第一:了解一下setXfermode

额鹅鹅鹅。。。。至于这个网上太多了,反正就是遮罩的显示模式,小伙伴们自己随便看看去吧,

,记得看完还要回来哦
上一张图,看看setXfermode的模式,其实不去看也没关系



第二步:上代码,

,当然是代码才重要了

/**
* 利用View的相交模式,实现两种圆形图片的进度条
*
*/
public class MyView extends View {
private Bitmap bmpBg;
private Bitmap bmpForbg;

private PorterDuffXfermode mMode ;
private Paint mXferPaint ;
private RectF mOval ;
private int mPercent;

private Paint paint ;
private Rect targetRect ;
private FontMetricsInt fontMetrics ;
/**
* 重写父类构造函数
*
* @param context
*/
public MyView(Context context) {
super(context);
setFocusable(true);
// setFocusableInTouchMode(true);
bmpBg = (Bitmap) BitmapFactory.decodeResource(getResources(),
R.drawable.ic_set_download_speed1);
bmpForbg = (Bitmap) BitmapFactory.decodeResource(getResources(),
R.drawable.ic_set_download_speed2);

mMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
//        mXferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mXferPaint = new Paint();
//        mXferPaint.setStyle(Paint.Style.FILL);
mXferPaint.setColor(Color.RED);
mXferPaint.setXfermode(mMode);
mOval = new RectF();
mOval.left = 0;
mOval.top = 0;

mPercent = 0 ;

paint = new Paint() ;
paint.setColor(getResources().getColor(R.color.pr2)) ;
paint.setTextSize(24) ;
targetRect = new Rect(100, 100, 100 + bmpBg.getWidth(), 100 + bmpBg.getHeight());
fontMetrics = paint.getFontMetricsInt();
}

/**
* 重写父类绘图函数
*/
@Override
protected void onDraw(Canvas canvas) {

mXferPaint.setXfermode(null);
canvas.drawBitmap(bmpBg, 100, 100, mXferPaint) ;
int saveCount = canvas.saveLayer(100, 100, 100 + bmpBg.getWidth(), 100 + bmpBg.getHeight(), null, Canvas.MATRIX_SAVE_FLAG
| Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
| Canvas.CLIP_TO_LAYER_SAVE_FLAG);

mOval.left = 100 ;
mOval.top = 100 ;
mOval.right = 100 + bmpBg.getWidth();
mOval.bottom = 100 + bmpBg.getHeight();
mXferPaint.setXfermode(null);
canvas.drawArc(mOval, -90, 360 * mPercent / 100, true, mXferPaint);

mXferPaint.setXfermode(mMode);
canvas.drawBitmap(bmpForbg, 100, 100, mXferPaint);

canvas.restoreToCount(saveCount);

int baseline = targetRect.top + (targetRect.bottom - targetRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
// 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(mPercent + "%", targetRect.centerX(), baseline, paint);
}

@Override
public boolean onTouchEvent(MotionEvent event) {

mPercent ++ ;
mPercent %= 100 ;

// 重绘画布
invalidate();
// postInvalidate();
return true;
}
}


第三呢,如果亲们看代码已经懂了,就去逛逛其他的博文吧

,接下来进入分析阶段

定义两张备用图Bitmap
private Bitmap bmpBg;
private Bitmap bmpForbg;
然后呢,定义操作图片的画笔mXferPaint,以及显示区域mOval<备注:因为显示区域是扇形的,所以当然是Oval了>
以及重叠显示模式mMode
private PorterDuffXfermode mMode ;
private Paint mXferPaint ;
private RectF mOval ;
接着就定义一个需要控制进度的变量
private int mPercent;
最后就剩下中间显示进度的文字了,targetRect和fontMetrics是为了使文字居中显示,大家可以先不管
private Paint paint ;
private Rect targetRect ;
private FontMetricsInt fontMetrics ;
接着就是初始化操作了
public MyView(Context context) {
super(context);
setFocusable(true);
// setFocusableInTouchMode(true);
bmpBg = (Bitmap) BitmapFactory.decodeResource(getResources(),
R.drawable.ic_set_download_speed1);
bmpForbg = (Bitmap) BitmapFactory.decodeResource(getResources(),
R.drawable.ic_set_download_speed2);

mMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
//        mXferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mXferPaint = new Paint();
//        mXferPaint.setStyle(Paint.Style.FILL);
mXferPaint.setColor(Color.RED);
mXferPaint.setXfermode(mMode);
mOval = new RectF();
mOval.left = 0;
mOval.top = 0;

mPercent = 0 ;

paint = new Paint() ;
paint.setColor(getResources().getColor(R.color.pr2)) ;
paint.setTextSize(24) ;
targetRect = new Rect(100, 100, 100 + bmpBg.getWidth(), 100 + bmpBg.getHeight());
fontMetrics = paint.getFontMetricsInt();
}


看这个应该没什么问题吧

重点来了!就是复写onDraw了
先把画笔的模式设置为null,把背景画了
<span style="white-space:pre">		</span>mXferPaint.setXfermode(null);
canvas.drawBitmap(bmpBg, 100, 100, mXferPaint) ;
接下来定制Oval区域,然后绘制前景图
定制区域前需要对画布进行一个save的操作
int saveCount = canvas.saveLayer(100, 100, 100 + bmpBg.getWidth(), 100 + bmpBg.getHeight(), null, Canvas.MATRIX_SAVE_FLAG
| Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
| Canvas.CLIP_TO_LAYER_SAVE_FLAG);

mOval.left = 100 ;
mOval.top = 100 ;
mOval.right = 100 + bmpBg.getWidth();
mOval.bottom = 100 + bmpBg.getHeight();
mXferPaint.setXfermode(null);
canvas.drawArc(mOval, -90, 360 * mPercent / 100, true, mXferPaint);

mXferPaint.setXfermode(mMode);
canvas.drawBitmap(bmpForbg, 100, 100, mXferPaint);

canvas.restoreToCount(saveCount);
终点终于来了,就是操控另一只画笔涂写文体了
前面的两行代码是为了文字居中做的操作
<span style="white-space:pre">	</span>int baseline = targetRect.top + (targetRect.bottom - targetRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
// 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(mPercent + "%", targetRect.centerX(), baseline, paint);


第四步呢,现在需要做什么呢?

,小伙伴肯定又想了,又想装X。。。<B>

因为需要有进度嘛,所以当然是需要更新画布,做进度加减的操作咯

@Override
public boolean onTouchEvent(MotionEvent event) {

mPercent ++ ;
mPercent %= 100 ;

// 重绘画布
invalidate();
// postInvalidate();
return true;
}


注意咯
invalidate();//这个可不能少,是刷新画布


最后给一个源码下载 的链接吧!不要钱,免费,任性
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: