閱讀701 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Android在自定義View(SurfaceView)中實現進度條Progress

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

Android本身帶有Progress控件。可以在布局中靈活使用,但如果是在自定義的View或者SurfaceView中使用,就需要自己實現,其實不難,隻要熟悉了android的PorterDuff,就能利用PorterDuff的遮罩效果方便的實現進度條。

PorterDuff.Mode的靈活使用可以實現很多強大的功能,比如以前比較流行的美女擦玻璃,在屏幕上用手指繪圖或橡皮檫等功能。

下麵是源碼,老規矩,完整源碼中文章末尾下載。

先上一張效果圖:
Progress效果

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;
/**
 *
 * https://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代替
 * https://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的各種效果:
PorterDuff.Mode效果

完整源碼:點擊下載

出處:https://www.havenliu.com/other/689.html,謝謝!


最後更新:2017-04-03 18:51:45

  上一篇:go 從零開始學習OpenCL開發(二)一個最簡單的示例與簡單性能分析
  下一篇:go Android顯示係統之View與SurfaceView更新屏幕的區別