android 之 SurfaceView使用(桌面弹球)

来源:互联网 发布:linux 修改权限 chmod 编辑:程序博客网 时间:2024/05/16 14:13

整个项目一共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
packagecom.example.sl.desktoppinball;
/**
 * 动画中用到的常量
 * @author songliang
 *
 */
publicclassMyConstant {
    publicstaticintSCREENWIDTH=320//屏幕宽//580*320
    publicstaticintSCREENHEIGHT=490;//屏幕高
    publicstaticintPICWIDTH=64;     //图片宽
    publicstaticintPICHEIGHT=64;    //图片高
    publicstaticfloatPICXSPEED=4.5f;//图片水平移动速度
    publicstaticfloatPICYSPEED=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
packagecom.example.sl.desktoppinball;
 
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.view.Window;
importandroid.view.WindowManager;
 
publicclassMainActivityextendsActivity {
 
    privateMySurfaceView sfv = null;
 
    @Override
    protectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sfv = newMySurfaceView(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
packagecom.example.sl.desktoppinball;
 
importcom.example.sl.deskball.R;
 
importandroid.content.Context;
importandroid.graphics.Bitmap;
importandroid.graphics.BitmapFactory;
importandroid.graphics.Canvas;
importandroid.graphics.Paint;
importandroid.view.SurfaceHolder;
importandroid.view.SurfaceView;
 
publicclassMySurfaceViewextendsSurfaceViewimplements
        SurfaceHolder.Callback, Runnable {
    privateSurfaceHolder sh;
    privateMainActivity ma;
    privatefloat[][] d = newfloat[2][2];// 用于记录小球一次位移的起始坐标
    privateCanvas cv;
    privatePaint paint;// 画笔
    privatefloatpicX = 0;// 图片x坐标
    privatefloatpicY = 0;// 图片y坐标
    privateBoolean compX = null;// 判断起始坐标x的大小
    privateBoolean compY = null;// 判断起始坐标y的大小
    privateintflag = 0;// 标记,用于控制显示不同的小球
    intflag2 = 0;// 标记,用于控制小球的运动方向
    privateBoolean isRunning = true;// 判断线程是否正在运行
 
    publicMySurfaceView(Context context) {
        super(context);
        ma = (MainActivity) context;
        sh = this.getHolder();
        sh.addCallback(this);
        paint = newPaint();
    }
 
    publicfloatgetPicX() {
        returnpicX;
    }
 
    publicvoidsetPicX(floatpicX) {
        this.picX = picX;
    }
 
    publicfloatgetPicY() {
        returnpicY;
    }
 
    publicvoidsetPicY(floatpicY) {
        this.picY = picY;
    }
 
    publicvoidsetFlag(intflag) {
        this.flag = flag;
    }
 
    // 用于绘制图像,图形等
    publicvoiddoDrawView() {
        if(sh != null) {
            cv = sh.lockCanvas();// 锁定画布
            if(cv != null) {
                Bitmap bitmapBackGround = null;
                Bitmap bitmapDuke = null;
                switch(flag) {// 根据flag的值绘制不同的图片(此处为不同颜色的小球)
                case1:
                    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;
                case2:
                    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;
                case3:
                    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
    publicvoidsurfaceChanged(SurfaceHolder arg0, intarg1,intarg2,intarg3) {
 
    }
 
    @Override
    publicvoidsurfaceCreated(SurfaceHolder arg0) {
        // 当surfaceView创建完成后启动画图线程
        newThread(this).start();
 
    }
 
    @Override
    publicvoidsurfaceDestroyed(SurfaceHolder arg0) {
        isRunning = false;
        try{
            Thread.sleep(300);
        }catch(InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
 
    // 记录前后两次位移的坐标
    privatevoidstorageXY(floatx,floaty) {
        d[0][0] = d[1][0];
        d[0][1] = d[1][1];
        d[1][0] = x;
        d[1][1] = y;
    }
 
    // 比较前后坐标x,y的大小,用以确定小球当前运动的方向
    privatevoidcompXY() {
 
        if((d[1][0] - d[0][0]) > 0) {
            compX = true;
        }elseif((d[1][0] - d[0][0]) < 0)
            compX = false;
        if((d[1][1] - d[0][1]) > 0) {
            compY = true;
        }elseif((d[1][1] - d[0][1]) < 0)
            compY = false;
 
    }
 
    // 画图线程
    @Override
    publicvoidrun() {
        while(isRunning) {
            while(true) {
                flag2 = 1;// 小球移动方向:1-->右上,2-->右下,3-->左上,4-->左下
                intflag1 = 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) {
                    case1:// 右上
                        picY = picY - MyConstant.PICYSPEED;
                        picX = picX + MyConstant.PICXSPEED;
                        flag1 = 1;
                        break;
                    case2:// 右下
                        picY = picY + MyConstant.PICYSPEED;
                        picX = picX + MyConstant.PICXSPEED;
                        flag1 = 2;
                        break;
                    case3:// 左上
                        picY = picY - MyConstant.PICYSPEED;
                        picX = picX - MyConstant.PICXSPEED;
                        flag1 = 3;
                        break;
                    case4:// 左下
                        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