Android - как сделать прокручиваемый ограничительный макет?


157

Я хочу создать макет, который позволяет мне прокручивать вниз с помощью макета ограничений, но я не знаю, как это сделать. Должен ли он ScrollViewбыть родителем ConstraintLayoutподобного?

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

<ScrollView 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"
    android:fillViewport="true">

<android.support.constraint.ConstraintLayout
    android:id="@+id/Constraint"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

Или наоборот? Может быть, кто-нибудь может указать мне на хороший учебник по этому поводу или привести пример, я не могу его найти.

Кроме того, я не знаю, является ли это ошибкой или какой-то конфигурацией, которую я не настраивал, но я видел изображения, подобные этому:

введите описание изображения здесь

где некоторые компоненты находятся за пределами "синего прямоугольника" чертежа, но они видны, а на моей стороне, если я помещаю компонент в "белое пространство", я не могу его видеть или перемещать куда угодно, и он появляется в дереве компонентов .

ОБНОВИТЬ :

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

Ответы:


88

Кажется, что он работает, я не знаю, с какой зависимостью вы работали, но в этой

compile 'com.android.support.constraint:constraint-layout:1.0.2'

Работает, вот что я сделал

<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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=".MainActivity">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.design.widget.TextInputLayout
            android:id="@+id/til_input"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:hint="Escriba el contenido del archivo"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@+id/btn_save"
            app:layout_constraintTop_toTopOf="@id/btn_save"
            app:layout_constraintVertical_chainStyle="spread">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </android.support.design.widget.TextInputLayout>

        <Button
            android:id="@+id/btn_save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClickButtonSave"
            android:text="Guardar"
            app:layout_constraintLeft_toRightOf="@+id/til_input"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/txt_content"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="0dp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/til_input"
            app:layout_constraintVertical_chainStyle="spread"
            app:layout_constraintVertical_weight="1" />

        <Button
            android:id="@+id/btn_delete"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:onClick="onClickButtonDelete"
            android:text="Eliminar"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/txt_content"
            app:layout_constraintVertical_chainStyle="spread" />

    </android.support.constraint.ConstraintLayout>

</ScrollView>

Прокрутка вверхвведите описание изображения здесь

Прокрутка внизвведите описание изображения здесь


3
спасибо, проблема заключалась в том, что я не мог прокрутить предварительный просмотр, поэтому построить что-то там было невозможно, но я обнаружил, что с помощью руководства я могу вытащить макет, чтобы сделать пустое прокручиваемое пространство, а затем удалить его, когда я
закончу

2
этот ответ должен быть на высоте!
Костанос

67

Есть тип ограничения, который нарушает функцию прокрутки:

Просто убедитесь, что вы не используете это ограничение в любом представлении, если хотите, чтобы ваш ConstraintLayoutбыл прокручиваемым с помощью ScrollView:

app:layout_constraintBottom_toBottomOf=“parent”

Если вы удалите их, ваш свиток должен работать.

Пояснение:

Установка высоты дочернего элемента в соответствии с высотой ScrollViewродительского элемента противоречит тому, для чего предназначен компонент. В большинстве случаев мы хотим, чтобы некоторый контент с динамическим размером был прокручиваемым, когда он больше экрана / кадра; сопоставление высоты с родительским ScrollViewприведет к тому, что весь контент будет отображаться в фиксированном фрейме (высота родительского элемента), что приведет к недействительности любой функции прокрутки.

Это также происходит, когда для обычных прямых дочерних компонентов установлено значение layout_height="match_parent".

Если вы хотите, чтобы дочерний ScrollViewэлемент соответствовал высоте родительского элемента при недостаточном содержании, просто установите android:fillViewportзначение true для ScrollView.


1
@BasilBattikhi Добавил объяснение
SuppressWarnings

3
Черт, это действительно сработало! Я серьезно ненавижу прокрутки.
Удай

3
Спасибо @SuppressWarnings, очень признателен. Вы намекнули на удаление "app: layout_constraintBottom_toBottomOf =" parent "" работают на 100%
Джигнеш

1
+1, действительно полезно, я не знал, почему элементы в моем просмотре прокрутки не располагались в том месте, которое я хотел.
Хесус Хагивара

1
Да, верно ... но для достижения того же требования следуйте подходу, который я упомянул выше.
Рагхав Шарма

37

Использовать NestedScrollView с окном просмотра, правда, мне подходит

<android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="700dp">

        </android.support.constraint.ConstraintLayout>

</android.support.v4.widget.NestedScrollView>

для android x используйте это

 <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
.....other views....

</androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.core.widget.NestedScrollView>

5
Благодарность! Это то, что я искал - android: fillViewport = "true" - это ключ.
pratt 07

1
не забудьте добавить внутри nestedscrollview, если вы используете AppBarLayoutapp:layout_behavior="@string/appbar_scrolling_view_behavior"
majurageerthan

11

Подводя итог, вы в основном оборачиваете свое android.support.constraint.ConstraintLayoutпредставление в ScrollViewтекст *.xmlфайла, связанного с вашим макетом.

Пример activity_sign_in.xml

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

<ScrollView 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=".SignInActivity"> <!-- usually the name of the Java file associated with this activity -->

    <android.support.constraint.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"
        android:background="@drawable/gradient"
        tools:context="app.android.SignInActivity">

        <!-- all the layout details of your page -->

    </android.support.constraint.ConstraintLayout>
</ScrollView>

Примечание 1. Полосы прокрутки появляются только в том случае, если требуется перенос текста, включая всплывающую клавиатуру.

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


9

Просто используйте макет ограничения внутри NestedScrollViewили ScrollView.

<android.support.v4.widget.NestedScrollView
        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">

    <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/white">

 </android.support.constraint.ConstraintLayout>

</android.support.v4.widget.NestedScrollView>

вот и все. наслаждайтесь кодированием.


4

Чтобы сделать макет с возможностью прокрутки, макет правильный. Его нельзя будет прокручивать, пока не появится причина для прокрутки (как и в любом другом макете). Поэтому добавьте достаточно контента, и его можно будет прокручивать, как и с любым макетом (линейным, относительным и т. Д.). Однако вы не можете правильно прокручивать в Blueprint или режиме дизайна при проектировании с ConstraintLayout и ScrollView.

Имея в виду:

Вы можете сделать прокручиваемый ConstraintLayout, но он не будет правильно прокручиваться в редакторе из-за ошибки / сценария, который не был рассмотрен. Но даже если в редакторе прокрутка не работает, она работает на устройствах. (Я сделал несколько прокручиваемых COnstraintLayouts, поэтому протестировал его)

Заметка

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


1
Чтобы разработать прокручиваемую схему ограничения, в текущем состоянии CL вы можете увеличить высоту устройства и сделать ее настраиваемой. Установите большую высоту макетов (ScrollView и CL) (например, 2000DP) и просто выполните обычное проектирование. Обратите внимание, что вам нужен хороший компьютер, чтобы справиться с расширением, поскольку действительно большие специализированные устройства требуют от компьютера многого. Жаль, что CL не поддерживает проектирование с помощью SCrollViews, но есть обходные пути. например, увеличение высоты устройства.
Zoe

3

Для завершения предыдущих ответов я добавляю следующий пример, который также учитывает использование AppBar. С этим кодом редактор дизайна Android Studio, похоже, отлично работает с ConstraintLayout.

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout
    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"
    android:fitsSystemWindows="true"
    android:background="@drawable/bg"
    android:orientation="vertical">

<android.support.design.widget.AppBarLayout
    android:id="@+id/app_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.ActionBar.AppOverlayTheme">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>

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

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/image_id"
            android:layout_width="match_parent"
            android:layout_height="@dimen/app_bar_height"
            android:fitsSystemWindows="true"
            android:scaleType="centerCrop"
            android:src="@drawable/intro"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="parent" />

        <TextView
            android:id="@+id/desc_id"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/text_margin"
            android:text="@string/intro_desc"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/image_id" />

        <Button
            android:id="@+id/button_scan"
            style="?android:textAppearanceSmall"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:backgroundTint="@color/colorAccent"
            android:padding="8dp"
            android:text="@string/intro_button_scan"
            android:textStyle="bold"
            app:layout_constraintTop_toBottomOf="@+id/desc_id" />

        <Button
            android:id="@+id/button_return"
            style="?android:textAppearanceSmall"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="8dp"
            android:backgroundTint="@color/colorAccent"
            android:padding="8dp"
            android:text="@string/intro_button_return"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/button_recycle" />

        <Button
            android:id="@+id/button_recycle"
            style="?android:textAppearanceSmall"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:backgroundTint="@color/colorAccent"
            android:padding="8dp"
            android:text="@string/intro_button_recycle"
            android:textStyle="bold"
            app:layout_constraintTop_toBottomOf="@+id/button_scan" />
    </android.support.constraint.ConstraintLayout>
</ScrollView>
</LinearLayout>

2

вам нужно окружить мой макет ограничения тегом ScrollView и присвоить ему свойство android: isScrollContainer = "true".


1

В версии 2.2 есть ошибка, из- за которой невозможно прокрутить ConstraintLayout. Я думаю, он все еще существует. В качестве альтернативы вы можете использовать LinearLayout или RelativeLayout.

Кроме того, проверьте: можно ли поместить макет ограничения внутри ScrollView .


Предлагаем вместо этого использовать RelativeLayout, он ближе всего к ConstraintLayout
Зои

Ошибка исправлена.
X09

1

Constraintlayout - это значение по умолчанию для нового приложения. Я сейчас «учусь на Android», и мне было очень трудно понять, как обрабатывать «образец» кода по умолчанию для прокрутки, когда клавиатура поднята. Я видел много приложений, в которых мне приходилось закрывать клавиатуру, чтобы нажать кнопку «Отправить», и иногда она не исчезает. Используя эту иерархию [ScrollView / ContraintLayout / Fields], теперь она работает нормально. Таким образом, мы можем получить преимущества и простоту использования ConstraintLayout в прокручиваемом представлении.


1

Выньте нижнюю кнопку из nestedscrollview и возьмите linearlayout в качестве родительского. Добавьте bottom и nestedscrollview как их дочерние элементы. Он будет работать абсолютно нормально. В манифесте для действия используйте это - это поднимет кнопку при открытии клавиатуры

android:windowSoftInputMode="adjustResize|stateVisible"

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical">

    <androidx.core.widget.NestedScrollView xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:fillViewport="true">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/input_city_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="20dp"
                android:layout_marginTop="32dp"
                android:layout_marginEnd="20dp"
                android:hint="@string/city_name"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent">

                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/city_name"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:digits="abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                    android:lines="1"
                    android:maxLength="100"
                    android:textSize="16sp" />

            </com.google.android.material.textfield.TextInputLayout>

        </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.core.widget.NestedScrollView>

    <Button
        android:id="@+id/submit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:onClick="onSubmit"
        android:padding="12dp"
        android:text="@string/string_continue"
        android:textColor="#FFFFFF"
        app:layout_constraintBottom_toBottomOf="parent" />

</LinearLayout>


0

Вот как я решил это:
если вы используете Nested ScrollView, то есть ScrollView в ConstraintLayout, используйте следующую конфигурацию для ScrollView вместо «WRAP_CONTENT» или «MATCH_PARENT»:


<ScrollView
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintBottom_toTopOf="@+id/someOtherWidget"
    app:layout_constraintTop_toTopOf="parent">

0

в scrollview сделайте высоту и ширину 0, добавьте ограничения Top_toBottomOfand Bottom_toTopOf, что это.


Пожалуйста, объясните этот ответ подробнее, например, на примере кода для реализации.
Джейк

0

Для меня ни одно из предложений об удалении нижних ограничений или установке для контейнера прокрутки значения true не сработало. Что сработало: увеличьте высоту отдельных / вложенных представлений в моем макете, чтобы они «выходили» за пределы родительского, используя параметр «Развернуть по вертикали» в редакторе макета ограничений, как показано ниже.

Для любого подхода важно, чтобы пунктирные линии предварительного просмотра выходили вертикально за пределы верхнего или нижнего размера родительского объекта.

Развернуть по вертикали


0

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

Приятного вам времени :)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    android:background="@color/white"
    >

    <ScrollView
        android:id="@+id/mainScroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:fillViewport="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentStart="true">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">


            <android.support.constraint.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                android:layout_alignParentStart="true"
                android:layout_alignParentTop="true"
                android:layout_alignParentBottom="true"
                android:layout_alignParentEnd="true"
                >

            </android.support.constraint.ConstraintLayout>

        </RelativeLayout>
    </ScrollView>
</RelativeLayout>

Используйте именно так, и вы обязательно найдете свое решение ...

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.