Android: come creare un vincolo scorrevole?


149

Voglio creare un layout che mi consenta di scorrere verso il basso utilizzando il layout dei vincoli, ma non so come procedere. Dovrebbe ScrollViewessere il genitore del ConstraintLayoutsimile?

<?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 viceversa? Forse qualcuno può indicarmi un buon tutorial su questo o fare un esempio, non riesco a trovarne uno.

Inoltre, non so se questo è un bug o una configurazione che non ho impostato ma ho visto immagini come questa:

inserisci qui la descrizione dell'immagine

dove ci sono alcuni componenti al di fuori del progetto "rettangolo blu", ma sono visibili, mentre dalla mia parte se posiziono un componente nello "spazio bianco" non riesco a vederlo o spostarlo da nessuna parte, e appare nella struttura dei componenti .

AGGIORNARE :

Ho trovato un modo per rendere scorrevole il layout del vincolo nello strumento di progettazione, utilizzando una linea guida orizzontale per spingere verso il basso il bordo del layout del vincolo ed estenderlo oltre il dispositivo, dopodiché è possibile utilizzare la linea guida come nuovo fondo del layout del vincolo per ancorare i componenti.

Risposte:


84

Sembra che funzioni, non so con quale dipendenza stavi lavorando ma in questo

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

Funziona, questo è quello che ho fatto

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

Scorri in altoinserisci qui la descrizione dell'immagine

Scorri in bassoinserisci qui la descrizione dell'immagine


3
grazie, il problema era che non ero in grado di scorrere l'anteprima, quindi costruire qualcosa lì era impossibile ma ho scoperto che usando una linea guida posso abbassare il layout per rendere lo spazio scorrevole vuoto e poi rimuoverlo quando ho finito
gtovar

1
questa risposta dovrebbe essere al top!
Kostanos,

60

Esiste un tipo di vincolo che interrompe la funzione di scorrimento:

Assicurati solo di non utilizzare questo vincolo in nessuna vista quando vuoi ConstraintLayoutche sia scorrevole con ScrollView:

app:layout_constraintBottom_toBottomOf=“parent

Se li rimuovi, lo scorrimento dovrebbe funzionare.

Spiegazione:

Impostare l'altezza del bambino in modo che corrisponda a quello di un ScrollViewgenitore è contraddittorio rispetto a ciò che il componente è destinato a fare. Ciò che vogliamo il più delle volte è che alcuni contenuti di dimensioni dinamiche siano scorrevoli quando sono più grandi di uno schermo / cornice; la corrispondenza dell'altezza con il genitore ScrollViewforzerebbe la visualizzazione di tutto il contenuto in un frame fisso (l'altezza del genitore), invalidando così qualsiasi funzionalità di scorrimento.

Ciò accade anche quando sono impostati i componenti figlio diretti regolari layout_height="match_parent" .

Se si desidera che il figlio di the ScrollViewcorrisponda all'altezza del genitore quando non c'è abbastanza contenuto, impostare semplicemente android:fillViewportsu true per il ScrollView.


1
@BasilBattikhi Aggiunta una spiegazione
SuppressWarnings,

3
Dannazione, in realtà ha funzionato! Odio le visualizzazioni di scorrimento, sul serio.
Uday

2
Grazie @SuppressWarnings, lo apprezzo molto. Hai suggerito di rimuovere "app: layout_constraintBottom_toBottomOf =" parent "" funziona al 100%
Jignesh

1
Il +1, davvero utile, non sapeva perché gli oggetti all'interno della mia vista di scorrimento non si posizionassero nel punto desiderato.
Jesús Hagiwara,

1
Sì giusto ... ma per raggiungere lo stesso requisito segui l'approccio che ho menzionato sopra.
Raghav Sharma,

28

Utilizzare NestedScrollView con viewport true funziona bene per me

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

per Android x usa questo

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

4
Grazie! Questo è quello che stavo cercando - android: fillViewport = "true" è la chiave.
pratt,

non dimenticare di aggiungere all'interno di nestedscrollview, se stai usando AppBarLayoutapp:layout_behavior="@string/appbar_scrolling_view_behavior"
majurageerthan

1
Ad oggi, questa è la risposta corretta!
madfree il

11

Per riassumere, fondamentalmente si avvolge la android.support.constraint.ConstraintLayoutvista in a ScrollViewall'interno del testo del *.xmlfile associato al layout.

Esempio 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: le barre di scorrimento vengono visualizzate solo se è necessario un avvolgimento, inclusa la comparsa della tastiera.

Nota 2: Inoltre, non sarebbe una cattiva idea assicurarsi che ConstraintLayout sia abbastanza grande da raggiungere la parte inferiore e i lati di una determinata schermata, soprattutto se si dispone di uno sfondo, in quanto ciò garantirà che non ci siano spazi bianchi dispari . Puoi farlo con spazi se non altro.


9

Basta usare il layout dei vincoli all'interno 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>

questo è tutto. goditi la tua programmazione.


4

Per creare un layout scorrevole, il layout è corretto. Non sarà scorrevole fino a quando non vi è motivo di scorrere (proprio come in qualsiasi altro layout). Quindi aggiungi abbastanza contenuto e sarà scorrevole, proprio come con qualsiasi layout (lineare, relativo, ecc.). Tuttavia, non è possibile scorrere correttamente in Blueprint o in modalità progettazione progettazione durante la progettazione con ConstraintLayout e ScrollView.

Senso:

È possibile effettuare un ConstraintLayout scorrevole, ma non scorrerà correttamente nell'editor a causa di un bug / scenario che non è stato considerato. Ma anche se lo scorrimento non funziona nell'editor, funziona sui dispositivi. (Ho effettuato diversi layout COnstraintLayout scorrevoli, quindi l'ho provato)

Nota

Per quanto riguarda il tuo codice. In ScrollView manca un tag di chiusura, non so se è il caso nel file o se si tratta di un errore copia-incolla, ma potresti volerlo guardare.


1
Per progettare un vincolo scorrevole, nello stato attuale di CL, è possibile espandere l'altezza del dispositivo e renderlo personalizzato. Impostare l'altezza dei layout (ScrollView e CL) su un numero elevato (ad es. 2000DP) ed eseguire semplicemente la progettazione normale. Si noti che è necessario un buon computer per gestire l'espansione, poiché i dispositivi personalizzati davvero grandi richiedono molto dal computer. È un peccato che CL non supporti la progettazione con SCrollViews, ma ci sono soluzioni alternative. come espandere l'altezza del dispositivo.
Zoe,

3

Per completare le risposte precedenti, sto aggiungendo il seguente esempio, che tiene conto anche dell'uso della AppBar. Con questo codice, l'editor di progettazione di Android Studio sembra funzionare bene 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>

2

devi circondare il mio layout di vincolo con un tag ScrollView e dargli la proprietà android: isScrollContainer = "true".



1

Constraintlayout è l'impostazione predefinita per una nuova app. Sto "imparando ad Android" ora e ho avuto delle difficoltà a capire come gestire il codice "campione" predefinito da scorrere quando una tastiera è in funzione. Ho visto molte app in cui devo chiudere la tastiera per fare clic sul pulsante "Invia" e talvolta non scompare. Usando questa gerarchia [ScrollView / ContraintLayout / Fields] ora funziona bene. In questo modo possiamo ottenere i vantaggi e la facilità d'uso da ConstraintLayout in una vista scorrevole.


1

Estrarre il pulsante in basso da nestedscrollview e prendere linearlayout come genitore. Aggiungi bottom e nestedscrollview come i loro figli. Funzionerà assolutamente bene. In manifest per l'attività usa questo: questo solleverà il pulsante quando la tastiera è aperta

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

Ecco come l'ho risolto:
se si utilizza ScrollView annidato, ovvero ScrollView in un ConstraintLayout, utilizzare la seguente configurazione per ScrollView anziché "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">

0

in scrollview crea altezza e larghezza 0 aggiungi i vincoli Top_toBottomOfand Bottom_toTopOf questo è tutto.


Spiega di più questa risposta, ad esempio un esempio di codice da implementare.
Jake,

0

Per me, nessuno dei suggerimenti sulla rimozione dei vincoli di fondo o sull'impostazione del contenitore di scorrimento su true sembrava funzionare. Cosa ha funzionato: espandi l'altezza delle viste individuali / nidificate nel mio layout in modo che "si estendano" oltre il genitore utilizzando l'opzione "Espandi verticalmente" dell'editor del layout dei vincoli come mostrato di seguito.

Per qualsiasi approccio, è importante che le linee di anteprima tratteggiate si estendano verticalmente oltre le dimensioni superiore o inferiore del genitore

Espandi verticalmente

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.