Android - jak zrobić przewijalny układ ograniczeń?

150

Chcę utworzyć układ, który pozwala mi przewijać w dół za pomocą układu z ograniczeniami, ale nie wiem, jak się do tego zabrać. Czy powinien ScrollViewbyć rodzicem ConstraintLayouttakiej osoby?

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

Albo na odwrót? Może ktoś wskaże mi dobry tutorial na ten temat lub poda przykład, nie mogę go znaleźć.

Nie wiem też, czy to błąd, czy konfiguracja, której nie ustawiłem, ale widziałem takie obrazy:

wprowadź opis obrazu tutaj

gdzie są jakieś komponenty na zewnątrz "niebieskiego prostokąta" ale są widoczne, podczas gdy po mojej stronie, jeśli umieszczę komponent na "białej przestrzeni", nie mogę go zobaczyć ani nigdzie przenieść i pojawia się na drzewie komponentów .

AKTUALIZACJA :

Znalazłem sposób na przewijanie układu ograniczeń w narzędziu do projektowania, używając poziomej prowadnicy, aby przesunąć w dół obramowanie układu ograniczeń i rozciągnąć je poza urządzenie, a następnie można użyć prowadnicy jako nowego dołu układu ograniczeń do zakotwicz komponenty.

gtovar
źródło

Odpowiedzi:

85

Wygląda na to, że działa, nie wiem, z jaką zależnością pracowałeś, ale w tej

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

Działa, to właśnie zrobiłem

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

Przewiń do górywprowadź opis obrazu tutaj

Przewiń do dołuwprowadź opis obrazu tutaj

sealroto
źródło
3
dzięki, problem polegał na tym, że nie mogłem przewijać podglądu, więc zbudowanie czegoś tam było niemożliwe, ale dowiedziałem się, że korzystając z prowadnicy, mogę
rozwinąć
2
ta odpowiedź powinna być najlepsza!
Kostanos
60

Istnieje rodzaj ograniczenia, które przerywa funkcję przewijania:

Tylko upewnij się, że nie używasz tego ograniczenia w żadnym widoku, gdy chcesz, ConstraintLayoutaby Twój widok był przewijalny ScrollView:

app:layout_constraintBottom_toBottomOf=“parent

Jeśli je usuniesz, twój zwój powinien działać.

Wyjaśnienie:

Ustawienie wzrostu dziecka tak, aby odpowiadało wysokości ScrollViewrodzica, jest sprzeczne z tym, do czego ma on służyć. W większości przypadków chcemy, aby niektóre treści o rozmiarze dynamicznym dały się przewijać, gdy są większe niż ekran / ramka; dopasowanie wzrostu do rodzicaScrollView wymusiłoby wyświetlenie całej treści w stałej ramce (wysokość elementu nadrzędnego), a tym samym unieważniło jakąkolwiek funkcję przewijania.

Dzieje się tak również, gdy ustawiono zwykłe bezpośrednie komponenty podrzędne layout_height="match_parent".

Jeśli chcesz, aby element podrzędny elementu podrzędnego ScrollViewodpowiadał wysokości elementu nadrzędnego, gdy nie ma wystarczającej ilości treści, po prostu ustaw wartość android:fillViewporttrue dla ScrollView.

Tłumić ostrzeżenia
źródło
1
@BasilBattikhi Dodano wyjaśnienie
SuppressWarnings
3
Cholera, to faktycznie zadziałało! Poważnie nienawidzę widoków przewijania.
Uday
2
Dziękuję @SuppressWarnings, naprawdę to doceniam. Wskazówka dotycząca usunięcia „app: layout_constraintBottom_toBottomOf =„ rodzic ”” działa w 100%
Jignesh
1
+1, naprawdę przydatne, nie wiedziałem, dlaczego elementy w widoku przewijania nie są pozycjonowane w wybranym miejscu.
Jesús Hagiwara
1
Tak, zgadza się ... ale aby osiągnąć ten sam wymóg, postępuj zgodnie z podejściem, o którym wspomniałem powyżej.
Raghav Sharma
28

Użyj NestedScrollView z widocznym obszarem true działa dobrze dla mnie

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

dla Androida x użyj tego

 <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
źródło
4
Dzięki! Tego właśnie szukałem - android: fillViewport = "true" to klucz.
pratt
nie zapomnij dodać wewnętrznego widoku zagnieżdżonego przewijania, jeśli używasz AppBarLayoutapp:layout_behavior="@string/appbar_scrolling_view_behavior"
majurageerthan
1
Do tej pory to jest poprawna odpowiedź!
madfree
11

Podsumowując, po prostu zawijasz android.support.constraint.ConstraintLayoutwidok w ScrollViewtekście*.xml pliku skojarzonego z układem.

Przykład 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>

Notatka 1: Paski przewijania pojawiają się tylko wtedy, gdy w jakikolwiek sposób potrzebne jest zawijanie, w tym wyskakująca klawiatura.

Uwaga 2: Nie byłoby również złym pomysłem upewnienie się, że Twój ConstraintLayout jest wystarczająco duży, aby sięgał do dołu i boków dowolnego ekranu, szczególnie jeśli masz tło, ponieważ zapewni to, że nie ma dziwnych białych znaków . Możesz to zrobić ze spacjami, jeśli nic innego.

StackAttack
źródło
9

Po prostu użyj układu ograniczeń wewnątrz NestedScrollViewlub 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>

Otóż ​​to. miłego kodowania.

mahendren
źródło
4

Aby utworzyć przewijalny układ, układ jest poprawny. Nie będzie można go przewijać, dopóki nie będzie powodu do przewijania (tak jak w każdym innym układzie). Dodaj więc wystarczającą ilość treści, a będzie można ją przewijać, tak jak w przypadku każdego układu (liniowego, względnego itp.). Jednak podczas projektowania za pomocą ConstraintLayout i ScrollView nie można prawidłowo przewijać w trybie Blueprint ani projektowania .

Znaczenie:

Możesz stworzyć przewijalny ConstraintLayout, ale nie będzie on przewijał się poprawnie w edytorze z powodu błędu / scenariusza, który nie był brany pod uwagę. Ale chociaż przewijanie nie działa w edytorze, działa na urządzeniach. (Zrobiłem kilka przewijania COnstraintLayouts, więc przetestowałem to)

Uwaga

Odnośnie twojego kodu. W ScrollView brakuje zamykającego tagu, nie wiem, czy tak jest w pliku, czy też jest to błąd typu „kopiuj-wklej”, ale możesz chcieć go obejrzeć.

Zoe
źródło
1
Aby zaprojektować przewijalny układ ograniczenia, w obecnym stanie CL, to znaczy, można zwiększyć wysokość urządzenia i dostosować je do własnych potrzeb. Ustaw wysokość układów (ScrollView i CL) na dużą liczbę (np. 2000DP) i po prostu wykonaj normalne projektowanie. Zwróć uwagę, że potrzebujesz dobrego komputera do obsługi rozszerzenia, ponieważ naprawdę duże niestandardowe urządzenia wymagają dużo od komputera. Szkoda, że ​​CL nie obsługuje projektowania za pomocą SCrollViews, ale są obejścia. takie jak zwiększenie wysokości urządzenia.
Zoe
3

Aby uzupełnić poprzednie odpowiedzi dodaję następujący przykład, który również uwzględnia użycie AppBar. Z tym kodem wydaje się, że edytor projektowania Android Studio działa dobrze z 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
źródło
2

musisz otoczyć mój układ ograniczenia znacznikiem ScrollView i nadać mu właściwość android: isScrollContainer = "true".

Sam
źródło
1

W wersji 2.2 występuje błąd uniemożliwiający przewijanie ConstraintLayout. Myślę, że nadal istnieje. Alternatywnie można użyć LinearLayout lub RelativeLayout.

Zobacz również: czy można umieścić układ ograniczeń wewnątrz ScrollView .

Ege Kuzubasioglu
źródło
Zaproponuj zamiast tego użycie RelativeLayout, jest najbliżej ConstraintLayout
Zoe
Błąd został naprawiony.
X09
1

Układ ograniczeń jest ustawieniem domyślnym dla nowej aplikacji. „Uczę się teraz Androida” i bardzo trudno mi było wymyślić, jak obsłużyć domyślny „przykładowy” kod do przewijania, gdy klawiatura jest włączona. Widziałem wiele aplikacji, w których muszę zamknąć klawiaturę, aby kliknąć przycisk „wyślij”, a czasami nie znika. Używając tej hierarchii [ScrollView / ContraintLayout / Fields], teraz działa dobrze. W ten sposób możemy czerpać korzyści i łatwość użycia z ConstraintLayout w przewijalnym widoku.

Renato Bourdon
źródło
1

Wyjmij dolny przycisk z zagnieżdżonego widoku przewijania i jako nadrzędny wybierz układ liniowy. Dodaj dolny i zagnieżdżony widok przewijania jako ich dzieci. Będzie działać absolutnie dobrze. W manifeście dla działania użyj tego - spowoduje to podniesienie przycisku, gdy klawiatura jest otwarta

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
źródło
0

Możesz użyć HorizontalScrollViewi to również zadziała!

Morgan Koh
źródło
Proszę wyjaśnić, jak go używać
FindOutIslamNow
0

Oto jak to rozwiązałem:
Jeśli używasz zagnieżdżonego ScrollView, tj. ScrollView w ConstraintLayout, użyj następującej konfiguracji dla ScrollView zamiast „WRAP_CONTENT” lub „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
źródło
0

w widoku scrollview ustaw wysokość i szerokość 0, dodaj ograniczenia Top_toBottomOfand Bottom_toTopOf i to wszystko.

mohammad al-momani
źródło
Proszę wyjaśnić tę odpowiedź bardziej, na przykład przykład kodu do zaimplementowania.
Jake
0

Wydaje mi się, że żadna z sugestii dotyczących usuwania dolnych ograniczeń ani ustawiania kontenera przewijania na wartość true nie działa. Co zadziałało: zwiększ wysokość pojedynczych / zagnieżdżonych widoków w moim układzie, aby „rozciągały się” poza element nadrzędny, używając opcji „Rozwiń w pionie” w Edytorze układu ograniczeń, jak pokazano poniżej.

W każdym podejściu ważne jest, aby kropkowane linie podglądu rozciągały się pionowo poza górne lub dolne wymiary elementu nadrzędnego

Rozwiń w pionie

kip2
źródło