Я пытаюсь динамически добавить представление к LinearLayout, используя высоту wrap_content. Однако это не сработает, если я не добавлю определенную высоту dp, например 300dp. Почему я не могу программно добавить представление и заставить родительский элемент LinearLayout обернуть содержимое?

Взгляд, который я пытаюсь добавить:

public class ImageCanvas extends View {

    private static final String TAG = "ImageCanvas";

    private Bitmap icon;

    public ImageCanvas(Context context) {
        super(context);

        Drawable drawable = ContextCompat.getDrawable(context, R.drawable.piggy);
        if(drawable != null){
            icon = ((BitmapDrawable) drawable).getBitmap();
        }
        Log.d(TAG, "ImageCanvas: " + icon);
    }

    public ImageCanvas(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ImageCanvas(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        canvas.drawBitmap(icon, 0, 0, null);
    }
}

LinearLayout Я пытаюсь добавить вышеупомянутое представление к:

             <LinearLayout
                android:id="@+id/drawingPad"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_constraintTop_toBottomOf="@+id/btn_create_image"
                app:layout_constraintBottom_toBottomOf="parent"
                android:paddingBottom="32dp"
                android:orientation="vertical"
                android:paddingTop="32dp"/>             

Программное создание представления и его добавление:

LinearLayout drawingPad = findViewById(R.id.drawingPad);

ImageCanvas imageCanvas = new ImageCanvas(context);
drawingPad.addView(imageCanvas);

Это работает, когда я устанавливаю XML LinearLayout на определенную высоту, например 200dp, но он не работает с wrap_content, как я могу заставить его делать это с wrap_content?

< Сильный > _________________________________________________________

Обновление 1:

Я упростил все до XML-макета, и проблема оказалась в родительском NestedScrollView.

<?xml version="1.0" encoding="utf-8"?>

<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/parentLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:id="@+id/btn_create_image"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:text="Create image"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <LinearLayout
            android:id="@+id/drawingPad"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingTop="32dp"
            android:paddingBottom="32dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/btn_create_image" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.core.widget.NestedScrollView>

Это весь макет. Когда вы добавляете NestedScrollView и пытаетесь добавить представление программно, растровое изображение НЕ БУДЕТ рисоваться на экране. Когда вы удалите NestedScrollView, появится растровое изображение. Если кто-нибудь знает, как это сделать с помощью NestedScrollView, поделитесь!

1
DIRTY DAVE 25 Май 2021 в 02:31

2 ответа

Лучший ответ

Вам необходимо предоставить измерения ImageCanvas с переопределением onMeasure():

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(icon.getWidth(),icon.getHeight());
}

См. Пользовательские компоненты представления.

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

(icon.getHeight() - это то, что вам действительно нужно, и оно соответствует wrap_content. Вам может потребоваться другое значение для icon.getWidth() в зависимости от вашего дизайна.)

Не уверен, почему NestedScrollView имеет какой-либо эффект, но приведенный выше код поможет.

1
Cheticamp 25 Май 2021 в 14:36

Проблема может заключаться в вашем макете ограничений. для макета ограничения> = 1.1

app:layout_constrainedHeight=”true"
android:layout_height="wrap_content" 

Для компоновки ограничений <1.1

android:layout_height="wrap_content" 
app:layout_constraintHeight_default="wrap"

Это всегда меня заводит, может быть, тебя достало. (изменить) это должно быть в дочернем элементе макета ограничения, а не в самом макете ограничения, то есть LinearLayout.

0
avalerio 25 Май 2021 в 04:45