android 之 SurfaceView使用(桌面弹球)

整个项目一共3个类:MyConstant,MainActivity,MySurfaceView

效果如下:


注意; 由于手机屏幕分辨的差异,在运行程序时应把AndroidManifest.xml中的

?
1
2
3
<uses-sdk
         android:minSdkVersion= "8"
         android:targetSdkVersion= "18" />

删掉

1,MyConstant 用于存放动画中所用的常量

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.sl.desktoppinball;
/**
  * 动画中用到的常量
  * @author songliang
  *
  */
public class MyConstant {
     public static int SCREENWIDTH= 320 //屏幕宽//580*320
     public static int SCREENHEIGHT= 490 ; //屏幕高
     public static int PICWIDTH= 64 ;      //图片宽
     public static int PICHEIGHT= 64 ;     //图片高
     public static float PICXSPEED= 4 .5f; //图片水平移动速度
     public static float PICYSPEED= 2 ;    //图片垂直移动速度
}
2,MainActivity 显示SurfaceView
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.example.sl.desktoppinball;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
 
public class MainActivity extends Activity {
 
     private MySurfaceView sfv = null ;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         sfv = new MySurfaceView(MainActivity. this );
         requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置屏幕显示没有title栏
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                 WindowManager.LayoutParams.FLAG_FULLSCREEN); // 设置全屏
         setContentView(sfv);
     }
 
}

3, MySurfaceView                                                      

?
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
package com.example.sl.desktoppinball;
 
import com.example.sl.deskball.R;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
 
public class MySurfaceView extends SurfaceView implements
         SurfaceHolder.Callback, Runnable {
     private SurfaceHolder sh;
     private MainActivity ma;
     private float [][] d = new float [ 2 ][ 2 ]; // 用于记录小球一次位移的起始坐标
     private Canvas cv;
     private Paint paint; // 画笔
     private float picX = 0 ; // 图片x坐标
     private float picY = 0 ; // 图片y坐标
     private Boolean compX = null ; // 判断起始坐标x的大小
     private Boolean compY = null ; // 判断起始坐标y的大小
     private int flag = 0 ; // 标记,用于控制显示不同的小球
     int flag2 = 0 ; // 标记,用于控制小球的运动方向
     private Boolean isRunning = true ; // 判断线程是否正在运行
 
     public MySurfaceView(Context context) {
         super (context);
         ma = (MainActivity) context;
         sh = this .getHolder();
         sh.addCallback( this );
         paint = new Paint();
     }
 
     public float getPicX() {
         return picX;
     }
 
     public void setPicX( float picX) {
         this .picX = picX;
     }
 
     public float getPicY() {
         return picY;
     }
 
     public void setPicY( float picY) {
         this .picY = picY;
     }
 
     public void setFlag( int flag) {
         this .flag = flag;
     }
 
     // 用于绘制图像,图形等
     public void doDrawView() {
         if (sh != null ) {
             cv = sh.lockCanvas(); // 锁定画布
             if (cv != null ) {
                 Bitmap bitmapBackGround = null ;
                 Bitmap bitmapDuke = null ;
                 switch (flag) { // 根据flag的值绘制不同的图片(此处为不同颜色的小球)
                 case 1 :
                     bitmapBackGround = BitmapFactory.decodeResource(
                             ma.getResources(), R.drawable.fp_1);
                     cv.drawBitmap(bitmapBackGround, 0 , 0 , paint);
 
                     bitmapDuke = BitmapFactory.decodeResource(
                             ma.getResources(), R.drawable.w1);
                     cv.drawBitmap(bitmapDuke, picX, picY, paint);
                     break ;
                 case 2 :
                     bitmapBackGround = BitmapFactory.decodeResource(
                             ma.getResources(), R.drawable.fp_2);
                     cv.drawBitmap(bitmapBackGround, 0 , 0 , paint);
 
                     bitmapDuke = BitmapFactory.decodeResource(
                             ma.getResources(), R.drawable.w2);
                     cv.drawBitmap(bitmapDuke, picX, picY, paint);
                     break ;
                 case 3 :
                     bitmapBackGround = BitmapFactory.decodeResource(
                             ma.getResources(), R.drawable.fp_3);
                     cv.drawBitmap(bitmapBackGround, 0 , 0 , paint);
 
                     bitmapDuke = BitmapFactory.decodeResource(
                             ma.getResources(), R.drawable.w3);
                     cv.drawBitmap(bitmapDuke, picX, picY, paint);
                     break ;
                 default :
                     bitmapBackGround = BitmapFactory.decodeResource(
                             ma.getResources(), R.drawable.fp_2);
                     cv.drawBitmap(bitmapBackGround, 0 , 0 , paint);
 
                     bitmapDuke = BitmapFactory.decodeResource(
                             ma.getResources(), R.drawable.w4);
                     cv.drawBitmap(bitmapDuke, picX, picY, paint);
                     break ;
                 }
                 sh.unlockCanvasAndPost(cv);
             }
         }
 
     }
 
     @Override
     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
 
     }
 
     @Override
     public void surfaceCreated(SurfaceHolder arg0) {
         // 当surfaceView创建完成后启动画图线程
         new Thread( this ).start();
 
     }
 
     @Override
     public void surfaceDestroyed(SurfaceHolder arg0) {
         isRunning = false ;
         try {
             Thread.sleep( 300 );
         } catch (InterruptedException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
     }
 
     // 记录前后两次位移的坐标
     private void storageXY( float x, float y) {
         d[ 0 ][ 0 ] = d[ 1 ][ 0 ];
         d[ 0 ][ 1 ] = d[ 1 ][ 1 ];
         d[ 1 ][ 0 ] = x;
         d[ 1 ][ 1 ] = y;
     }
 
     // 比较前后坐标x,y的大小,用以确定小球当前运动的方向
     private void compXY() {
 
         if ((d[ 1 ][ 0 ] - d[ 0 ][ 0 ]) > 0 ) {
             compX = true ;
         } else if ((d[ 1 ][ 0 ] - d[ 0 ][ 0 ]) < 0 )
             compX = false ;
         if ((d[ 1 ][ 1 ] - d[ 0 ][ 1 ]) > 0 ) {
             compY = true ;
         } else if ((d[ 1 ][ 1 ] - d[ 0 ][ 1 ]) < 0 )
             compY = false ;
 
     }
 
     // 画图线程
     @Override
     public void run() {
         while (isRunning) {
             while ( true ) {
                 flag2 = 1 ; // 小球移动方向:1-->右上,2-->右下,3-->左上,4-->左下
                 int flag1 = 0 ; // 控制不同小球的切换
                 picX = 0 ;
                 picY = MyConstant.SCREENHEIGHT - MyConstant.PICHEIGHT;
                 while (flag2 < 5 ) {
                     this .setPicX(picX); // 设置x坐标
                     this .setPicY(picY); // 设置y坐标
                     this .setFlag(flag1); // 设置flag1的值
                     storageXY(picX, picY); // 记录前后两次位移的坐标
                     doDrawView(); // 通过坐标绘制图像
                     switch (flag2) {
                     case 1 : // 右上
                         picY = picY - MyConstant.PICYSPEED;
                         picX = picX + MyConstant.PICXSPEED;
                         flag1 = 1 ;
                         break ;
                     case 2 : // 右下
                         picY = picY + MyConstant.PICYSPEED;
                         picX = picX + MyConstant.PICXSPEED;
                         flag1 = 2 ;
                         break ;
                     case 3 : // 左上
                         picY = picY - MyConstant.PICYSPEED;
                         picX = picX - MyConstant.PICXSPEED;
                         flag1 = 3 ;
                         break ;
                     case 4 : // 左下
                         picY = picY + MyConstant.PICYSPEED;
                         picX = picX - MyConstant.PICXSPEED;
                         flag1 = 4 ;
                         break ;
                     }
                     compXY(); // 比较小球运动过程中其实位置的x,y
                     if (picY <= 0 ) { // 到达屏幕上沿
                         if (compX == true && compY == false ) {
                             flag2 = 2 ;
                         }
                         if (compX == false && compY == false ) {
                             flag2 = 4 ;
                         }
                     }
                     if (picY >= MyConstant.SCREENHEIGHT - MyConstant.PICHEIGHT) { // 到达屏幕下沿
                         if (compX == true && compY == true ) {
                             flag2 = 1 ;
                         }
                         if (compX == false && compY == true ) {
                             flag2 = 3 ;
                         }
                     }
                     if (picX >= MyConstant.SCREENWIDTH - MyConstant.PICWIDTH) { // 到达屏幕右沿
                         if (compX == true && compY == false ) {
                             flag2 = 3 ;
                         }
                         if (compX == true && compY == true ) {
                             flag2 = 4 ;
                         }
                     }
                     if (picX <= 0 ) { // 到达屏幕左沿
                         if (compX == false && compY == false ) {
                             flag2 = 1 ;
                         }
                         if (compX == false && compY == true ) {
                             flag2 = 2 ;
                         }
                     }
 
                 }
             }
         }
     }
 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 AndroidSurfaceView 中实现倒计时功能,您需要创建一个线程,该线程在 SurfaceView 上绘制计时器并更新计时器的值。以下是一个简单的示例,您可以参考: ```java public class CountdownSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private CountdownThread mThread; private int mCountdownValue = 10; // 倒计时的初始值 public CountdownSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); mHolder = getHolder(); mHolder.addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { mThread = new CountdownThread(mHolder, mCountdownValue); mThread.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { boolean retry = true; mThread.setRunning(false); while (retry) { try { mThread.join(); retry = false; } catch (InterruptedException e) { // 重试 } } } private class CountdownThread extends Thread { private SurfaceHolder mThreadHolder; private int mCountdownValue; private boolean mIsRunning = true; public CountdownThread(SurfaceHolder holder, int countdownValue) { mThreadHolder = holder; mCountdownValue = countdownValue; } public void setRunning(boolean isRunning) { mIsRunning = isRunning; } @Override public void run() { while (mIsRunning) { Canvas canvas = null; try { canvas = mThreadHolder.lockCanvas(); synchronized (mThreadHolder) { drawCountdown(canvas); Thread.sleep(1000); // 每秒钟更新一次计时器 mCountdownValue--; if (mCountdownValue == 0) { break; // 计时器结束 } } } catch (InterruptedException e) { // 重试 } finally { if (canvas != null) { mThreadHolder.unlockCanvasAndPost(canvas); } } } } private void drawCountdown(Canvas canvas) { Paint paint = new Paint(); paint.setColor(Color.WHITE); paint.setTextSize(100); canvas.drawColor(Color.BLACK); canvas.drawText(String.valueOf(mCountdownValue), getWidth() / 2, getHeight() / 2, paint); } } } ``` 在这个例子中,我们创建了一个 CountdownSurfaceView 类,它继承自 SurfaceView,并实现了 SurfaceHolder.Callback 接口。在 surfaceCreated() 方法中,我们创建了一个 CountdownThread 线程,并启动该线程。在 CountdownThread 线程中,我们使用 Canvas 绘制计时器,并使用 Thread.sleep() 方法使线程休眠一秒钟。每次线程醒来时,我们更新计时器的值,并检查计时器是否结束。如果计时器结束,我们退出线程。最后,在 surfaceDestroyed() 方法中,我们停止线程并等待线程结束。 请注意,在这个例子中,我们将计时器的值绘制在 SurfaceView 的中心。您可以根据自己的需要更改这个位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值