歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android應用實例之跟隨手指的小球——自定義SurfaceView應用

Android應用實例之跟隨手指的小球——自定義SurfaceView應用

日期:2017/3/1 11:16:18   编辑:Linux編程

實現的功能:手指在屏幕上滑動,變幻顏色的小球始終跟隨手指移動。

實現的思路:1)自定義SurfaceView,在新線程中每間隔0.1秒就調用一次繪圖方法;2)重寫自定義SurfaceView的onTouchEvent方法,記錄觸屏坐標,用新的坐標重新繪制小球。

關鍵技術點:自定義SurfaceView應用、觸摸事件處理、canvas繪圖、Paint應用

第一步:新建一個工程,命名為BallSurfaceViewDemo,Activity命名為BallActivity。

第二步:編寫自定義SurfaceView類BallSurfaceView,本例中將BallSurfaceView作為BallActivity的內部類,BallActivity代碼如下:

  1. package com.zyg.surfaceview.ball;
  2. import java.util.Random;
  3. import Android.app.Activity;
  4. import android.content.Context;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.Paint;
  8. import android.os.Bundle;
  9. import android.view.MotionEvent;
  10. import android.view.SurfaceHolder;
  11. import android.view.SurfaceHolder.Callback;
  12. import android.view.SurfaceView;
  13. import android.view.Window;
  14. import android.view.WindowManager;
  15. public class BallActivity extends Activity {
  16. @Override
  17. public void onCreate(Bundle savedInstanceState) {
  18. super.onCreate(savedInstanceState);
  19. //設置全屏
  20. requestWindowFeature(Window.FEATURE_NO_TITLE);
  21. this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  22. WindowManager.LayoutParams.FLAG_FULLSCREEN);
  23. setContentView(new BallSurfaceView(this));
  24. }
  25. class BallSurfaceView extends SurfaceView implements Callback,Runnable{
  26. private int screenW; //屏幕寬度
  27. private int screenH; //屏幕高度
  28. private Paint paint; //定義畫筆
  29. private float cx = 50; //圓點默認X坐標
  30. private float cy = 50; //圓點默認Y坐標
  31. private int radius = 20;
  32. //定義顏色數組
  33. private int colorArray[] = {Color.BLACK,Color.BLACK,Color.GREEN,Color.YELLOW, Color.RED};
  34. private int paintColor = colorArray[0]; //定義畫筆默認顏色
  35. private Canvas canvas = null; //定義畫布
  36. private Thread th = null; //定義線程
  37. private SurfaceHolder sfh = null;
  38. public BallSurfaceView(Context context){
  39. super(context);
  40. /*備注1:在此處獲取屏幕高、寬值為0,以為此時view還未被���建,
  41. * 在接口Callback的surfaceCreated方法中view才被創建
  42. */
  43. /*screenW = getWidth();
  44. screenH = getHeight();*/
  45. //初始化畫筆
  46. initPaint();
  47. sfh = getHolder();
  48. sfh.addCallback(this);
  49. th = new Thread(this);
  50. }
  51. @Override
  52. public void surfaceCreated(SurfaceHolder holder) {
  53. //獲取屏幕寬度
  54. screenW = getWidth();
  55. //獲取屏幕高度
  56. screenH = getHeight();
  57. //啟動繪圖線程
  58. th.start();
  59. }
  60. private void initPaint(){
  61. paint = new Paint();
  62. //設置消除鋸齒
  63. paint.setAntiAlias(true);
  64. //設置畫筆顏色
  65. paint.setColor(paintColor);
  66. }
  67. @Override
  68. public void run() {
  69. while(true){
  70. try{
  71. myDraw();
  72. Thread.sleep(100);
  73. }catch(InterruptedException e){
  74. e.printStackTrace();
  75. }
  76. }
  77. }
  78. /*備注2:切記,在自定SurfaceView中定義的myDraw方法,自定義View(繼承自View的子類)中的onDraw方法
  79. * 完全是兩碼事:
  80. * 1)自定義View(繼承自View的子類)中的onDraw方法是重寫父類的onDraw方法,在調用postInvalidate後會自動回調該onDraw()方法。
  81. * 2)此處的myDraw方法需要手動調用,所以此處故意將方法命名為myDraw,突出為該方法是自己寫的,非重寫父類的方法 。
  82. *
  83. */
  84. //重寫onDraw方法實現繪圖操作
  85. protected void myDraw() {
  86. //獲取canvas實例
  87. canvas = sfh.lockCanvas();
  88. //將屏幕設置為白色
  89. canvas.drawColor(Color.WHITE);
  90. //修正圓點坐標
  91. revise();
  92. //隨機設置畫筆顏色
  93. setPaintRandomColor();
  94. //繪制小圓作為小球
  95. canvas.drawCircle(cx, cy, radius, paint);
  96. //將畫好的畫布提交
  97. sfh.unlockCanvasAndPost(canvas);
  98. }
  99. //為畫筆設置隨機顏色
  100. private void setPaintRandomColor(){
  101. Random rand = new Random();
  102. int randomIndex = rand.nextInt(colorArray.length);
  103. paint.setColor(colorArray[randomIndex]);
  104. }
  105. //修正圓點坐標
  106. private void revise(){
  107. if(cx <= radius){
  108. cx = radius;
  109. }else if(cx >= (screenW-radius)){
  110. cx = screenW-radius;
  111. }
  112. if(cy <= radius){
  113. cy = radius;
  114. }else if(cy >= (screenH-radius)){
  115. cy = screenH-radius;
  116. }
  117. }
  118. @Override
  119. public boolean onTouchEvent(MotionEvent event) {
  120. switch (event.getAction()) {
  121. case MotionEvent.ACTION_DOWN:
  122. // 按下
  123. cx = (int) event.getX();
  124. cy = (int) event.getY();
  125. break;
  126. case MotionEvent.ACTION_MOVE:
  127. // 移動
  128. cx = (int) event.getX();
  129. cy = (int) event.getY();
  130. break;
  131. case MotionEvent.ACTION_UP:
  132. // 抬起
  133. cx = (int) event.getX();
  134. cy = (int) event.getY();
  135. break;
  136. }
  137. /*
  138. * 備注1:次處一定要將return super.onTouchEvent(event)修改為return true,原因是:
  139. * 1)父類的onTouchEvent(event)方法可能沒有做任何處理,但是返回了false。
  140. * 2)一旦返回false,在該方法中再也不會收到MotionEvent.ACTION_MOVE及MotionEvent.ACTION_UP事件。
  141. */
  142. //return super.onTouchEvent(event);
  143. return true;
  144. }
  145. @Override
  146. public void surfaceChanged(SurfaceHolder holder, int format, int width,
  147. int height) {
  148. }
  149. @Override
  150. public void surfaceDestroyed(SurfaceHolder holder) {
  151. }
  152. }
  153. }
Copyright © Linux教程網 All Rights Reserved