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的各种效果:

完整源码:点击下载

出处:http://www.havenliu.com/other/689.html,谢谢!

时间: 2024-09-21 17:28:17

Android在自定义View(SurfaceView)中实现进度条Progress的相关文章

Android自定义View实现钟摆效果进度条PendulumView_Android

在网上看到了一个IOS组件PendulumView,实现了钟摆的动画效果.由于原生的进度条确实是不好看,所以想可以自定义View实现这样的效果,以后也可以用于加载页面的进度条.  废话不多说,先上效果图   底部黑边是录制时不小心录上的,可以忽略.  既然是自定义View我们就按标准的流程来,第一步,自定义属性  自定义属性  建立属性文件  在Android项目的res->values目录下新建一个attrs.xml文件,文件内容如下: <?xml version="1.0&quo

Android自定义View实现钟摆效果进度条PendulumView

在网上看到了一个IOS组件PendulumView,实现了钟摆的动画效果.由于原生的进度条确实是不好看,所以想可以自定义View实现这样的效果,以后也可以用于加载页面的进度条. 废话不多说,先上效果图 底部黑边是录制时不小心录上的,可以忽略. 既然是自定义View我们就按标准的流程来,第一步,自定义属性 自定义属性 建立属性文件 在Android项目的res->values目录下新建一个attrs.xml文件,文件内容如下: <?xml version="1.0" enco

求大神解答一下-android 在自定义view 中添加popwindow报错

问题描述 android 在自定义view 中添加popwindow报错 android 在自定义view中添加popuwindow报错 GC_CONCURRENT freed 内存问题. 求大神给解决方案 解决方案 Android的ScrollView中添加自定义View----------------------

界面-android这样的一个自定义View有什么问题吗?

问题描述 android这样的一个自定义View有什么问题吗? 不知道为什么在布局中添加了却没有什么显示: //界面更新 BookButton bookButton=new BookButton(SelectAty.this,newNote); layout.addView(bookButton); View源码: public class BookButton extends RelativeLayout { Note note; TextView noteName; public BookB

Android通过自定义View实现随机验证码_Android

很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章. 一.问题描述 熟悉web开发中童鞋们都知道为了防止恶意破解.恶意提交.刷票等我们在提交表单数据时,都会使用随机验证码功能.在Android应用中我们同样需要这一功能,该如何实现呢,下面我们就自定义一个随机验证码View控件实现这一需求,并且具备通用性,需要的时候在界面中直接加入这个View组件即可. 二.案例介绍 案例运行效

Android使用自定义View绘制渐隐渐现动画_Android

实现了一个有趣的小东西:使用自定义View绘图,一边画线,画出的线条渐渐变淡,直到消失.效果如下图所示: 用属性动画或者渐变填充(Shader)可以做到一笔一笔的变化,但要想一笔渐变(手指不抬起边画边渐隐),没在Android中找到现成的API可用.所以,自己做了一个. 基本的想法是这样的: 在View的onTouchEvent中记录触摸点,生成一条一条的线LineElement,放在一个List中.给每个LineElement配置一个Paint实例. 在onDraw中绘制线段. 变换LineE

Android通过自定义View实现随机验证码

很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章. 一.问题描述 熟悉web开发中童鞋们都知道为了防止恶意破解.恶意提交.刷票等我们在提交表单数据时,都会使用随机验证码功能.在Android应用中我们同样需要这一功能,该如何实现呢,下面我们就自定义一个随机验证码View控件实现这一需求,并且具备通用性,需要的时候在界面中直接加入这个View组件即可. 二.案例介绍 案例运行效

Android编程实现类似于圆形ProgressBar的进度条效果

本文实例讲述了Android编程实现类似于圆形ProgressBar的进度条效果.分享给大家供大家参考,具体如下: 我们要实现一个类似于小米分享中的圆形播放进度条,android自带的圆形ProgressBar是默认自动旋转的,所以无法实现,于是我们想到了使用自定义一个View,来实现这种效果. 首先来看看自己定义的View package cn.easymobi.application.bell.common; import android.content.Context; import an

Android 仿摩拜单车共享单车进度条实现StepView效果

先看效果图: Step1:定义StepBean 定义五个状态,分别为:为完成.正在进行.已完成.终点完成.终点未完成. public class StepBean{ public static final int STEP_UNDO = -1;//未完成 public static final int STEP_CURRENT = 0;//正在进行 public static final int STEP_COMPLETED = 1;//已完成 public static final int S