Сбросить положение просмотра, андроид

В моем приложении для Android я позволяю пользователю перемещать некоторые представления. Я реализовал перемещение, добавив OnTouchListener в представления (v.setX()/v.setY()).

Теперь я хочу, чтобы пользователь сбросить позиции просмотров нажимал кнопку. Под сбросом я подразумеваю установку положения в исходное положение. А исходная позиция — это позиция представлений после их загрузки/первого отображения.

Представления находятся в относительной компоновке. Поэтому у меня нет фиксированных координат для просмотров.

Я попытался получить позиции представлений в onCreate() с помощью v.getX()/v.getY(), но позиции в это время всегда равны нулю.

XML-код:

<?xml version = "1.0" encoding = "utf-8"?>
<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:app = "http://schemas.android.com/apk/res-auto"
    xmlns:tools = "http://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    android:orientation = "vertical"
    tools:context = ".GameActivity">
    
    ...

    <RelativeLayout
        android:layout_width = "match_parent"
        android:layout_height = "match_parent">

      ...

        <ImageView
            android:id = "@+id/ivCard1"
            android:layout_width = "@dimen/card_width"
            android:layout_height = "@dimen/card_height"
            android:layout_below = "@id/ivCardAnchor"
            android:layout_marginStart = "@dimen/card_margin"
            android:layout_marginTop = "@dimen/card_margin"
            android:layout_marginEnd = "@dimen/card_margin"
            android:layout_marginBottom = "@dimen/card_margin"
            android:layout_toStartOf = "@+id/ivCard2"
            android:background = "@color/black" />

      ...


    </RelativeLayout>

</LinearLayout>

Код активности:

public class GameActivity extends AppCompatActivity {

    ...
    private ImageView ivCard1;
    ...

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game);

      ...
        ivCard1 = findViewById(R.id.ivCard1);
      ivCard1.setOnTouchListener(new OnTouchCardListener());
        Log.d(TAG, "onCreate: POS x = " + ivCard1.getX() + ", POS y = " + ivCard1.getY());    // -----> always zero
      ...

    }




     public class OnTouchCardListener implements View.OnTouchListener {
        PointF touchPos = new PointF();
        PointF cardStartPos = new PointF();

        @Override
        public boolean onTouch(View ivCard, MotionEvent event)
        {
            switch (event.getAction())
            {
                case MotionEvent.ACTION_MOVE:
                      ivCard.setX((int) (cardStartPos.x + event.getX() - touchPos.x));
                  ivCard.setY((int) (cardStartPos.y + event.getY() - touchPos.y));
                  cardStartPos.set(ivCard.getX(), ivCard.getY());
                    break;
                case MotionEvent.ACTION_DOWN:
                    touchPos.set(event.getX(), event.getY());
                    cardStartPos.set(ivCard.getX(), ivCard.getY());
                    break;
                case MotionEvent.ACTION_UP:
                    break;
                default :
                    break;
            }
            return true;
        }
    }
}

Я удалил ненужные части кода.

Можете ли вы опубликовать свой код активности и макет XML?

Jim Rhodes 05.04.2022 21:59
1
1
26
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать translation вместо координат, а затем для сброса просто выполните:

view.setTranslationX(0);
view.setTranslationY(0);

Тогда ваш код будет:

public class OnTouchCardListener implements View.OnTouchListener {
        PointF touchPos = new PointF();
        PointF cardStartPos = new PointF();

        @Override
        public boolean onTouch(View ivCard, MotionEvent event)
        {
            switch (event.getAction())
            {
                case MotionEvent.ACTION_MOVE:
                    ivCard.setTranslationX((int) (cardStartPos.x + event.getX() - touchPos.x));
                    ivCard.setTranslationY((int) (cardStartPos.y + event.getY() - touchPos.y));
                    cardStartPos.set(ivCard.getTranslationX(), ivCard.getTranslationY());
                    break;
                case MotionEvent.ACTION_DOWN:
                    touchPos.set(event.getX(), event.getY());
                    cardStartPos.set(ivCard.getTranslationX(), ivCard.getTranslationY());
                    break;
                case MotionEvent.ACTION_UP:
                    break;
                default :
                    break;
            }
            return true;
        }
    }

Не работает. Когда я перемещаю вид пальцем, между моим пальцем и видом большое расстояние. Кажется, что на первом ходу позиция устанавливается в неправильное положение. Но тогда он движется правильно. Наверное потому, что event.get не возвращает глобальные координаты?

Created 05.04.2022 22:58

Хорошо, я нашел более простое решение. Я отредактирую свой ответ.

Jan Rozenbajgier 05.04.2022 23:07

Простое решение не соответствует моим потребностям. Я хочу сбросить его также за пределами TouchListener, и происхождение будет обновляться каждый раз, когда я касаюсь представления. Я исправил ваше первое решение. Вы использовали get вместо getTranslation для обновления cardStartPos в блоке кода перемещения. Теперь он работает нормально! Измените его, чтобы я мог отметить его как правильный ответ.

Created 05.04.2022 23:17

Хорошо, я изменил ошибку. Спасибо!

Jan Rozenbajgier 05.04.2022 23:25

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