Android - comment créer une mise en page de contraintes avec défilement?

150

Je veux créer une mise en page qui me permette de faire défiler vers le bas en utilisant la mise en page de contraintes, mais je ne sais pas comment m'y prendre. Devrait-il ScrollViewêtre le parent de ce ConstraintLayoutgenre de choses?

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

Ou l'inverse? Peut-être que quelqu'un peut m'indiquer un bon tutoriel à ce sujet ou donner un exemple, je n'arrive pas à en trouver un.

De plus, je ne sais pas s'il s'agit d'un bogue ou d'une configuration que je n'ai pas configurée mais j'ai vu des images comme celle-ci:

entrez la description de l'image ici

où il y a des composants en dehors du plan "rectangle bleu" mais ils sont visibles, tandis que de mon côté, si je place un composant sur "l'espace blanc", je ne peux pas le voir ou le déplacer n'importe où, et il apparaît sur l'arborescence des composants .

METTRE À JOUR :

J'ai trouvé un moyen de faire défiler la disposition de contrainte dans l'outil de conception, en utilisant une ligne de guidage horizontale pour abaisser la bordure de disposition de contrainte et l'étendre au-delà de l'appareil, après cela, vous pouvez utiliser la ligne directrice comme nouveau bas de la disposition de contrainte pour ancrer les composants.

gtovar
la source

Réponses:

85

Il semble que ça marche, je ne sais pas avec quelle dépendance tu travaillais mais dans celle-ci

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

Ça marche, c'est ce que j'ai fait

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

Faire défiler vers le hautentrez la description de l'image ici

Faire défiler vers le basentrez la description de l'image ici

Sealroto
la source
3
merci, le problème était que je ne pouvais pas faire défiler l'aperçu, donc construire quelque chose là-bas était impossible, mais j'ai découvert qu'en utilisant une ligne directrice, je peux abaisser la mise en page pour créer un espace défilable vide, puis la supprimer lorsque j'ai terminé
gtovar
2
cette réponse devrait être au top!
Kostanos
60

Il existe un type de contrainte qui rompt la fonction de défilement:

Assurez-vous simplement que vous n'utilisez cette contrainte sur aucune vue lorsque vous souhaitez que vous ConstraintLayoutpuissiez faire défiler avec ScrollView:

app:layout_constraintBottom_toBottomOf=“parent

Si vous les supprimez, votre parchemin devrait fonctionner.

Explication:

Définir la hauteur de l'enfant pour qu'elle corresponde à celle d'un ScrollViewparent est contradictoire avec ce que le composant est censé faire. Ce que nous voulons la plupart du temps, c'est que certains contenus de taille dynamique puissent faire défiler quand ils sont plus grands qu'un écran / cadre; faire correspondre la hauteur avec le parent ScrollViewforcerait tout le contenu à être affiché dans un cadre fixe (la hauteur du parent), annulant ainsi toute fonctionnalité de défilement.

Cela se produit également lorsque les composants enfants directs normaux sont définis sur layout_height="match_parent".

Si vous voulez que l'enfant de la ScrollViewcorresponde à la hauteur du parent lorsqu'il n'y a pas assez de contenu, définissez simplement android:fillViewportsur true pour le ScrollView.

Supprimer les avertissements
la source
1
@BasilBattikhi Ajouté une explication
SuppressWarnings
3
Merde, cela a fonctionné! Je déteste les vues de défilement, au sérieux.
Uday
2
Merci @SuppressWarnings, je l'apprécie vraiment. Vous suggérez de supprimer "app: layout_constraintBottom_toBottomOf =" parent "" fonctionne à 100%
Jignesh
1
+1, vraiment utile, ne savait pas pourquoi les éléments de mon scrollview ne se positionnaient pas à l'endroit que je voulais.
Jesús Hagiwara
1
Oui, d'accord ... mais pour atteindre la même exigence, suivez l'approche que j'ai mentionnée ci-dessus.
Raghav Sharma
28

Utiliser NestedScrollView avec viewport true fonctionne bien pour moi

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

pour android x utilisez ceci

 <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
la source
4
Merci! C'est ce que je cherchais - android: fillViewport = "true" est la clé.
pratt
n'oubliez pas d'ajouter à l'intérieur nestedscrollview, si vous utilisez AppBarLayoutapp:layout_behavior="@string/appbar_scrolling_view_behavior"
majurageerthan
1
À ce jour, c'est la bonne réponse!
madfree le
11

Pour résumer, vous enveloppez essentiellement votre android.support.constraint.ConstraintLayoutvue dans un ScrollViewdans le texte du *.xmlfichier associé à votre mise en page.

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

Remarque 1: les barres de défilement n'apparaissent que si un enroulement est nécessaire de quelque manière que ce soit, y compris le clavier qui apparaît.

Remarque 2: Ce ne serait pas non plus une mauvaise idée de vous assurer que votre ConstraintLayout est suffisamment grand pour atteindre le bas et les côtés d'un écran donné, surtout si vous avez un arrière-plan, car cela garantira qu'il n'y a pas d'espaces blancs impairs. . Vous pouvez le faire avec des espaces si rien d'autre.

StackAttack
la source
9

Utilisez simplement la disposition de contrainte à l'intérieur NestedScrollViewou 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>

c'est tout. profitez de votre codage.

Mahendren
la source
4

Pour créer une mise en page déroulante, la mise en page est correcte. Il ne pourra pas faire défiler jusqu'à ce qu'il y ait une raison de faire défiler (comme dans n'importe quelle autre disposition). Ajoutez donc suffisamment de contenu et il pourra faire défiler, comme avec n'importe quelle mise en page (linéaire, relative, etc.). Cependant, vous ne pouvez pas faire défiler correctement en Blueprint ou en mode Création lors de la conception avec ConstraintLayout et ScrollView.

Sens:

Vous pouvez créer un ConstraintLayout défilant, mais il ne défilera pas correctement dans l'éditeur en raison d'un bogue / scénario qui n'a pas été pris en compte. Mais même si le défilement ne fonctionne pas dans l'éditeur, il fonctionne sur les appareils. (J'ai fait plusieurs COnstraintLayouts défilants, donc je l'ai testé)

Remarque

Concernant votre code. Il manque une balise de fermeture au ScrollView, je ne sais pas si c'est le cas dans le fichier ou s'il s'agit d'un échec de copier-coller, mais vous voudrez peut-être l'examiner.

Zoé
la source
1
Pour concevoir une disposition de contraintes défilante, dans l'état actuel de CL, vous pouvez étendre la hauteur de l'appareil et la personnaliser. Réglez la hauteur des mises en page (ScrollView et CL) sur un nombre élevé (par exemple 2000DP) et faites simplement la conception normale. Notez que vous avez besoin d'un bon ordinateur pour gérer l'expansion, car les très gros appareils personnalisés exigent beaucoup de l'ordinateur. C'est dommage que CL ne prenne pas en charge la conception avec SCrollViews, mais il existe des solutions de contournement. comme l'augmentation de la hauteur de l'appareil.
Zoe
3

Pour compléter les réponses précédentes, j'ajoute l'exemple suivant, qui prend également en compte l'utilisation de l'AppBar. Avec ce code, l'éditeur de conception d'Android Studio semble fonctionner correctement avec le 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
la source
2

vous devez entourer ma mise en page de contrainte avec une balise ScrollView et lui donner la propriété android: isScrollContainer = "true".

Sam
la source
1

Il y a un bogue dans la version 2.2 qui rend impossible le défilement du ConstraintLayout. Je suppose que cela existe toujours. Vous pouvez également utiliser LinearLayout ou RelativeLayout.

Vérifiez également: Est-il possible de mettre une disposition de contrainte dans un ScrollView .

Ege Kuzubasioglu
la source
Suggérer d'utiliser RelativeLayout à la place, c'est le plus proche de ConstraintLayout
Zoe
Le bogue a été corrigé.
X09
1

Constraintlayout est la valeur par défaut pour une nouvelle application. J'apprends maintenant à Android et j'ai eu beaucoup de mal à comprendre comment gérer le code "exemple" par défaut pour faire défiler lorsqu'un clavier est activé. J'ai vu de nombreuses applications où je dois fermer le clavier pour cliquer sur le bouton «Soumettre» et parfois cela ne disparaît pas. En utilisant cette hiérarchie [ScrollView / ContraintLayout / Fields], cela fonctionne très bien maintenant. De cette façon, nous pouvons bénéficier des avantages et de la facilité d'utilisation de ConstraintLayout dans une vue déroulante.

Renato Bourdon
la source
1

Retirez le bouton du bas de la vue de défilement imbriquée et prenez la disposition linéaire comme parent. Ajoutez le bas et la vue de défilement imbriquée en tant que leurs enfants. Cela fonctionnera parfaitement. Dans le manifeste de l'activité, utilisez ceci - cela soulèvera le bouton lorsque le clavier sera ouvert

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
la source
0

Vous pouvez l'utiliser HorizontalScrollViewet cela fonctionnera aussi!

Morgan Koh
la source
Veuillez expliquer comment l'utiliser
FindOutIslamNow
0

Voici comment je l'ai résolu:
Si vous utilisez Nested ScrollView, c'est-à-dire ScrollView dans un ConstraintLayout, utilisez la configuration suivante pour ScrollView au lieu de "WRAP_CONTENT" ou "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
la source
0

dans scrollview, faites la hauteur et la largeur 0 ajoutez les contraintes Top_toBottomOf et Bottom_toTopOf c'est tout.

mohammad al-momani
la source
Veuillez expliquer cette réponse plus en détail, comme un exemple de code à implémenter.
Jake
0

Pour moi, aucune des suggestions concernant la suppression des contraintes de fond ni la définition du conteneur de défilement sur true ne semblait fonctionner. Ce qui a fonctionné: étendre la hauteur des vues individuelles / imbriquées dans ma mise en page afin qu'elles "s'étendent" au-delà du parent en utilisant l'option "Développer verticalement" de l'éditeur de disposition de contraintes comme indiqué ci-dessous.

Pour toute approche, il est important que les lignes d'aperçu en pointillé s'étendent verticalement au-delà des dimensions supérieure ou inférieure du parent

Développer verticalement

kip2
la source