Android在自定义View(SurfaceView)中实现进度条Progress

http://www.havenliu.com/java/689.html

Android本身带有Progress控件。可以在布局中灵活使用,但如果是在自定义的View或者SurfaceView中使用,就需要自己实现,其实不难,只要熟悉了android的PorterDuff,就能利用PorterDuff的遮罩效果方便的实现进度条。

PorterDuff.Mode的灵活使用可以实现很多强大的功能,比如以前比较流行的美女擦玻璃,在屏幕上用手指绘图或橡皮檫等功能。

下面是源码,老规矩,完整源码中文章末尾下载。

先上一张效果图:


Main.java,这是个Activity,地球人都看的懂

? Download Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.havenliu.progressdemo;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.Display;
import android.view.Window;
import android.view.WindowManager;
/**
 *
 * http://www.havenliu.com/other/689.html
 * @author HavenLiu 
 *
 */
public class Main extends Activity {
	public static int screen_width;// 屏幕的宽度
	public static int screen_height;// 屏幕的高度
	//图片资源根据游戏屏幕的缩放比例
	public static float zoomRate;
	public static boolean isRun;
 
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// 全屏显示窗口
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
		isRun = true;
 
		Display display = getWindowManager().getDefaultDisplay();
 
		screen_width = display.getWidth();
		screen_height = display.getHeight();
		zoomRate = getZoomRate();
		setContentView(new MyView(this));
	}
 
	/**
	 * 计算图片的缩放比例,这要是为了让图片能自适应屏幕大小
	 * 
	 * @return
	 */
	private float getZoomRate() {
		float rate = 1f;
		float rate_width = screen_width / 44f;// 图片资源的宽度为44px
		float rate_height = screen_height / 547f;// 图片资源的高度为547px
		rate = Math.min(rate_width, rate_height);
		return rate;
	}
 
	@Override
	protected void onDestroy() {
		super.onDestroy();
		isRun = false;
	}
}

MyView.java:是一个自定义View,为了简单,这没有使用SurfaceView,其实是一样的。里面实现了对分辨率的自适应,可以在不同分辨率下保证progress的精准。

? Download MyView.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package com.havenliu.progressdemo;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.view.View;
 
/**
 * 自定义View,也可以用SurfaceView代替
 * http://www.havenliu.com/other/689.html
 * @author HavenLiu 
 *
 *
 */
public class MyView extends View implements Runnable {
	// 游戏总时间,单位:秒
	public static final int TOTALTIME = 30;
	// 刷新频率:毫秒
	public static final int REFRESH = 30;
	private Bitmap img_progress;
	private Bitmap img_progress_bg;
	// 屏幕每次刷新,progressBar应减去的长度
	private float step;
	private Paint paint;
	// progressBar的中长度
	private float progress;
 
	public MyView(Context context) {
		super(context);
		paint = new Paint();
		paint.setDither(true);
 
		initBitmap();
		initProgress();
		new Thread(this).start();
	}
 
	/**
	 * 预加载图片图片资源,并根据屏幕大小等比缩放
	 */
	private void initBitmap() {
		Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.timebar);
		Matrix matrix = new Matrix();
		matrix.postScale(Main.zoomRate, Main.zoomRate);
		img_progress = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
 
		Bitmap bitmap_bg = BitmapFactory.decodeResource(getResources(), R.drawable.timebar_bg);
		img_progress_bg = Bitmap.createBitmap(bitmap_bg, 0, 0, bitmap_bg.getWidth(), bitmap_bg.getHeight(), matrix, true);
	}
 
	/**
	 * 初始化progressBar相关参数
	 */
	private void initProgress() {
		int _totalTime = TOTALTIME * 1000;
		int refreshTimes = _totalTime / REFRESH;
		progress = 547.0f * Main.zoomRate;
		step = progress / refreshTimes;// 547为滚动条的高度
	}
 
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		canvas.drawARGB(255, 157, 157, 157);
		// 居中
		canvas.drawBitmap(img_progress, Main.screen_width / 2 - img_progress.getWidth() / 2, 0, null);// 背景条:蓝色
 
		int rc = canvas.saveLayer(Main.screen_width / 2 - img_progress.getWidth() / 2, img_progress.getHeight() - progress, Main.screen_width / 2 + img_progress.getWidth() / 2,
				img_progress.getHeight(), null, Canvas.ALL_SAVE_FLAG);
		paint.setFilterBitmap(false);
		canvas.drawRect(Main.screen_width / 2 - img_progress.getWidth() / 2, 0, Main.screen_width / 2 + img_progress.getWidth() / 2, img_progress.getHeight(), paint);
		//Xfermode的类型很重要,不同的Mode有不同的效果。具体可以参考后面的图片
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(img_progress_bg, Main.screen_width / 2 - img_progress.getWidth() / 2, 0, paint);
		paint.setXfermode(null);
		canvas.restoreToCount(rc);
	}
 
	@Override
	public void run() {
		while (Main.isRun) {
			postInvalidate();
			if (progress <= 0) {
				// Game Over.....
				// do something......
//				Log.i("", "Game over.........you lost!");
			} else {
				progress -= step;
			}
			try {
				Thread.sleep(REFRESH);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
 
}
PorterDuff.Mode的各种效果:

你可能感兴趣的:(android)