При добавлении растрового изображения в макет отображается только первое изображение для l oop. - PullRequest
0 голосов
/ 23 февраля 2020

КОНТЕКСТ

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


КАК ЭТО РАБОТАЕТ

У меня есть for l oop, который перебирает каждую сущность, имеющую собственное изображение. Внутри l oop я получаю случайную позицию на экране, и наряду с изображением текущей сущности я добавляю пользовательский View в эту случайную позицию.


ПРОБЛЕМА

for l oop перебирает все данные, собранные из базы данных, правильно получает координаты и изображения, и не Exception брошен Однако в основном макете показано только изображение первого объекта, хотя addView выполняется для каждого из всех объектов. Отображаемое изображение отображается только один раз.


SNIPPETS

Основной метод действия:

// Método que establece el estado inicial de la aplicación
// TODO: Sólo se ve la cereza
private void estadoInicial()
{
    // Recorremos cada fruta obtenida
    for (int i = 0; i < this.contenedorFrutasOriginal.size(); i++)
    {
        // Obtenemos la fruta de la iteración actual
        DTOFruta frutaActual = this.contenedorFrutasOriginal.get(i);

        if (frutaActual.getImagen() != null)
        {
            // Obtenemos una posición aleatoria en la pantalla
            DTOPunto posicionAleatoria = this.objLogicaVistas.ObtenerCoordenadaAleatoria(getWindowManager().getDefaultDisplay());


            // Creamos una imagen a partir de la fruta
            DTOImagen imagenFruta = new DTOImagen(this, new Paint(),
                                                  frutaActual.getImagen(), posicionAleatoria);

            // Añadimos la imagen a la pantalla
            this.layoutPrincipal.addView(imagenFruta);
        }
    }
}

Метод, который получает случайную координату из экран:

// Método que obtiene una coordenada aleatoria en la pantalla recibida
public DTOPunto ObtenerCoordenadaAleatoria(Display pantalla)
{
    // Obtenemos el tamaño de la pantalla
    Point tamanoPantalla = new Point();
    pantalla.getSize(tamanoPantalla);

    // Obtenemos unos valores para los ejes x e y aleatorios
    float xAleatorio = new Random().nextFloat() * tamanoPantalla.x;
    float yAleatorio = new Random().nextFloat() * tamanoPantalla.y;

    // Creamos el punto aleatorio a partir de los valores obtenidos
    return new DTOPunto(xAleatorio, yAleatorio);
}

Класс для прорисовки изображения на экране:

// 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);
}
}

layoutPrincipal XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context=".capa_vistas.ActPrincipal">

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/fondo"
    android:contentDescription="@null" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/layoutPrincipal"
    android:orientation="vertical">

</LinearLayout>

</RelativeLayout>

ОТЛАДКА

На следующем изображении показано layoutPrincipal детей после for l oop: Layout children after adding views PD: DTOPunto - это класс, который представляет 2D-точка, она имеет только пару float для значений по осям X и Y.
2-й PD: На последней итерации я обнаружил, что макет имеет все предыдущие изображения как дочерние, поэтому выглядит так, что они добавлено правильно.

Ответы [ 2 ]

0 голосов
/ 23 февраля 2020

Похоже, проблема была в том, что макет был LinearLayout. Как указала @Lena Bru, мои виды все еще были там.
Однако, поскольку я хотел, чтобы все виды были видны без прокрутки, я изменил свой макет на ConstraintLayout. ImageView был удален (это было предназначено для фона, бессмысленно, когда есть атрибут для макета root), поэтому 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>  

Теперь все изображения отображаются правильно. Есть еще одна проблема (перетаскивается только последнее добавленное изображение), но я опубликую это сейчас в другом вопросе, поскольку он не относится к текущей топи c.

0 голосов
/ 23 февраля 2020

измените это:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context=".capa_vistas.ActPrincipal">

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/fondo"
    android:contentDescription="@null" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/layoutPrincipal"
    android:orientation="vertical">

</LinearLayout>

</RelativeLayout>

на это:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".capa_vistas.ActPrincipal">

<ImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@mipmap/fondo"
    android:contentDescription="@null" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/layoutPrincipal"
    android:orientation="vertical">

</LinearLayout>

</RelativeLayout>

Ваше изображение там, оно просто занимает весь экран. Когда вы начнете прокручивать (если этот макет находится внутри прокручиваемого), вы увидите, что он там есть.

...