今天是尝试開始Android版2048小游戏的第二天。在今天,我主要学习了怎样获取用户在屏幕滑动的手势,以及对布局进行了一些小小的完好。
获取用户操作的手势(比方向左滑。向右滑等)主要用到了GestureDetector。这个类能够帮助我们获取一些常见的用户对屏幕的操作。比如单击、双击、按压、拖动等。详细的使用说明。大家能够查API也能够去百度,或者看我之前有一篇使用GestureDetector实现的小样例(http://blog.csdn.net/xiapinnong/article/details/21970419)在这里就不多说了。
以下还是看代码吧。相对与第一篇,我在代码中主要增加一个内部类MygestureDetector。而且让这个类实现了OnTouchListener和OnGestureListener这两个接口。
当中OnTouchListener这个接口主要用来为我的GridLayout绑定对touch这个动作的监听,然后将详细的动作传递到GestureDetector。通过将用户详细的操作相应到不同的手势上。
public class MygestureDetector implements OnGestureListener,OnTouchListener{ @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub return gd.onTouchEvent(event); } @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // 參数解释: // e1:第1个ACTION_DOWN MotionEvent // e2:最后一个ACTION_MOVE MotionEvent // velocityX:X轴上的移动速度,像素/秒 // velocityY:Y轴上的移动速度。像素/秒 // 触发条件 : // X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒 if(e1.getX()-e2.getX()>100){ System.out.println("向左"); return true; }else if(e1.getX()-e2.getX()<-100){ System.out.println("向右"); return true; }else if(e1.getY()-e2.getY()>100){ System.out.println("向上"); return true; }else if(e1.getY()-e2.getY()<-00){ System.out.println("向下"); return true; } return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } }
onFiling()这个回调函数主要是指用户点击屏幕,并移动一小段距离。然后放开。
这种方法里的四个參数:
e1是指: 第1个ACTION_DOWN MotionEvent
e2是指: 最后一个ACTION_MOVE MotionEvent
velocityX:X轴上的移动速度,像素/秒
velocityY:Y轴上的移动速度。像素/秒
(其他回调函数和參数的说明,能够參考这篇博客http://blog.csdn.net/xiapinnong/article/details/21970419)
推断用户手指滑动的方向:
通过比較e1和e2这两个MotinEvent的坐标来计算的
比方e1的x坐标减去e2的x坐标大于零。说明用户的手指是向左滑动的
然后我们须要声明并初始化一个GestureDetector相应,并传入我们的MygestureDetector的对象,然后为我们的GridLayout绑定onTouchListener
完整的Activity代码例如以下:
package com.example.t2048; import java.util.ArrayList; import java.util.List; import java.util.Random; import android.app.Activity; import android.os.Bundle; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.Menu; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.GridLayout; import android.widget.ImageView; public class MainActivity extends Activity { GridLayout gridLayout = null; //用于保存空格的位置 List<Integer> spaceList = new ArrayList<Integer>(); //用于保存有数字格的位置 List<Integer> stuffList = new ArrayList<Integer>(); GestureDetector gd = null; /** * 图标数组 */ private final int[] icons = { R.drawable.but_empty, R.drawable.but2, R.drawable.but4, R.drawable.but8, R.drawable.but16, R.drawable.but32, R.drawable.but64, R.drawable.but128, R.drawable.but256, R.drawable.but512, R.drawable.but1024, R.drawable.but2048, R.drawable.but4096 }; protected void onCreate(Bundle savedInstanceState) { System.out.println("程序启动"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gridLayout = (GridLayout) findViewById(R.id.GridLayout1); init(); MygestureDetector mg = new MygestureDetector(); gd = new GestureDetector(mg); gridLayout.setOnTouchListener(mg); gridLayout.setLongClickable(true); } //初始化界面 public void init(){ System.out.println("初始化"); //首先在16个各种都填上空白的图片 for(int i=0;i<16;i++){ View view = View.inflate(this, R.layout.item, null); ImageView image = (ImageView) view.findViewById(R.id.image); image.setBackgroundResource(icons[0]); spaceList.add(i); gridLayout.addView(view); } //在界面中随机增加两个2或者4 addRandomItem(); addRandomItem(); } //从空格列表中随机获取位置 public int getRandomIndex(){ Random random = new Random(); if(spaceList.size()>0) return random.nextInt(spaceList.size()); else return -1; } //在空白格中随机增加数字2 public void addRandomItem(){ int index = getRandomIndex(); if(index!=-1){ //获取相应坐标所相应的View View view = gridLayout.getChildAt(spaceList.get(index)); ImageView image = (ImageView) view.findViewById(R.id.image); //随机生成数字1或2 int i = (int) Math.round(Math.random()+1); //将当前格子的图片置换为2或者4 image.setBackgroundResource(icons[i]); //在空白列表中去掉这个格子 spaceList.remove(index); } } public class MygestureDetector implements OnGestureListener,OnTouchListener{ @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub return gd.onTouchEvent(event); } @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // 參数解释: // e1:第1个ACTION_DOWN MotionEvent // e2:最后一个ACTION_MOVE MotionEvent // velocityX:X轴上的移动速度,像素/秒 // velocityY:Y轴上的移动速度。像素/秒 // 触发条件 : // X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒 if(e1.getX()-e2.getX()>100){ System.out.println("向左"); return true; }else if(e1.getX()-e2.getX()<-100){ System.out.println("向右"); return true; }else if(e1.getY()-e2.getY()>100){ System.out.println("向上"); return true; }else if(e1.getY()-e2.getY()<-00){ System.out.println("向下"); return true; } return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } } public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
程序执行界面例如以下(界面比較难看):
用手指在GridLayout上滑动,在Log中能够打印出详细的滑动方向