XML 布局权重在 android API23 的 ScrollView 中不起作用

XML Layout weight not working in a ScrollView on android API23

我正在 AndroidStudio 中做一个 Android 项目,其中一个 ScrollView 包含一个垂直的 LinearLayout,并且在该 LinearLayout 中有一个 ImageView 和另一个 LinearLayout。我试图将 ImageView 设置为比 LinearLayout 小 10 倍,结果在预览 window 中显示正确,但在我的 phone(Xperia Z3 with API23)中显示不正确。

This is what I see in the preview window and what I want to achieve

但是在我的 phone 上,图片占满了屏幕的宽度,图片的高度与原始图片成正比(几乎占满了屏幕的一半,与根据权重应该达到的距离相去甚远)

该应用在 Google Pixel 7.1.1 和 API25 上运行正常。

这是部分代码:

    <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:fillViewport="true"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <ImageView
            android:layout_weight="1"
            android:adjustViewBounds="true"
            android:layout_height="0dp"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:id="@+id/image"
            android:scaleType="fitCenter"
            android:src="@drawable/bjj2" />
        <LinearLayout
            android:layout_weight="10"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="0dp">
            <LinearLayout
                ...rest of the app
         </LinearLayout>
    </LinearLayout>
</ScrollView>

这是完整的代码https://github.com/IvarsGoldingen/Bjjscorekeeper/blob/master/app/src/main/res/layout/activity_main.xml

谁能告诉我哪里做错了。

应该了解尺寸是如何计算的。 让我们一一来看。

1) ScrollViewfill_parent/fill_parent(实际上可以将其更改为 match_parent/match_parent,因为 fill_parent 已弃用据我记得,但在这种情况下并不重要)。 因此,显示 ScrollView 适合整个屏幕(宽度和高度)。

2) ScrollView里面的LinearLayoutmatch_parent/wrap_content。这是正确的。对于 ScrollView 内的视图,应该使用 wrap_content。 原因 - 是 ScrollView 用于包装 long 高度通常未知的视图(如列表)。假设这里 match_parent 高度 - LinearLayout 的高度将根据滚动视图的高度计算,这是整个屏幕的高度,并且 LinearLayout 高度可以大于屏幕高度。只是不合逻辑。但到目前为止一切正常。继续前进。

3) LinearLayout 内的项目。您希望它们是父布局高度的 1/109/10。此外,您将内部项目的 height 设置为 0,以表明您希望根据 weights 计算高度。 在这里你得到了一个 cycle 的依赖关系。 LinearLayout 高度为 wrap_content 并且取决于内部元素的高度总和。 内部元素的高度是根据父 LinearLayout 高度计算的。

此外,您希望 ImageViewLinearLayout 高度的 1/10。但实际上您似乎希望 ImageView 成为 屏幕的 高度的 1/10,因为 LinearLayout 高度可以大于屏幕的高度(看起来像这就是您在设备上获得的内容。

你说,在 Android Studio 中预览时一切正常。 要证明并非一切正常,请尝试以下操作:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:fillViewport="true"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <ImageView
            android:layout_weight="1"
            android:adjustViewBounds="true"
            android:layout_height="0dp"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:id="@+id/image"
            android:scaleType="fitCenter"
            android:src="@drawable/bjj2" />
        <LinearLayout
            android:layout_weight="10"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="0dp">
            <View
                android:layout_width="match_parent"
                android:layout_height="1000dp"/>

        </LinearLayout>
    </LinearLayout>

</ScrollView>

只需在 inner-inner LinearLayout 中放置一些大(大于屏幕高度)的视图,您将在预览中看到您的图像大于屏幕高度的 1/10。但是LinearLayout的身高是1/10

如何解决您的问题? 我认为唯一的方法是计算屏幕高度的 1/10 并使用您想要的图像调整位图大小并将该位图设置为 ImageView。 或者以任何其他方式将确切高度设置为 ImageView.

或者检查您的布局并创建一些不同的东西。

我们可以在 运行 时通过使用显示指标避免 layout_weight 设置图像视图的高度。

例如

DisplayMetrics displayMetrics = new DisplayMetrics();
            activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
            int height = displayMetrics.heightPixels;
            int width = displayMetrics.widthPixels;
            yourImageView.getLayoutParams().height = height / 5;
            yourImageView.getLayoutParams().width = width / 4;