You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android双ScrollView自适应布局需求:小屏平分大屏下方拉伸

Android布局适配:动态分配两个ScrollView高度

需求说明:

  • 垂直排列两个ScrollView,屏幕高度较小时,两者各占屏幕50%空间(如图1)
  • 屏幕高度充足时,下方包含TableView的ScrollView自动拉伸填充剩余可用空间(如图2)
    当前使用LinearLayout权重均分的方案无法实现该动态适配效果。

原布局代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".cards.CardGoods">


    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:contentInsetStart="0dp"
        app:menu="@menu/card_step1_menu"
        >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:paddingStart="32dp"
            android:gravity="center">

            <TextView android:id="@+id/tv_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/card_goods_p1"
                style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
                android:singleLine="true"
                android:maxLines="1"
                android:ellipsize="end"
                android:layout_weight="1"
                android:gravity="center"
                android:textColor="?attr/colorPrimary"
                />
            <View
                android:id="@+id/view"
                android:layout_width="match_parent"
                android:layout_height="@dimen/divider_height"
                android:background="@drawable/horizontal_gradient_menu_divider_02" />
        </LinearLayout>
    </androidx.appcompat.widget.Toolbar>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">


                    <com.google.android.material.textfield.TextInputLayout
                        android:id="@+id/card_Code_n"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:layout_marginStart="16dp"
                        android:layout_marginTop="16dp"
                        android:layout_marginEnd="16dp"
                        app:startIconDrawable="@drawable/barcode24px"
                        app:startIconTint="@color/deep_purple_100"
                        >

                        <com.google.android.material.textfield.TextInputEditText
                            android:id="@+id/card_Code"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:hint="@string/code"
                            android:maxLines="2"
                            android:backgroundTint="@color/white"
                            android:inputType="textCapSentences" />
                    </com.google.android.material.textfield.TextInputLayout>

                    <LinearLayout
                        android:id="@+id/lL_edit2"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:orientation="horizontal"
                        android:layout_marginStart="10dp"
                        android:layout_marginEnd="10dp"
                        >

                        <Button
                            android:id="@+id/btn_ean13"
                            android:layout_weight="1"
                            android:layout_width="wrap_content"
                            android:layout_marginStart="10dp"
                            android:layout_marginEnd="5dp"
                            android:layout_marginTop="8dp"
                            android:layout_marginBottom="8dp"
                            android:layout_height="wrap_content"
                            android:text="@string/card_Ean13"
                            android:padding="8dp"
                            />

                        <Button
                            android:id="@+id/btn_edit_userInfo4"
                            android:layout_weight="1"
                            android:layout_width="wrap_content"
                            android:layout_marginStart="5dp"
                            android:layout_marginEnd="10dp"
                            android:layout_marginTop="8dp"
                            android:layout_marginBottom="8dp"
                            android:layout_height="wrap_content"
                            android:padding="8dp"
                            android:text="@string/card_a1" />

                        <Button
                            android:id="@+id/btn_edit_userInfo4"
                            android:layout_weight="1"
                            android:layout_width="wrap_content"
                            android:layout_marginStart="5dp"
                            android:layout_marginEnd="10dp"
                            android:layout_marginTop="8dp"
                            android:layout_marginBottom="8dp"
                            android:layout_height="wrap_content"
                            android:padding="8dp"
                            android:text="@string/card_a2" />

                    </LinearLayout>

                    <com.google.android.material.textfield.TextInputLayout
                        android:id="@+id/card_Nt_n"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:layout_marginStart="16dp"
                        android:layout_marginTop="16dp"
                        android:layout_marginEnd="16dp"
                        app:startIconDrawable="@drawable/shopping_basket24px"
                        app:startIconTint="@color/deep_purple_100">

                        <com.google.android.material.textfield.TextInputEditText
                            android:id="@+id/card_Nt"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:hint="@string/name"
                            android:backgroundTint="@color/white"
                            android:inputType="textCapSentences" />
                    </com.google.android.material.textfield.TextInputLayout>

                    <com.google.android.material.textfield.TextInputLayout
                        android:id="@+id/eiSpinnerLayout"
                        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:layout_marginStart="16dp"
                        android:layout_marginTop="16dp"
                        android:layout_marginEnd="16dp"
                        app:startIconDrawable="@drawable/scale24px"
                        app:startIconTint="@color/deep_purple_100">

                        <androidx.appcompat.widget.AppCompatAutoCompleteTextView
                            android:id="@+id/eiTextView"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            tools:ignore="KeyboardInaccessibleWidget"
                            android:clickable="true"
                            android:focusable="false"
                            android:focusableInTouchMode="false"
                            android:hint="@string/ei"
                            />
                    </com.google.android.material.textfield.TextInputLayout>


                </LinearLayout>
            </LinearLayout>

        </ScrollView>
      
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="@color/grey_400"
            android:layout_weight="1">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">


                <com.evrencoskun.tableview.TableView
                    android:id="@+id/tableview"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginTop="1dp"
                    app:allow_click_inside_cell="true"
                    app:allow_click_inside_column_header="true"

                    app:allow_click_inside_row_header="true">
                </com.evrencoskun.tableview.TableView>

            </LinearLayout>

        </LinearLayout>


    </LinearLayout>



</androidx.constraintlayout.widget.ConstraintLayout>

图1:屏幕较小时的50/50布局
图2:屏幕充足时下方ScrollView拉伸填充


解决方案:使用ConstraintLayout实现动态高度适配

替换原布局中的外层LinearLayout,直接用ConstraintLayout管理两个ScrollView的约束,核心逻辑:

  1. 给上方ScrollView设置最小高度,确保小屏幕时占屏幕50%空间,同时允许空间充足时自适应内容高度
  2. 下方ScrollView自动填充上方ScrollView底部到屏幕底部的剩余空间

修改后的核心布局代码:

<!-- 替换原布局中的LinearLayout部分 -->
<ScrollView
    android:id="@+id/top_scroll"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toBottomOf="@id/toolbar"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    <!-- 小屏幕时至少占屏幕高度的50% -->
    app:layout_constraintHeight_percent="0.5"
    app:layout_constraintHeight_min="0dp"
    <!-- 空间充足时自适应内容高度 -->
    app:layout_constraintHeight_default="wrap">

    <!-- 原上方ScrollView内的内容保持不变 -->
</ScrollView>

<LinearLayout
    android:id="@+id/bottom_container"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:background="@color/grey_400"
    app:layout_constraintTop_toBottomOf="@id/top_scroll"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintBottom_toBottomOf="parent">

    <com.evrencoskun.tableview.TableView
        android:id="@+id/tableview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="1dp"
        app:allow_click_inside_cell="true"
        app:allow_click_inside_column_header="true"
        app:allow_click_inside_row_header="true">
    </com.evrencoskun.tableview.TableView>
</LinearLayout>

关键属性说明:

  • app:layout_constraintHeight_percent="0.5":强制上方ScrollView在小屏幕时至少占屏幕高度的50%
  • app:layout_constraintHeight_default="wrap":屏幕高度充足时,上方ScrollView自适应内容高度,不再局限于50%
  • 下方容器用layout_height="0dp"配合上下约束,自动填充剩余空间

内容的提问来源于stack exchange,提问作者Сергей Соколов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:02:27