如何缩小 ScrollView 高度以保持另一个视图(按钮)固定到位?

How to shrink a ScrollView's height keeping the other view(Button) fixed in place?

我有一个 ScrollView 和一个 Button 在垂直方向并排(两个 children 的 ConstraintLayout 的加权链ScrollViewButton 的权重分别为 1 和 0。顺便说一句,您可以选择假设它们是 LinearLayout 的 children 而不是 ConstraintLayout,因为加权 ConstraintLayout 链的工作原理几乎与 LinearLayout 相同)。

这是典型的用例之一,您在其中创建 ScrollView,其中包含特定项目的列表 (children),底部有一个大按钮,可根据数值填入ScollViewchildren。如下所示:

red-color 圈出的部分是 Button 应该在的地方(它在那里但不可见)。

现在是问题。

我希望按钮始终可见,而不管 ScrollView( 如果这意味着 ScrollView 的高度缩小,就这样吧,因为它是可滚动的毕竟 ) 但由于 ScrollView 的内容占用了足够的 space 来隐藏 Button,默认情况下它会被隐藏。解决方案(我认为)需要将 ScrollView 的高度缩小到 Button 在下面剩余的 space 中可见的数量。

请注意,我不希望安排最终像 Button 覆盖 ScrollView 的区域。在这种情况下,ScrollView 不需要收缩高度,而是 Button 在底部漂浮在它上方,隐藏它的一些区域。我想强制 ScrollView 调整到 Button。此外,权重分别为 1 和 0 也没有帮助。

编辑: 布局代码。 (Button 的 ID 为 search_button)

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="8dp"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    >

    <ScrollView
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        android:id="@+id/scrollView2"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_constraintRight_creator="1"
        tools:layout_constraintLeft_creator="1"
        app:layout_constraintVertical_weight="1"
        app:layout_constraintBottom_toTopOf="@+id/search_button"
        app:layout_constraintVertical_chainStyle="spread_inside">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginEnd="4dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:layout_marginStart="4dp"
            android:layout_marginTop="8dp"
            android:background="@android:drawable/dialog_holo_light_frame"
            android:paddingEnd="8dp"
            android:paddingLeft="8dp"
            android:paddingRight="8dp"
            android:paddingStart="8dp"
            android:paddingTop="8dp">

            <LinearLayout
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                app:layout_constraintTop_toTopOf="parent"
                android:layout_marginTop="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginStart="8dp"
                app:layout_constraintLeft_toLeftOf="parent"
                android:layout_marginRight="8dp"
                android:layout_marginEnd="8dp"
                android:orientation="vertical"
                app:layout_constraintRight_toRightOf="parent"
                android:id="@+id/frameLayout">

                <include layout="@layout/layout_subject_search" />

            </LinearLayout>


            <View
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:background="?android:attr/listDivider"
                android:layout_marginLeft="8dp"
                app:layout_constraintLeft_toLeftOf="parent"
                android:layout_marginRight="8dp"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/frameLayout"
                android:layout_marginStart="8dp"
                android:layout_marginEnd="8dp"
                android:layout_marginTop="8dp"
                android:id="@+id/view" />

            <LinearLayout
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:layout_marginTop="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginStart="8dp"
                app:layout_constraintLeft_toLeftOf="parent"
                android:layout_marginRight="8dp"
                android:layout_marginEnd="8dp"
                android:orientation="vertical"
                app:layout_constraintRight_toRightOf="parent"
                android:id="@+id/frameLayout1"
                app:layout_constraintTop_toBottomOf="@+id/view">

                <include layout="@layout/layout_qualification_search" />

            </LinearLayout>

            <View
                android:layout_width="0dp"
                android:layout_height="2dp"
                android:background="?android:attr/listDivider"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/frameLayout1"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginEnd="8dp"
                android:id="@+id/view2" />


            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/search_by_location_label"
                android:textSize="15sp"
                android:textStyle="bold"
                android:layout_marginLeft="8dp"
                app:layout_constraintLeft_toLeftOf="parent"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/view2"
                android:layout_marginStart="8dp" />

            <Switch
                android:id="@+id/location_toggle_switch"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:text=""
                android:layout_marginTop="16dp"
                app:layout_constraintTop_toBottomOf="@+id/view2"
                android:layout_marginRight="16dp"
                app:layout_constraintRight_toRightOf="parent"
                android:layout_marginEnd="16dp" />

            <FrameLayout
                android:id="@+id/map_search_fragment"
                android:layout_width="0dp"
                android:layout_height="240dp"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@+id/textView"
                android:layout_marginBottom="8dp"
                android:layout_marginEnd="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:background="@android:drawable/dialog_holo_light_frame"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/location_toggle_switch"
                app:layout_constraintVertical_bias="0.0">

            </FrameLayout>

        </android.support.constraint.ConstraintLayout>

    </ScrollView>

    <Button
        android:id="@+id/search_button"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:text="@string/search_tutors_string"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="4dp"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintVertical_weight="0"
        app:layout_constraintTop_toBottomOf="@+id/scrollView2" />

    <ProgressBar
        android:id="@+id/search_tutors_progress_bar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:visibility="gone"/>


</android.support.constraint.ConstraintLayout>

编辑 2: 正如@marshmallow 所问,

// 包括布局="@layout/layout_subject_search"

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/search_by_subject_label"
        android:textStyle="bold"
        android:textSize="15sp"/>

    <com.learncity.learner.search.SubjectMultiAutoCompleteTextView
        android:id="@+id/subject_multi_auto_complete_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:completionThreshold="1"
        android:ems="10"/>

</merge>

// 包含布局="@layout/layout_qualification_search"

<merge xmlns:android="http://schemas.android.com/apk/res/android" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/search_by_qualification_label"
        android:textStyle="bold"
        android:textSize="15sp"/>

    <com.learncity.learner.search.QualificationMultiAutoCompleteTextView
        android:id="@+id/qualification_multi_auto_complete_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:completionThreshold="1"
        android:ems="10"/>


</merge>

ScrollView 高度更改为 wrap_content

<ScrollView
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    android:id="@+id/scrollView2"
    ...>
</ScrollView>

同时在 ScrollView

中将 constraintVertical_bias 更改为 0.0
app:layout_constraintVertical_bias="0.0"

更新:

将高度Button改为wrap_content即可正常显示

首先,感谢@marshmallow 提出 wrap_content 策略以及反复测试和回复更新的解决方案。


解决方案与他的建议有点不同:

  • Buttonlayout_height 设为 wrap_content。为什么?我们想声明按钮的高度作为ScrollView调整大小的参考,按钮的真实高度是通过wrap_content.[=40=得到的]
  • 现在,我们要告诉 ScrollView 根据按钮调整其大小。为此,我们将 layout_height 用作 0dp,即 "Use available constraints to adjust your size rather than asserting any fixed size of your own"。同理,Button的高度也不是0dp。
  • 接下来,我们在两者之间建立一个权重链关系,ScrollView权重为1,Button权重为0(对于Button无效,因为width不是0dp/match约束;所以只是一个指向 ScrollView 的指针来占用 space 除了 Button)

有了这个,最终的解决方案就变成了:(纵向和横向模式测试的解决方案

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="8dp"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    >

    <ScrollView
        android:id="@+id/scrollView2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="4dp"
        app:layout_constraintBottom_toTopOf="@+id/search_button"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0"
        app:layout_constraintVertical_chainStyle="spread_inside"
        app:layout_constraintVertical_weight="1"
        tools:layout_constraintLeft_creator="1"
        tools:layout_constraintRight_creator="1">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginEnd="4dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:layout_marginStart="4dp"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp"
            android:background="@android:drawable/dialog_holo_light_frame"
            android:paddingEnd="8dp"
            android:paddingLeft="8dp"
            android:paddingRight="8dp"
            android:paddingStart="8dp"
            android:paddingTop="8dp">

            <LinearLayout
                android:id="@+id/frameLayout"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginEnd="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:orientation="vertical"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent">

                <include layout="@layout/layout_subject_search" />

            </LinearLayout>


            <View
                android:id="@+id/view"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginEnd="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:background="?android:attr/listDivider"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/frameLayout" />

            <LinearLayout
                android:id="@+id/frameLayout1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginEnd="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:orientation="vertical"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/view">

                <include layout="@layout/layout_qualification_search" />

            </LinearLayout>

            <View
                android:id="@+id/view2"
                android:layout_width="0dp"
                android:layout_height="2dp"
                android:layout_marginEnd="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:background="?android:attr/listDivider"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/frameLayout1" />


            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:text="@string/search_by_location_label"
                android:textSize="15sp"
                android:textStyle="bold"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/view2" />

            <Switch
                android:id="@+id/location_toggle_switch"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_marginEnd="16dp"
                android:layout_marginRight="16dp"
                android:layout_marginTop="16dp"
                android:text=""
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/view2" />

            <FrameLayout
                android:id="@+id/map_search_fragment"
                android:layout_width="0dp"
                android:layout_height="240dp"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@+id/textView"
                android:layout_marginBottom="8dp"
                android:layout_marginEnd="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:background="@android:drawable/dialog_holo_light_frame"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/location_toggle_switch"
                app:layout_constraintVertical_bias="0.0">

            </FrameLayout>

        </android.support.constraint.ConstraintLayout>

    </ScrollView>

    <Button
        android:id="@+id/search_button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="4dp"
        android:layout_marginTop="4dp"
        android:text="@string/search_tutors_string"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/scrollView2"
        app:layout_constraintVertical_weight="0" />

    <ProgressBar
        android:id="@+id/search_tutors_progress_bar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:visibility="gone"/>


</android.support.constraint.ConstraintLayout>