編輯:高級開發
QQ:158067568
上一節小試牛刀,介紹了一個簡單的SurfaceVIEw的例子,如果用於實際開發,那還差得遠呢。本節介紹SurfaceView與VIEw結合使用的例子,SurfaceVIEw部分與球類稍作改動,這裡就不在贅述。主要介紹一下如何在View中成功的把SurfaceView添加進來,並且通過widget中默認的控件來操作自定義的SurfaceVIEw。
View中添加SurfaceVIEw
還記得我上一節中的SurfaceView類BallSurfaceVIEw的構造方法麼?BallSurfaceView(Context context)沒錯就是這個,但是如果我們要在vIEw中添加,還是用這個構造方法就會報錯。感謝mars老師的android群,裡面的大蝦們幫我解決了這個問題。
其實只要使用如下構造方法,然後注意幾點就ok了。
Java代碼
1. public BallSurfaceVIEw(Context context, AttributeSet attrs) {
2. super(context,attrs);
3. …..
public BallSurfaceVIEw(Context context, AttributeSet attrs) {
super(context,attrs);
…..
就是上面的構造方法,是符合vIEw的。AttributeSet是提供一些設置的類,可以參考API。
但是值得注意的是,不要再SurfaceView中去綁定VIEw,這樣會帶來意想不到的錯誤。
實現
我將把代碼全部貼出,供大家參考。
Java代碼
1. package cn.edu.heut.zcl;
2.
3. import android.content.Context;
4. import android.graphics.Canvas;
5. import android.graphics.Color;
6. import android.graphics.Paint;
7. import android.util.AttributeSet;
8. import android.util.DisplayMetrics;
9. import android.vIEw.SurfaceHolder;
10. import android.view.SurfaceVIEw;
11.
12. public class BallSurfaceView extends SurfaceVIEw
13. implements SurfaceHolder.Callback{
14. // SportActivity sportActivity ;//調用該SurfaceVIEw的上下文引用
15. private Ball ball ;//小球
16. public static final int initX = 100;
17. public static final int initY = 100;
接上頁
18. SurfaceHolder holder ;
19. public int screenWidth ;
20. public int screenHeight ;
21. public BallSurfaceVIEw(Context context, AttributeSet attrs) {
22. super(context,attrs);
23. ball = new Ball(initX, initY, this);
24. holder = this.getHolder();
25. holder.addCallback(this);
26. //獲得屏幕尺寸
27. DisplayMetrics dm = new DisplayMetrics();
28. dm = context.getApplicationContext().getResources().getDisplayMetrics();
29. screenWidth = dm.widthPixels;
30. screenHeight = dm.heightPixels;
31. }
32.
33. @Override
34. protected void onDraw(Canvas canvas) {
35. super.onDraw(canvas);
36.
37. if(canvas == null) canvas = holder.lockCanvas();//鎖定畫布
38. Paint p = new Paint();
39. int c = p.getColor();
40. p.setColor(Color.WHITE);//設置背景白色
41. if(canvas != null)
42. canvas.drawRect(0, 0, screenWidth, screenHeight, p);
43. p.setColor(c);
44. ball.onDraw(canvas);
45. holder.unlockCanvasAndPost(canvas);//釋放鎖
46. }
47.
48. @Override
49. public void surfaceChanged(SurfaceHolder holder, int format, int width,
50. int height) {
51.
52. }
53.
54. @Override
55. public void surfaceCreated(SurfaceHolder holder) {
56. new RefreshThread().start();
57. }
58.
59. @Override
60. public void surfaceDestroyed(SurfaceHolder holder) {
61.
62. }
63.
64. public void setStop(){
65. ball.setStop(true);
66. }
67. public void setStart(){
68. ball.setStop(false);
69. }
70. public void setRestart(){
接上頁
71. ball.setPosition(initX, initY);
72. ball.setMaxHeight(initY);
73. }
74. private class RefreshThread extends Thread{
75.
76. @Override
77. public void run() {
78.
79. while(true){
80. Canvas canvas = null;
81. try{
82. onDraw(canvas);
83. }catch(Exception e){
84. e.printStackTrace();
85. }
86.
87. try {
88. Thread.sleep(40);
89. } catch (InterruptedException e) {
90. e.printStackTrace();
91. }
92. }
93. }
94.
95. }
96.
97. }
98.
99.
100. package cn.edu.heut.zcl;
101.
102. import android.graphics.Bitmap;
103. import android.graphics.BitmapFactory;
104. import android.graphics.Canvas;
105. import android.graphics.Color;
106. import android.graphics.Paint;
107. import android.util.DisplayMetrics;
108.
109. /**
110. * 球類
111. * @author zcl
112. *
113. */
114. public class Ball {
115.
116. /**
117. * 球的高
118. */
119. public static final int HEIGHT = 93;
120. /**
121. * 球的寬
122. */
123. public static final int WIDTH = 93;
124.
125. private static final int STEPLENGTH = 10;//每次運動的間距
126. private static final float REDUCEPERCENTAGE = 0.35F;//遞減系數
127. private int stepReduce ;//每次反向運動的縮短的距離
128.
129. private boolean stop = false;
130.
131. public void setStop(boolean stop) {
132. this.stop = stop;
133. }
接上頁
134. private float runX ;//球的位置
135. private float runY ;//球的位置
136. private BallSurfaceVIEw bsv ;
137. private boolean upDirection = false;//if true,up direction,or is down direction
138. private float maxHeight ;//當前運動最高的高度
139. private Paint paint ;
140.
141. Bitmap ballBitmap ;//球的圖片
142. public Ball(float initX , float initY , BallSurfaceVIEw bsv){
143. this.runX = initX;
144. this.runY = initY ;
145. maxHeight = initY;
146. this.bsv = bsv;
147. ballBitmap = BitmapFactory.decodeResource(bsv.getResources(), R.drawable.ball);//加載圖片
148. paint = new Paint();
149. }
150.
151. public void onDraw(Canvas canvas) {
152. int c = paint.getColor();//保存顏色,之後還原為之前顏色
153. if( !stop ) boundaryTest();
154. if(canvas != null) canvas.drawBitmap(ballBitmap,runX,runY,paint);
155. paint.setColor(c);
156. if( !stop ) move();
157. }
158. /**
159. * 運動
160. */
161. private void move() {
162. if(maxHeight >= (bsv.screenHeight - HEIGHT)) {
163. return;
164. }
165. if(upDirection){//向上
166. runY = runY + STEPLENGTH ;
167. }else{
168. runY = runY - STEPLENGTH ;
169. }
170. }
171.
172. /**
173. * 邊界檢測,使球不會飛出邊界
174. */
175. private void boundaryTest(){
176.
177. if(runY > bsv.screenHeight - HEIGHT){//向下運動到頭
178. upDirection = !upDirection;//方向置反
179. runY = bsv.screenHeight - HEIGHT;
180. stepReduce = (int) (maxHeight * REDUCEPERCENTAGE);
181. maxHeight = maxHeight + stepReduce ;//最大高度遞減
接上頁
182.
183. }
184. if(runY < maxHeight ){//向上運動到頭
185. upDirection = !upDirection;//方向置反
186. if(maxHeight >= (bsv.screenHeight - HEIGHT)) return;
187. runY = maxHeight ;
188.
189. }
190. }
191. public void setPosition(float x,float y){
192. this.runX = x;
193. this.runY = y;
194. }
195. public void setMaxHeight(float y){
196. this.maxHeight = y;
197. }
198. }
199.
200.
201. package cn.edu.heut.zcl;
202.
203. import android.app.Activity;
204. import android.content.pm.ActivityInfo;
205. import android.os.Bundle;
206. import android.util.DisplayMetrics;
207. import android.view.VIEw;
208. import android.vIEw.Window;
209. import android.vIEw.WindowManager;
210. import android.widget.Button;
211.
212. public class SportActivity extends Activity {
213.
214. Button butStop;
215. Button butStart;
216. Button butRestart;
217.
218. BallSurfaceVIEw bsv ;
219. /** Called when the activity is first created. */
220. @Override
221. public void onCreate(Bundle savedInstanceState) {
222. super.onCreate(savedInstanceState);
223. // bsv = new BallSurfaceVIEw(this);
224. //下兩句為設置全屏
225. requestWindowFeature(Window.FEATURE_NO_TITLE);
226. getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN ,
227. WindowManager.LayoutParams.FLAG_FULLSCREEN);
228.
229. setContentVIEw(R.layout.main);
230. butStop =(Button)findVIEwById(R.id.butStop);
231. butStop.setOnClickListener(new listener());
接上頁
232. butStart =(Button)findVIEwById(R.id.butStart);
233. butStart.setOnClickListener(new listener());
234. butRestart =(Button)findVIEwById(R.id.butRestart);
235. butRestart.setOnClickListener(new listener());
236. bsv = (BallSurfaceView) findViewById(R.id.ballSurfaceVIEw);
237. }
238. class listener implements VIEw.OnClickListener{
239.
240. @Override
241. public void onClick(VIEw v) {
242. Button but = (Button)v;
243. switch(but.getId()){
244. case R.id.butStop:
245. bsv.setStop();
246. break;
247. case R.id.butStart:
248. bsv.setStart();
249. break;
250. case R.id.butRestart:
251. bsv.setRestart();
252. break;
253. }
254.
255. }
256.
257. }
258.
259. }
260.
261.
262. < ?XML version="1.0" encoding="utf-8"?>
263. < LinearLayout XMLns:android="http://schemas.android.com/apk/res/android"
264. android:orIEntation="vertical"
265. android:layout_width="fill_parent"
266. android:layout_height="fill_parent"
267. >
268. < LinearLayout
269. android:orIEntation="horizontal"
270. android:layout_width="fill_parent"
271. android:layout_height="wrap_content"
272. >
273. < Button android:id="@+id/butStop"
274. android:text="stop"
275. android:layout_height="wrap_content"
276. android:layout_width="wrap_content"
277. >
278. < /Button>
279. < Button android:id="@+id/butStart"
280. android:text="Start"
281. android:layout_height="wrap_content"
282. android:layout_width="wrap_content"
接上頁
283. >
284. < /Button>
285. < Button android:id="@+id/butRestart"
286. android:text="ReStart"
287. android:layout_height="wrap_content"
288. android:layout_width="wrap_content"
289. >
290. < /Button>
291. < /LinearLayout>
292. < FrameLayout
293. android:layout_width="fill_parent"
294. android:layout_height="wrap_content">
295. < cn.edu.heut.zcl.BallSurfaceVIEw
296. android:id="@+id/ballSurfaceVIEw"
297. android:layout_width="fill_parent"
298. android:layout_height="fill_parent">
299. < /cn.edu.heut.zcl.BallSurfaceVIEw>
300. < /FrameLayout>
301. < /LinearLayout>
package cn.edu.heut.zcl;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.vIEw.SurfaceHolder;
import android.view.SurfaceVIEw;
public class BallSurfaceView extends SurfaceVIEw
implements SurfaceHolder.Callback{
// SportActivity sportActivity ;//調用該SurfaceVIEw的上下文引用
private Ball ball ;//小球
public static final int initX = 100;
public static final int initY = 100;
SurfaceHolder holder ;
public int screenWidth ;
public int screenHeight ;
public BallSurfaceVIEw(Context context, AttributeSet attrs) {
super(context,attrs);
ball = new Ball(initX, initY, this);
holder = this.getHolder();
holder.addCallback(this);
//獲得屏幕尺寸
DisplayMetrics dm = new DisplayMetrics();
dm =
接上頁
context.getApplicationContext().getResources().getDisplayMetrics();screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(canvas == null) canvas = holder.lockCanvas();//鎖定畫布
Paint p = new Paint();
int c = p.getColor();
p.setColor(Color.WHITE);//設置背景白色
if(canvas != null)
canvas.drawRect(0, 0, screenWidth, screenHeight, p);
p.setColor(c);
ball.onDraw(canvas);
holder.unlockCanvasAndPost(canvas);//釋放鎖
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
new RefreshThread().start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void setStop(){
ball.setStop(true);
}
public void setStart(){
ball.setStop(false);
}
public void setRestart(){
ball.setPosition(initX, initY);
ball.setMaxHeight(initY);
}
private class RefreshThread extends Thread{
@Override
public void run() {
while(true){
Canvas canvas = null;
try{
onDraw(canvas);
}catch(Exception e){
e.printStackTrace();
}
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
package cn.edu.heut.zcl;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
接上頁
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.DisplayMetrics;
/**
* 球類
* @author zcl
*
*/
public class Ball {
/**
* 球的高
*/
public static final int HEIGHT = 93;
/**
* 球的寬
*/
public static final int WIDTH = 93;
private static final int STEPLENGTH = 10;//每次運動的間距
private static final float REDUCEPERCENTAGE = 0.35F;//遞減系數
private int stepReduce ;//每次反向運動的縮短的距離
private boolean stop = false;
public void setStop(boolean stop) {
this.stop = stop;
}
private float runX ;//球的位置
private float runY ;//球的位置
private BallSurfaceVIEw bsv ;
private boolean upDirection = false;//if true,up direction,or is down direction
private float maxHeight ;//當前運動最高的高度
private Paint paint ;
Bitmap ballBitmap ;//球的圖片
public Ball(float initX , float initY , BallSurfaceVIEw bsv){
this.runX = initX;
this.runY = initY ;
maxHeight = initY;
this.bsv = bsv;
ballBitmap = BitmapFactory.decodeResource(bsv.getResources(), R.drawable.ball);//加載圖片
paint = new Paint();
}
public void onDraw(Canvas canvas) {
int c = paint.getColor();//保存顏色,之後還原為之前顏色
if( !stop ) boundaryTest();
if(canvas != null) canvas.drawBitmap(ballBitmap,runX,runY,paint);
paint.setColor(c);
if( !stop ) move();
}
/**
* 運動
*/
private void move() {
if(maxHeight >= (bsv.screenHeight - HEIGHT)) {
接上頁
return;
}
if(upDirection){//向上
runY = runY + STEPLENGTH ;
}else{
runY = runY - STEPLENGTH ;
}
}
/**
* 邊界檢測,使球不會飛出邊界
*/
private void boundaryTest(){
if(runY > bsv.screenHeight - HEIGHT){//向下運動到頭
upDirection = !upDirection;//方向置反
runY = bsv.screenHeight - HEIGHT;
stepReduce = (int) (maxHeight * REDUCEPERCENTAGE);
maxHeight = maxHeight + stepReduce ;//最大高度遞減
}
if(runY < maxHeight ){//向上運動到頭
upDirection = !upDirection;//方向置反
if(maxHeight >= (bsv.screenHeight - HEIGHT)) return;
runY = maxHeight ;
}
}
public void setPosition(float x,float y){
this.runX = x;
this.runY = y;
}
public void setMaxHeight(float y){
this.maxHeight = y;
}
}
package cn.edu.heut.zcl;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.VIEw;
import android.vIEw.Window;
import android.vIEw.WindowManager;
import android.widget.Button;
public class SportActivity extends Activity {
Button butStop;
Button butStart;
Button butRestart;
BallSurfaceVIEw bsv ;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// bsv = new BallSurfaceVIEw(this);
//下兩句為設置全屏
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN ,
接上頁
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentVIEw(R.layout.main);
butStop =(Button)findVIEwById(R.id.butStop);
butStop.setOnClickListener(new listener());
butStart =(Button)findVIEwById(R.id.butStart);
butStart.setOnClickListener(new listener());
butRestart =(Button)findVIEwById(R.id.butRestart);
butRestart.setOnClickListener(new listener());
bsv = (BallSurfaceView) findViewById(R.id.ballSurfaceVIEw);
}
class listener implements VIEw.OnClickListener{
@Override
public void onClick(VIEw v) {
Button but = (Button)v;
switch(but.getId()){
case R.id.butStop:
bsv.setStop();
break;
case R.id.butStart:
bsv.setStart();
break;
case R.id.butRestart:
bsv.setRestart();
break;
}
}
}
}
< ?XML version="1.0" encoding="utf-8"?>
< LinearLayout XMLns:android="http://schemas.android.com/apk/res/android"
android:orIEntation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
< LinearLayout
android:orIEntation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
< Button android:id="@+id/butStop"
android:text="stop"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
>
< /Button>
< Button android:id="@+id/butStart"
android:text="Start"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
>
< /Button>
< Button android:id="@+id/butRestart"
接上頁
android:text="ReStart"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
>
< /Button>
< /LinearLayout>
< FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
< cn.edu.heut.zcl.BallSurfaceVIEw
android:id="@+id/ballSurfaceVIEw"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
< /cn.edu.heut.zcl.BallSurfaceVIEw>
< /FrameLayout>
< /LinearLayout>
有問題的留言,籃球運動是直接修改的上一節的例子,需要代碼的留下郵箱。