java – Only last draggable image added to layout can be moved around-ThrowExceptions

Exception or error:

BACKGROUND

I have an app where on a certain time multiple images are added to the screen in random locations. Those images are supposed to be draggable when touched.
All images are 120x120, so they are not too big.


PROBLEM

Although all images are added correctly to the layout, only the last image added can be dragged.


SNIPPETS

View added to the layout with an image. This is the draggable view. It must be added on the coordinates specified by coordenadas, which stores an X-axis and a Y-axis value.

// 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. This represents a point on a 2D environment, with an X-axis and Y-axis value. Used for storing the position in pixels of the draggable view in the layout.

// 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 Layout:

<?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>
How to solve:

Leave a Reply

Your email address will not be published. Required fields are marked *