导读:初学乍练,欢迎多多指教。

本例是一个拖动小球的游戏(坑爹,给Baby玩的吧。。),主要是用到Android2D绘图技术、自定义组件技术。
话不多说,先上图:
1. 窗口在拖动小球之后会变为当前的Touch坐标
2. 当手选中小球(有点难选中,球有点儿小),手机会震动(必须是真机才有震动),50ms。
3. 小球会随着手的移动而移动。
4. 不加代码控制的话,小球可以自Right、Bottom两个方向移出视图,那个时候你就看不到了。不过本例子中加入了代码,是不能移出边界的。
5. 例子比较简单,功能也很单一,需要改进。欢迎安油门提出更好的实现方案。
实现思路:
1. 自定义一个BallView类,主要有一个成员变量HashSet
2. BallView实现OnTouchListener,能监听Touch事件。
3. 将实现好的BallView类加入MainActivity,运行即可见到如图效果。
代码:
package ryan.entity; import android.util.Log; /** * @author Ryan Hoo * @date: 2012/3/11 * */ public class Ball { public int id;// 唯一标示 public float x;// 横坐标 public float y;// 纵坐标 public int drawableId; public Ball(float x, float y, int drawableId) { this.x = x; this.y = y; this.drawableId = drawableId; id = this.hashCode(); Log.d("ball init", "id:" + id + " x:" + x + " y:" + y + " drawableId:" + drawableId); } }
package ryan.view;
import java.util.HashSet; import java.util.Iterator; import ryan.activity.R; import ryan.entity.Ball; import android.app.Activity; import android.app.Service; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.os.Vibrator; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; public class BallView extends View implements OnTouchListener { // 一个HashSet(无法重复元素),存放要用来添加的小球 private HashSetpackage ryan.activity;basket; // 上下文对象,即将要使用此视图的对象 private Context context; private float mX; private float mY; private Ball drag; public BallView(Context context) { super(context); this.context = context; basket = new HashSet (); setOnTouchListener(this); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 绘制logo canvas.drawBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.title), 0, 0, null); for (Iterator it = basket.iterator(); it.hasNext();) { Ball ball = it.next(); // 解码成Bitmap Bitmap bitmap = BitmapFactory.decodeResource( context.getResources(), ball.drawableId); // 图片50*50 canvas.drawBitmap(bitmap, ball.x, ball.y, null); } } @Override public boolean onTouch(View v, MotionEvent event) { mX = event.getX(); mY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 若为按下鼠标,判断拖拽点在哪个球的上面 getDragBall(mX, mY); break; case MotionEvent.ACTION_MOVE: // 如果超出了界限的话,不进行下面的操作 if (mX >= (getWidth() - 50) || mY >= (getHeight() - 50)) { break; } // 设置被拖动球的位置 if (drag != null) { drag.x = mX; drag.y = mY; } // 重绘 break; case MotionEvent.ACTION_UP: // 不在按下状态时,清空drag对象 drag = null; break; } invalidate(); ((Activity) context).setTitle("DragTheBall:x:" + (float) (Math.round(mX * 100)) / 100 + " y:" + (float) (Math.round(mY * 100)) / 100); return true; } public boolean addComponent(Ball ball) { // true when this HashSet did not already contain the object, false // otherwise return basket.add(ball); } public void getDragBall(float x, float y) { for (Iterator it = basket.iterator(); it.hasNext();) { Ball ball = it.next(); // 如果拖拽点在球的区域内,返回该球 if (x > ball.x && y > ball.y && x < (ball.x + 50) && y < (ball.y + 50)) { this.drag = ball; // 震动提示用户已经触摸到球 try { Vibrator vibrator = (Vibrator) context .getApplicationContext().getSystemService( Service.VIBRATOR_SERVICE); //vibrator.vibrate(new long[] { 100, 10, 100, 1000 }, -1); vibrator.vibrate(50); } catch (Exception e) { System.err.println(e); } } } } }
import ryan.entity.Ball; import ryan.view.BallView; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.ViewGroup.LayoutParams; import android.widget.Toast; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { /*requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);*/ BallView view = new BallView(this); view.setBackgroundDrawable(getResources().getDrawable(R.drawable.back)); view.addComponent(new Ball(0, 10, R.drawable.ball_blue)); view.addComponent(new Ball(80, 10, R.drawable.bol_geel)); view.addComponent(new Ball(160, 10, R.drawable.bol_groen)); view.addComponent(new Ball(240, 10, R.drawable.bol_rood)); super.onCreate(savedInstanceState); setContentView(view, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); int width = getWindowManager().getDefaultDisplay().getWidth(); int height = getWindowManager().getDefaultDisplay().getHeight(); Toast.makeText(this, "width:" + width + "\nheight:" + height, Toast.LENGTH_SHORT).show(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu); return true; } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { if(item.getItemId() == R.id.exit) finish(); return super.onMenuItemSelected(featureId, item); } }源码下载地址
http://download.csdn.net/detail/floodingfire/4131227