В моем приложении для 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;
}
}
}
Я удалил ненужные части кода.
Вы можете использовать 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 не возвращает глобальные координаты?
Хорошо, я нашел более простое решение. Я отредактирую свой ответ.
Простое решение не соответствует моим потребностям. Я хочу сбросить его также за пределами TouchListener, и происхождение будет обновляться каждый раз, когда я касаюсь представления. Я исправил ваше первое решение. Вы использовали get вместо getTranslation для обновления cardStartPos в блоке кода перемещения. Теперь он работает нормально! Измените его, чтобы я мог отметить его как правильный ответ.
Хорошо, я изменил ошибку. Спасибо!
Можете ли вы опубликовать свой код активности и макет XML?