我和你一样,你怎么解决了?在做实训,求教教我
1、onCreate中的所有代码及其子代码执行完成之前,里面设置的所有View是获取不到坐标的。
即:没到运行状态,view.getX()获取不到,结果都是0。(如果debug会发现,在oncreate中,即使走过了代码添加addView(),但此时界面并没有绘制View)
所以要判断,首次运行的时候,可以交换ImageView图片方块的内容,但是不能走动画,因为动画是通过getX()这种方法实现的。
我这边设置的是isAnim变量,首次不加载动画(达到了首次不会执行getX()这个效果)
private boolean isAnim = false;
onCreate(){ //…… //随机打乱顺序,这时onCreate还没有执行完,getX()肯定是0,但是默认isAnim是false,可以直接交换。 isAnim = false;//在整个onCreate最后写,已经过了首次,以后可以执行动画了 }
public void changeDataByImageView(final ImageView mImageView) { if(!isAnim){//不要执行动画,算是首次运行,直接开始交换 ImageViewData data1 = (ImageViewData) mImageView.getTag(); ImageViewData data2 = (ImageViewData) iv_null.getTag(); iv_null.setImageBitmap(data1.imageView); data2.imageView = data1.imageView; data2.p_x = data1.p_x; data2.p_y = data2.p_y; // 设置当前点击的是空方块 setNullImageView(mImageView); return; } //…… }
2、发现一个bug,移动时的效果动画都是从左向右的,需要去掉多余的代码。
====================修改后如下=================
package com.charspan.pintu; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.TranslateAnimation; import android.widget.GridLayout; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends Activity { private int rowsNum = 3; private int colsNum = 5; private boolean isAnim = false; /** * 利用二维数组创建若干个游戏小方块 */ private ImageView[][] iv_game_arr; /** * 当前空方块的实例 */ private ImageView iv_null; /** * 游戏主界面 */ private GridLayout gl_main_game; /** * 当前手势 */ private GestureDetector mDetector; @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub return mDetector.onTouchEvent(event); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDetector = new GestureDetector(this, new OnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public void onShowPress(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 onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub int dir = getDirByGes(e1.getX(), e1.getY(), e2.getX(), e2.getY()); // Toast.makeText(MainActivity.this, "" + dir, // Toast.LENGTH_SHORT).show(); changeByDir(dir); return false; } @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } }); setContentView(R.layout.activity_main); iv_game_arr = new ImageView[rowsNum][colsNum]; // Bitmap bigBm =( // (BitmapDrawable)getResources().getDrawable(R.drawable.pic_1)).getBitmap(); // 获取一张大图 Bitmap bigBm = BitmapFactory.decodeResource(getResources(), R.drawable.pic_1); // 计算每个小方块的宽和高 int tuWandH = bigBm.getWidth() / colsNum; // 初始化游戏小方块 for (int i = 0; i < rowsNum; i++) { for (int j = 0; j < colsNum; j++) { Bitmap bm = Bitmap.createBitmap(bigBm, j * tuWandH, i * tuWandH, tuWandH, tuWandH); iv_game_arr[i][j] = new ImageView(this); iv_game_arr[i][j].setImageBitmap(bm); // 设置方块之间的间距 iv_game_arr[i][j].setPadding(2, 2, 2, 2); // 绑定自定义的数据 iv_game_arr[i][j].setTag(new ImageViewData(i, j, bm)); iv_game_arr[i][j].setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub boolean flag = isNearByNull((ImageView) v); // Toast.makeText(MainActivity.this, "" + flag, // Toast.LENGTH_SHORT).show(); if (flag) { changeDataByImageView((ImageView) v); } } }); } } // 初始化游戏主界面,加载若干个小方块 gl_main_game = (GridLayout) findViewById(R.id.gl_main_game); for (int i = 0; i < rowsNum; i++) { for (int j = 0; j < colsNum; j++) { gl_main_game.addView(iv_game_arr[i][j]); } } // 设置最后一个方块为空 setNullImageView(iv_game_arr[rowsNum - 1][colsNum - 1]); randomMove(); isAnim = true; } /** * 根据手势方向获取与空方块相邻的位置,如果存在方块就进行数据交换 * * @param dir */ public void changeByDir(int dir) { // 获取空方块位置 ImageViewData data = (ImageViewData) iv_null.getTag(); // 根据手势方向,设置相邻位置坐标 int new_x = data.x; int new_y = data.y; if (dir == 1) {// new_x++; } else if (dir == 2) { new_x--; } else if (dir == 3) { new_y++; } else if (dir == 4) { new_y--; } // Toast.makeText(MainActivity.this, // data.x+" :: "+data.y,Toast.LENGTH_SHORT).show(); // 判断新坐标是否存在 if (new_x >= 0 && new_x < rowsNum && new_y >= 0 && new_y < colsNum) { // Toast.makeText(MainActivity.this, // new_x+" : "+new_y,Toast.LENGTH_SHORT).show(); // 存在的话开始移动 changeDataByImageView(iv_game_arr[new_x][new_y]); } } /** * 手势的判断 * * @param sx * @param sy * @param ex * @param ey * @return 上下左右 1 2 3 4 */ public int getDirByGes(float sx, float sy, float ex, float ey) { // 左右:横向距离大于竖直距离 boolean isLeftOrRight = Math.abs(sx - ex) > Math.abs(sy - ey); if (isLeftOrRight) {// 左右 // 左 :终点x小于起点x boolean isLeft = sx > ex; if (isLeft) { return 3; } else { return 4; } } else {// 上下 // 上:终点y大于起点y boolean isUp = sy > ey; if (isUp) { return 1; } else { return 2; } } } // 随机打乱顺序 public void randomMove() { // 打乱次数 for (int i = 0; i < 100; i++) { int dir = (int) (Math.random() * 4) + 1; changeByDir(dir); } // 开始交换,无动画 } /** * 动画结束后,交换两个方块的数据 * * @param mImageView * 点击的方块 */ public void changeDataByImageView(final ImageView mImageView) { if (!isAnim) {// 不要执行动画,算是首次运行,直接开始交换 ImageViewData data1 = (ImageViewData) mImageView.getTag(); ImageViewData data2 = (ImageViewData) iv_null.getTag(); iv_null.setImageBitmap(data1.imageView); data2.imageView = data1.imageView; data2.p_x = data1.p_x; data2.p_y = data2.p_y; // 设置当前点击的是空方块 setNullImageView(mImageView); return; } ImageViewData nullD = (ImageViewData) iv_null.getTag(); ImageViewData mD = (ImageViewData) mImageView.getTag(); // Toast.makeText(MainActivity.this, nullD.x+" :.. "+mD.x, // Toast.LENGTH_SHORT).show(); // Toast.makeText(MainActivity.this, nullD.y+" :.. "+mD.y, // Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, mImageView.getX() + " :.. " + iv_null.getX(), Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, mImageView.getY() + " : " + iv_null.getY(), Toast.LENGTH_SHORT).show(); // 创建一个动画,设置放心,移动距离 TranslateAnimation translateAnimation = null; if (mImageView.getX() > iv_null.getX()) {// 在空方块下面 // 往上移动 translateAnimation = new TranslateAnimation(0.1f, -mImageView.getWidth(), 0.1f, 0.1f); } else if (mImageView.getX() < iv_null.getX()) {// // 下 translateAnimation = new TranslateAnimation(0.1f, mImageView.getWidth(), 0.1f, 0.1f); } else if (mImageView.getY() > iv_null.getY()) {// // 左 translateAnimation = new TranslateAnimation(0.1f, 0.1f, 0.1f, -mImageView.getWidth()); } else if (mImageView.getY() < iv_null.getY()) {// // 右 translateAnimation = new TranslateAnimation(0.1f, 0.1f, 0.1f, mImageView.getWidth()); } // translateAnimation = new TranslateAnimation(0.1f, // mImageView.getWidth(), 0.1f, 0.1f); // 设置动画时长 translateAnimation.setDuration(70); // 设置动画结束后是否停留 translateAnimation.setFillAfter(true); // 动画结束后交换数据对象 translateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mImageView.clearAnimation(); ImageViewData data1 = (ImageViewData) mImageView.getTag(); ImageViewData data2 = (ImageViewData) iv_null.getTag(); iv_null.setImageBitmap(data1.imageView); data2.imageView = data1.imageView; data2.p_x = data1.p_x; data2.p_y = data2.p_y; // 设置当前点击的是空方块 setNullImageView(mImageView); } }); mImageView.startAnimation(translateAnimation); } /** * 设置某个方块为空方块 * * @param imageView * 当前需要设置为空的方块实例 */ public void setNullImageView(ImageView imageView) { imageView.setImageBitmap(null); iv_null = imageView; } /** * 判断点击方块是否和空方块相邻 * * @param imageView * 点击的方块 * @return true:相邻,false:不相邻 */ public boolean isNearByNull(ImageView imageView) { // 点击方块和当前空方块的x或y只差一个单位就是相邻 ImageViewData mNullImageViewData = (ImageViewData) iv_null.getTag(); ImageViewData mImageViewData = (ImageViewData) imageView.getTag(); if (mNullImageViewData.y == mImageViewData.y && mImageViewData.x + 1 == mNullImageViewData.x) {// 点击方块在空方块上面 return true; } else if (mNullImageViewData.y == mImageViewData.y && mImageViewData.x - 1 == mNullImageViewData.x) {// 点击方块在空方块下面 return true; } else if (mNullImageViewData.y == mImageViewData.y + 1 && mImageViewData.x == mNullImageViewData.x) {// 点击方块在空方块左边 return true; } else if (mNullImageViewData.y == mImageViewData.y - 1 && mImageViewData.x == mNullImageViewData.x) {// 点击方块在空方块右边 return true; } return false; } /** * 小方块上绑定的数据 */ class ImageViewData { /** 小方块的原始位置 **/ public int x = 0; public int y = 0; /** 小方块的图片 **/ public Bitmap imageView; /** 小方块的当前位置 **/ public int p_x; public int p_y; public ImageViewData(int x, int y, Bitmap imageView) { super(); this.x = x; this.y = y; this.imageView = imageView; this.p_x = x; this.p_y = y; } } }