ПРЕДПОСЫЛКИ
У меня есть приложение, в котором в определенное время несколько изображений добавляются на экран в случайных местах. Эти изображения должны быть перетаскиваемыми при касании.
Все изображения имеют размер 120x120
, поэтому они не слишком велики.
ПРОБЛЕМА
Хотя все изображения добавлены правильно в макет, только последнее добавленное изображение может быть перетаскиваться
SNIPPETS
Вид добавлен в макет с изображением. Это отвратительный вид. Он должен быть добавлен к координатам, указанным coordenadas
, в котором хранятся значения оси X и оси Y.
// Clase que representa una vista con una imagen
@SuppressLint("ViewConstructor")
public class DTOImagen extends View
{
// Atributos
private Paint brocha;
private byte[] imagen = null;
private DTOPunto coordenadas;
// Controladores
private boolean arrastrando;
// Propiedades
public Bitmap getImagenBitmap()
{
return BitmapFactory.decodeByteArray(this.imagen, 0, this.imagen.length);
}
// Constructor
public DTOImagen(Context context, Paint brocha, byte[] imagen, DTOPunto coordenadas)
{
super(context);
// Obtenemos los datos de la imagen
this.brocha = brocha;
if (imagen != null)
{
this.imagen = imagen;
}
this.coordenadas = coordenadas;
// Asignamos los controladores de la imagen
this.arrastrando = false;
}
// Método que controla las acciones a realizar al tocar la vista en pantalla
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event)
{
// Comprobamos el evento realizado
switch (event.getAction())
{
// Se ha tocado la pantalla
case MotionEvent.ACTION_DOWN:
// Obtenemos el hitbox de la vista
RectF hitbox = this.obtenerHitbox();
// Comprobamos si se ha tocado dentro del hitbox de la vista
if (hitbox.contains(event.getX(), event.getY()))
{
// La vista se va a arrastrar
this.arrastrando = true;
}
break;
// Se está arrastrando la vista
case MotionEvent.ACTION_MOVE:
// Comprobamos si se está arrastrando la vista
if (this.arrastrando)
{
// Actualizamos las coordenadas de la vista
this.coordenadas.setX(event.getX());
this.coordenadas.setY(event.getY());
// Invalidamos la vista para que se redibuje
this.invalidate();
}
break;
// Se ha dejado de tocar la vista
case MotionEvent.ACTION_UP:
// La imagen se deja de arrastrar
this.arrastrando = false;
break;
}
return true;
}
// Método que dibuja la vista
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas)
{
// Comprobamos que haya imagen
if (this.imagen != null)
{
// Dibujamos la imagen en las coordenadas correspondientes
canvas.drawBitmap(this.getImagenBitmap(), this.coordenadas.getX(),
this.coordenadas.getY(), this.brocha);
}
}
// Método que obtiene el hitbox de una imagen
private RectF obtenerHitbox()
{
// Obtenemos las mitades de la altura y ancho de la imagen
float ancho = this.getImagenBitmap().getWidth();
float altura = this.getImagenBitmap().getHeight();
// Obtenemos las paredes de la vista
float paredIzquierda = this.coordenadas.getX();
float paredDerecha = this.coordenadas.getX() + ancho;
float paredArriba = this.coordenadas.getY();
float paredAbajo = this.coordenadas.getY() + altura;
// Hitbox de la vista
return new RectF(paredIzquierda, paredArriba, paredDerecha, paredAbajo);
}
}
DTOPunto
class. Это представляет точку в 2D-окружении со значениями оси X и оси Y. Используется для сохранения положения в пикселях перетаскиваемого вида в макете.
// Clase que representa un punto en un entorno 2D
public class DTOPunto
{
// Atributos
private float x;
private float y;
// Propiedades
float getX()
{
return x;
}
void setX(float x)
{
this.x = x;
}
float getY()
{
return y;
}
void setY(float y)
{
this.y = y;
}
// Constructor
public DTOPunto(float x, float y)
{
this.setX(x);
this.setY(y);
}
}
XML Макет:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layoutPrincipal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/fondo"
tools:context=".capa_vistas.ActPrincipal">
</androidx.constraintlayout.widget.ConstraintLayout>