Ошибка в анимации свойства

Я создаю небольшое приложение для практики в программировании на Android. Это своего рода игра-головоломка, подобная этой:

Экран из приложения

У меня следующая проблема: когда я перемещаю кнопку влево или вправо в свойстве x, все в порядке. Я могу часто перемещать каждую кнопку влево и вправо. Проблема начинается, когда я перемещаю кнопку вниз или вверх в свойстве y. Я могу только переместить кнопку один раз, и затем она больше не будет доступна для onTouchListener. Он становится неподвижным в любом направлении, и никакие действия не выполняются. Вот мой файл активности Java и макет XML.

MainActivity.java

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;

class MyPoint{

    private boolean canMove;
    private View associatedView;
    private int x;
    private int y;
    private MyPoint nord;
    private MyPoint south;
    private MyPoint est;
    private MyPoint west;

    MyPoint(int x, int y, View associatedView){
        this.x = x;
        this.y = y;
        this.associatedView = associatedView;
        canMove = false;
    }

    public MyPoint getEst() {
        return est;
    }

    public MyPoint getNord() {
        return nord;
    }

    public MyPoint getSouth() {
        return south;
    }

    public MyPoint getWest() {
        return west;
    }

    public void setNeighbors(MyPoint nord, MyPoint south, MyPoint west, MyPoint est){
        this.nord = nord;
        this.south = south;
        this.est = est;
        this.west = west;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public View getAssociatedView() {
        return associatedView;
    }

    public void setAssociatedView(View associatedView) {
        this.associatedView = associatedView;
    }

    public boolean isSpace(){
        if(associatedView.getId() == R.id.space)
            return true;
        else
            return false;
    }

    public void allowMovement(){
         canMove = true;
    }

    public void denyMovement(){
        canMove = false;
    }

    public void allowMovementNeighbords(){
        nord.allowMovement();
        south.allowMovement();
        est.allowMovement();
        west.allowMovement();
    }

    public boolean isMoveable(){
        if(canMove) return true;
        else return false;
    }
}

public class MainActivity extends ActionBarActivity {

    LinearLayout mainScreen;
    MyPoint[] board = new MyPoint[16];
    View[] views = new View[16];
    View blank;
    MyPoint blankPoint, associatedPoint;
    int DX,DY;

    private MyPoint findPointByView(View target){
        MyPoint tempResult = blankPoint;
        for(int i=0; i<16; i++)
            if(board[i].getAssociatedView().getId() == target.getId())
                tempResult = board[i];
        return tempResult;
    }

    private MyPoint findSpace(){
        MyPoint tempResult = blankPoint;
        for(int i=0; i<16; i++)
            if(board[i].isSpace()){
                tempResult = board[i];
            }

        return tempResult;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mainScreen = (LinearLayout) findViewById(R.id.main_screen);
        blank = findViewById(R.id.blank);
        blankPoint = new MyPoint(0,0,blank);
        blankPoint.setNeighbors(blankPoint,blankPoint,blankPoint,blankPoint);
        associatedPoint = blankPoint;

        final View.OnTouchListener mTouchListener = new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event){

               float x1=0, x2, y1=0, y2, dx, dy;

               switch(event.getActionMasked()) {
                    case(MotionEvent.ACTION_DOWN):
                        associatedPoint = findPointByView(v);
                        x1 = event.getX();
                        y1 = event.getY();
                        break;
                    case(MotionEvent.ACTION_UP): {
                        x2 = event.getX();
                        y2 = event.getY();
                        dx = x2-x1;
                        dy = y2-y1;

                        if(associatedPoint.isMoveable()){
                            if(Math.abs(dx) > Math.abs(dy)) {
                                if(dx>0){
                                    if(associatedPoint.getEst().isSpace()){
                                       v.animate().xBy(DX);
                                        associatedPoint.setAssociatedView(findViewById(R.id.space));
                                        associatedPoint.getEst().setAssociatedView(v);
                                    }
                                }
                                else{
                                    if(associatedPoint.getWest().isSpace()){
                                        v.animate().xBy(-DX);
                                        associatedPoint.setAssociatedView(findViewById(R.id.space));
                                        associatedPoint.getWest().setAssociatedView(v);
                                    }
                                }
                            } else {
                                if(dy>0){
                                    if(associatedPoint.getSouth().isSpace()){
                                        v.animate().yBy(DY);
                                        associatedPoint.setAssociatedView(findViewById(R.id.space));
                                        associatedPoint.getSouth().setAssociatedView(v);
                                    }
                                }
                                else{
                                    if(associatedPoint.getNord().isSpace()){
                                        v.animate().yBy(-DY);
                                        associatedPoint.setAssociatedView(findViewById(R.id.space));
                                        associatedPoint.getNord().setAssociatedView(v);
                                    }
                                }
                            }

                        denyMovementAll();
                        findSpace().allowMovementNeighbords();
                        }
                    return true;
                    }
               }
            return false;
            }
        };

        views[0] = findViewById(R.id.button1);
        views[1] = findViewById(R.id.button2);
        views[2] = findViewById(R.id.button3);
        views[3] = findViewById(R.id.button4);
        views[4] = findViewById(R.id.button5);
        views[5] = findViewById(R.id.button6);
        views[6] = findViewById(R.id.button7);
        views[7] = findViewById(R.id.button8);
        views[8] = findViewById(R.id.button9);
        views[9] = findViewById(R.id.button10);
        views[10] = findViewById(R.id.button11);
        views[11] = findViewById(R.id.button12);
        views[12] = findViewById(R.id.button13);
        views[13] = findViewById(R.id.button14);
        views[14] = findViewById(R.id.button15);
        views[15] = findViewById(R.id.space);

        for(int i=0; i<15; i++)
            views[i].setOnTouchListener(mTouchListener);
    }

    private void denyMovementAll() {
        for(int i=0; i<16; i++)
            board[i].denyMovement();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int offsetY = displayMetrics.heightPixels - mainScreen.getMeasuredHeight();

        for (int i=0 ; i<16; i++){
            int[] tempCoords = new int[2];
            views[i].getLocationOnScreen(tempCoords);
            int x = tempCoords[0];
            int y = tempCoords[1] - offsetY;
            board[i] = new MyPoint(x,y,views[i]);
        }

        board[0].setNeighbors(blankPoint,board[4],blankPoint,board[1]);
        board[1].setNeighbors(blankPoint,board[5],board[0],board[2]);
        board[2].setNeighbors(blankPoint,board[6],board[1],board[3]);
        board[3].setNeighbors(blankPoint,board[7],board[2],blankPoint);
        board[4].setNeighbors(board[0],board[8],blankPoint,board[5]);
        board[5].setNeighbors(board[1],board[9],board[4],board[6]);
        board[6].setNeighbors(board[2],board[10],board[5],board[7]);
        board[7].setNeighbors(board[3],board[11],board[6],blankPoint);
        board[8].setNeighbors(board[4],board[12],blankPoint,board[9]);
        board[9].setNeighbors(board[5],board[13],board[8],board[10]);
        board[10].setNeighbors(board[6],board[14],board[9],board[11]);
        board[11].setNeighbors(board[7],board[15],board[10],blankPoint);
        board[12].setNeighbors(board[8],blankPoint,blankPoint,board[13]);
        board[13].setNeighbors(board[9],blankPoint,board[12],board[14]);
        board[14].setNeighbors(board[10],blankPoint,board[13],board[15]);
        board[15].setNeighbors(board[11],blankPoint,board[14],blankPoint);

        DX = board[1].getX() - board[0].getX();
        DY = board[4].getY() - board[0].getY();

        denyMovementAll();
        findSpace().allowMovementNeighbords();
    }
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"        android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
android:collapseColumns="4"
android:orientation="vertical"
android:clipChildren="false"
android:id="@+id/main_screen"
android:clipToPadding="false">


<LinearLayout
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:id="@+id/row1">

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b1"
        android:id="@+id/button1"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b2"
        android:id="@+id/button2"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b3"
        android:id="@+id/button3"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b4"
        android:id="@+id/button4"
        android:layout_weight="1" />
</LinearLayout>

<LinearLayout
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:id="@+id/row2">

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b5"
        android:id="@+id/button5"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b6"
        android:id="@+id/button6"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b7"
        android:id="@+id/button7"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b8"
        android:id="@+id/button8"
        android:layout_weight="1" />
</LinearLayout>

<LinearLayout
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:id="@+id/row3">

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b9"
        android:id="@+id/button9"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b10"
        android:id="@+id/button10"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b11"
        android:id="@+id/button11"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b12"
        android:id="@+id/button12"
        android:layout_weight="1" />
</LinearLayout>

<LinearLayout
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:id="@+id/row4">

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b13"
        android:id="@+id/button13"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b14"
        android:id="@+id/button14"
        android:layout_weight="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:text="@string/b15"
        android:id="@+id/button15"
        android:layout_weight="1" />

    <Space
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/space"
        android:visibility="invisible"/>

     <Space
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:visibility="invisible"
        android:id="@+id/blank"/>


</LinearLayout>
</LinearLayout>

Я действительно понятия не имею, что является причиной этой проблемы. Пожалуйста, дайте мне небольшую подсказку о том, что может вызвать эту проблему. заранее спасибо

2 ответа

Вы должны вернуть true, если слушатель использовал событие. В противном случае он должен вернуть false по умолчанию.

View.OnTouchListener mTouchListener = new View.OnTouchListener() {
    ...
    return false;
}

Я изменил свой код, следуя вашему совету:

View.OnTouchListener mTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event){

            float x1=0, x2, y1=0, y2, dx, dy;


            switch(event.getActionMasked()) {
                case(MotionEvent.ACTION_DOWN):
                    x1 = event.getX();
                    y1 = event.getY();
                    break;

                case(MotionEvent.ACTION_UP): {

                    x2 = event.getX();
                    y2 = event.getY();
                    dx = x2-x1;
                    dy = y2-y1;


                        if(Math.abs(dx) > Math.abs(dy)) {
                            if(dx>0){
                                v.animate().xBy(DX);
                                }

                            else{
                                v.animate().xBy(-DX);
                                }

                        } else {
                            if(dy>0){
                                v.animate().yBy(DY);
                                }

                            else{
                                v.animate().yBy(-DY);
                                }
                        }
                return true;

                }

            }
        return false;
        }
    };

К сожалению, это не решает мою проблему. Пожалуйста, поправьте меня, если я ошибся

Другие вопросы по тегам