移动和旋转 //OnTouchListener接口的函数
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i(getClass().getName(), "onTouch-----" + getActionName(event.getAction()));
gestureDetector.onTouchEvent(event);
Button eventBtn;
Class aClass = v.getClass();
if (v instanceof Button) {
eventBtn = (Button) v;
} else {
return true;
}
Point pos = getRowAndColumn(eventBtn);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
break;
}
case MotionEvent.ACTION_MOVE: {
//往左挪动 或者往左旋转
if (isMoveToLeft(event)) {
if (isFillEntireRow(pos.x)) {
isLeftRotation = true;
rotationRow(event, eventBtn);
} else {
moveLeft(eventBtn);
}
break;
}
//往右挪动 或者 往右旋转
if (isMoveToRight(event)) {
if(isFillEntireRow(pos.x)) {
isRightRotation = true;
rotationRow(event, eventBtn);
}
else {
moveRight(eventBtn);
}
break;
}
//往上挪动
if (isMoveToTop(event) && getTopBlankRow(pos)!=-1 && isRightRotation ==false && isLeftRotation==false) {
moveTop(eventBtn);
break;
}
//往下挪动
if (isMoveToDown(event) && getDownBlankRow(pos)!=-1 && isRightRotation ==false && isLeftRotation==false) {
moveDown(eventBtn);
break;
}
//Import: 如果去掉break,移动的时候出界的card不用等到ACTION_UP事件也会自动排列
//因为没有break 后面会接着执行,switch条件只判断一次,如果有break那么会在ACTION_UP事件时
//触发自动排列
// break;
}
case MotionEvent.ACTION_UP: {
//获取手指弹起时控件的位置
if (isFillEntireRow(pos.x) && (isRightRotation || isLeftRotation)) {
//使btn的位置是ctrlWidth的倍数
HashMap<Button, Point> map = adjustButtonLayoutAfterRotation(eventBtn);
if(map == null)
break;
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
Button key = (Button) entry.getKey();
Point value = (Point) entry.getValue();
grid[value.x][value.y] = key;
}
break;
}
break;
}
}
return true;
}
private boolean isMoveToLeft(MotionEvent event) {
return event.getX() < LEFT_LIMIT && Math.abs(event.getX()) > Math.abs(event.getY());
}
//移到左边空位
//pos:button现在的位置
private void moveLeft(Button btn) {
Point pos = getRowAndColumn(btn);
int blankCol=getLeftBlankColumn(pos);
if(blankCol == -1)
return;
for(int i=blankCol+1;i<=pos.y;i++) {
Button button = grid[pos.x][i];
int x = (i- 1) * layoutXUnit;
int y = pos.x * layoutYUnit;
AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(ctrlWidth, ctrlHeight, x, y);
button.setLayoutParams(params);
grid[pos.x][i- 1] = button;
}
grid[pos.x][pos.y] = null;
}
private boolean isMoveToRight(MotionEvent event) {
return event.getX() > RIGHT_LIMIT && Math.abs(event.getX()) > Math.abs(event.getY());
}
//移到右边空位
//pos:button现在的位置
private void moveRight(Button btn) {
Point pos = getRowAndColumn(btn);
int blankCol= getRightBlankColumn(pos);
if(blankCol == -1)
return;
for(int i=blankCol-1;i>=pos.y;i--) {
Button button = grid[pos.x][i];
int x = (i+1) * layoutXUnit;
int y = pos.x * layoutYUnit;
AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(ctrlWidth, ctrlHeight, x, y);
button.setLayoutParams(params);
grid[pos.x][i + 1] = button;
}
grid[pos.x][pos.y] = null;
}
private int getLeftBlankColumn(Point pos)
{
for(int i=0;i<pos.y;i++)
{
if(grid[pos.x][i] == null)
return i;
}
return -1;
}
private int getRightBlankColumn(Point pos)
{
for(int i=pos.y;i< COL;i++)
{
if(grid[pos.x][i] == null)
return i;
}
return -1;
}
private int getTopBlankRow(Point pos)
{
for(int i=0;i<pos.x;i++)
{
if(grid[i][pos.y] == null)
return i;
}
return -1;
}
private int getDownBlankRow(Point pos)
{
for(int i=pos.x;i< ROW;i++)
{
if(grid[i][pos.y] == null)
return i;
}
return -1;
}
private boolean isMoveToTop(MotionEvent event) {
return event.getY() < TOP_LIMIT && Math.abs(event.getY()) > Math.abs(event.getX());
}
//移到上边空位
//pos:button现在的位置
private void moveTop(Button btn) {
Point pos = getRowAndColumn(btn);
int blankRow = getTopBlankRow(pos);
if(blankRow == -1)
return;
for(int i=blankRow+1;i<=pos.x;i++) {
Button button=grid[i][pos.y];
int x = pos.y * layoutXUnit;
int y = (i-1) * layoutYUnit;
AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(ctrlWidth, ctrlHeight, x, y);
button.setLayoutParams(params);
grid[i-1][pos.y] = button;
}
grid[pos.x][pos.y] = null;
}
private boolean isMoveToDown(MotionEvent event) {
return event.getY() > DOWN_LIMIT && Math.abs(event.getY()) > Math.abs(event.getX());
}
//移到下边空位
//pos:button现在的位置
private void moveDown(Button btn){
Point pos = getRowAndColumn(btn);
int rowBlank = getDownBlankRow(pos);
for(int i=rowBlank-1;i>=pos.x;i--) {
Button button=grid[i][pos.y];
int x = pos.y * layoutXUnit;
int y = (i + 1) * layoutYUnit;
AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(ctrlWidth, ctrlHeight, x, y);
button.setLayoutParams(params);
grid[i+1][pos.y] = button;
}
grid[pos.x][pos.y] = null;
}
private boolean isBlank(int x, int y) {
if (x >= ROW || y >= COL || x < 0 || y < 0) {
return false;
}
return grid[x][y] == null;
}
//设置一个按钮的位置,x表示行,y表示列
private void addButtonLayout(Button button, int x, int y){
AbsoluteLayout.LayoutParams layoutParams = new AbsoluteLayout.LayoutParams(ctrlWidth, ctrlHeight, y * layoutXUnit, x * layoutYUnit);
absoluteLayout.addView(button, layoutParams);
grid[x][y]=button;
}
//该行是否有空位
private boolean isFillEntireRow(int row){
for(int j=0;j< COL;j++)
{
if(grid[row][j] == null)
return false;
}
return true;
}
//手指抬起时,确保按钮所在的位置是ctrlWidth的倍数
//btn:事件作用的按钮
private HashMap<Button, Point> adjustButtonLayoutAfterRotation(Button eventButton) {
//pos:按钮的横坐标和纵坐标
Point pos=getRowAndColumn(eventButton);
HashMap<Button, Point> map = new HashMap<Button, Point>();
//本行中每一列的按钮都要重设位置
for (int j = 0; j < COL; j++) {
Button eachButton = grid[pos.x][j];
if (eachButton == null)
continue;
Point point = new Point();
if (isRightRotation) {
point = getRowAndColumn(eachButton);
}
if (isLeftRotation) {
point = getRowAndColumnForLeftRotation(eachButton);
}
//对纵坐标小于大于col的情况进行处理
point.y = point.y < 0 ? point.y + COL : point.y;
point.y = point.y % COL;
int x = point.y * layoutXUnit;
int y = point.x * layoutYUnit;
map.put(eachButton, new Point(point.x, point.y));
Log.e(eachButton.getText() + ": After adjust Y:" + Integer.toString(y) + " X:" + Integer.toString(x), " Row:" + Integer.toString(point.x) + " Column:" + Integer.toString(point.y));
AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(ctrlWidth, ctrlHeight, x, y);
eachButton.setLayoutParams(params);
}
isLeftRotation = false;
isRightRotation =false;
return map;
}
//button:事件作用于的button
private void rotationRow(MotionEvent event, Button button) {
Point pos = getRowAndColumn(button);
for (int j = 0; j < COL; j++) {
Button btn = grid[pos.x][j];
if (btn == null) {
continue;
}
btn.offsetLeftAndRight((int) event.getX());
}
}
//往左旋转时,取right的位置 判定card应在哪个单元格
private Point getRowAndColumnForLeftRotation(View view) {
//取card的右上角坐标
int x, y;
x = view.getRight();
y = view.getTop();
Point point = new Point();
point.x = y / layoutYUnit;
point.y = x / layoutXUnit;
if (x % layoutXUnit == 0 || x < 0) {
point.y--;
}
return point;
}
//判断控件在第几行,第几列
private Point getRowAndColumn(Button view) {
int x = view.getLeft();
int y = view.getTop();
Point point = new Point();
point.x = y / layoutYUnit;
point.y = x / layoutXUnit;
return point;
}