Android: ¿cómo hacer una disposición de restricción desplazable?

149

Quiero hacer un diseño que me permita desplazarme hacia abajo usando un diseño de restricción, pero no sé cómo hacerlo. ¿Debería ScrollViewser el padre de ConstraintLayoutalguien así?

<?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"/>

¿O al revés? Tal vez alguien pueda señalarme un buen tutorial sobre esto o dar un ejemplo, parece que no puedo encontrar uno.

Además, no sé si esto es un error o alguna configuración que no he configurado, pero he visto imágenes como esta:

ingrese la descripción de la imagen aquí

donde hay algunos componentes fuera del plano "rectángulo azul" pero son visibles, mientras que de mi lado si coloco un componente en el "espacio en blanco" no puedo verlo ni moverlo a ningún lado, y aparece en el árbol de componentes .

ACTUALIZACIÓN

Encontré una manera de hacer que el diseño de restricción se pueda desplazar en la herramienta de diseño, usando una guía horizontal para empujar hacia abajo el borde del diseño de restricción y extenderlo más allá del dispositivo, después de eso, puede usar la guía como la nueva parte inferior del diseño de restricción para Anclar los componentes.

gtovar
fuente

Respuestas:

84

Parece que está funcionando, no sé con qué dependencia estabas trabajando, pero en este caso

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

Está funcionando, esto es lo que hice

<?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>

Desplazarse hacia arribaingrese la descripción de la imagen aquí

Parte inferior de desplazamientoingrese la descripción de la imagen aquí

Sealroto
fuente
3
gracias, el problema era que no podía desplazarme en la vista previa, así que construir algo allí era imposible, pero descubrí que usando una directriz puedo desplegar el diseño para hacer un espacio de desplazamiento vacío y luego eliminarlo cuando termine
gtovar
1
esta respuesta debería estar en la cima!
Kostanos
60

Hay un tipo de restricción que rompe la función de desplazamiento:

Solo asegúrese de no utilizar esta restricción en ninguna vista cuando desee ConstraintLayoutque se pueda desplazar con ScrollView:

app:layout_constraintBottom_toBottomOf=“parent

Si elimina estos, su desplazamiento debería funcionar.

Explicación:

Establecer la altura del niño para que coincida con la de un ScrollViewpadre es contradictorio con lo que el componente debe hacer. Lo que queremos la mayor parte del tiempo es que un contenido de tamaño dinámico sea desplazable cuando sea más grande que una pantalla / marco; haciendo coincidir la altura con el padreScrollView obligaría a que todo el contenido se muestre en un marco fijo (la altura del elemento primario), lo que invalidaría cualquier funcionalidad de desplazamiento.

Esto también sucede cuando los componentes secundarios directos regulares se establecen en layout_height="match_parent" .

Si desea que el elemento secundario ScrollViewcoincida con la altura del elemento primario cuando no hay suficiente contenido, simplemente configúrelo android:fillViewportcomo verdadero para ScrollView.

Suprimir Advertencias
fuente
1
@BasilBattikhi Agregó una explicación
SuppressWarnings
3
¡Maldición, esto realmente funcionó! Odio las vistas de desplazamiento, en serio.
Uday
2
Gracias @SuppressWarnings, realmente lo aprecio. Usted sugiere eliminar "app: layout_constraintBottom_toBottomOf =" parent "" 100%
Jignesh
1
+1, realmente útil, no sabía por qué los elementos dentro de mi vista de desplazamiento no estaban posicionados en el lugar que quería.
Jesús Hagiwara
1
Sí, claro ... pero para lograr el mismo requisito, siga el enfoque que he mencionado anteriormente.
Raghav Sharma
28

Usar NestedScrollView con viewport true funciona bien para mí

<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>

para Android x use esto

 <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>
Abhay Pratap
fuente
44
¡Gracias! Esto es lo que estaba buscando: android: fillViewport = "true" es la clave.
pratt
no olvide agregar dentro de nestedscrollview, si está utilizando AppBarLayoutapp:layout_behavior="@string/appbar_scrolling_view_behavior"
majurageerthan
1
Hasta la fecha, esta es la respuesta correcta!
Madfree
11

Para resumir, básicamente ajusta su android.support.constraint.ConstraintLayoutvista ScrollViewdentro del texto del *.xmlarchivo asociado con su diseño.

Ejemplo 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>

Nota 1: las barras de desplazamiento solo aparecen si se necesita un ajuste de alguna manera, incluido el teclado emergente.

Nota 2: Tampoco sería una mala idea asegurarse de que su ConstraintLayout sea lo suficientemente grande como para alcanzar la parte inferior y los lados de cualquier pantalla, especialmente si tiene un fondo, ya que esto garantizará que no haya espacios en blanco extraños . Puede hacer esto con espacios si nada más.

StackAttack
fuente
9

Simplemente use el diseño de restricción dentro NestedScrollViewo 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>

Eso es. disfruta tu codificación.

mahendren
fuente
4

Para hacer un diseño desplazable, el diseño es correcto. No será desplazable hasta que haya una razón para desplazarse (como en cualquier otro diseño). Por lo tanto, agregue suficiente contenido y será desplazable, al igual que con cualquier diseño (lineal, relativo, etc.). Sin embargo, no puede desplazarse correctamente en Blueprint o en modo de diseño diseño cuando diseña con ConstraintLayout y ScrollView.

Sentido:

Puede hacer un diseño de restricción desplazable, pero no se desplazará correctamente en el editor debido a un error / escenario que no se consideró. Pero aunque el desplazamiento no funciona en el editor, funciona en dispositivos. (He realizado varios COnstraintLayouts de desplazamiento, así que lo he probado)

Nota

En cuanto a su código. Al ScrollView le falta una etiqueta de cierre, no sé si es el caso en el archivo o si es un error de copiar y pegar, pero es posible que desee verlo.

Zoe
fuente
1
Para diseñar una disposición de restricción desplazable, en el estado actual de CL, es decir, puede expandir la altura del dispositivo y personalizarlo. Establezca la altura de los diseños (ScrollView y CL) en un número alto (por ejemplo, 2000DP) y simplemente realice el diseño normal. Tenga en cuenta que necesita una buena computadora para manejar la expansión, ya que los dispositivos personalizados realmente grandes exigen mucho de la computadora. Es una pena que CL no sea compatible con el diseño con SCrollViews, pero existen soluciones alternativas. como expandir la altura del dispositivo.
Zoe
3

Para completar las respuestas anteriores, estoy agregando el siguiente ejemplo, que también tiene en cuenta el uso de la barra de aplicaciones. Con este código, el editor de diseño de Android Studio parece funcionar bien con 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>
narko
fuente
2

necesita rodear mi diseño de restricción con una etiqueta ScrollView y le dio la propiedad android: isScrollContainer = "true".

Sam
fuente
1

Hay un error en la versión 2.2 que hace que sea imposible desplazarse por el diseño de restricción. Supongo que todavía existe. Puede usar LinearLayout o RelativeLayout alternativamente.

Además, consulte: ¿Es posible poner un diseño de restricción dentro de un ScrollView ?

Ege Kuzubasioglu
fuente
Sugiera usar RelativeLayout en su lugar, es el más cercano a ConstraintLayout
Zoe
El error ha sido corregido.
X09
1

Constraintlayout es el valor predeterminado para una nueva aplicación. Ahora estoy "aprendiendo a Android" y me costó mucho descubrir cómo manejar el código de "muestra" predeterminado para desplazarme cuando el teclado está activado. He visto muchas aplicaciones donde tengo que cerrar el teclado para hacer clic en el botón "enviar" y, a veces, no desaparece. Usando esta jerarquía [ScrollView / ContraintLayout / Fields] está funcionando bien ahora. De esta manera, podemos obtener los beneficios y la facilidad de uso de ConstraintLayout en una vista desplazable.

Renato Bourdon
fuente
1

Retire el botón inferior de la vista de desplazamiento anidado y tome la distribución lineal como padre. Agregue la vista de desplazamiento inferior y anidada como sus hijos. Funcionará absolutamente bien. En manifiesto para la actividad, use esto: esto levantará el botón cuando se abra el teclado

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>
Raghav Sharma
fuente
0

¡Puedes usarlo HorizontalScrollViewy funcionará también!

Morgan Koh
fuente
Por favor explique cómo usarlo
FindOutIslamNow
0

Así es como lo resolví:
si está utilizando ScrollView anidado, es decir, ScrollView dentro de un RestraintLayout, utilice la siguiente configuración para ScrollView en lugar de "WRAP_CONTENT" o "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">
Sajid2405
fuente
0

en la vista de desplazamiento, haga alto y ancho 0 agregue las restricciones Top_toBottomOfand y Bottom_toTopOf.

mohammad al-momani
fuente
Explique más esta respuesta, como un ejemplo de código para implementar.
Jake
0

Para mí, ninguna de las sugerencias sobre la eliminación de restricciones inferiores o la configuración del contenedor de desplazamiento en verdadero parecía funcionar. Lo que funcionó: expandir la altura de las vistas individuales / anidadas en mi diseño para que se "extiendan" más allá del padre utilizando la opción "Expandir verticalmente" del Editor de diseño de restricciones como se muestra a continuación.

Para cualquier enfoque, es importante que las líneas de vista previa punteadas se extiendan verticalmente más allá de las dimensiones superior o inferior del padre

Expandir verticalmente

kip2
fuente