Android - como fazer um layout de restrição rolável?

149

Quero criar um layout que me permita rolar para baixo usando o layout de restrição, mas não sei como fazê-lo. Deveria ScrollViewser o pai desse ConstraintLayouttipo?

<?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 o contrário? Talvez alguém possa me indicar um bom tutorial sobre isso ou dar um exemplo, parece que não consigo encontrar um.

Além disso, não sei se isso é um bug ou alguma configuração que não defini, mas vi imagens como esta:

insira a descrição da imagem aqui

onde existem alguns componentes fora do blueprint "retângulo azul", no entanto eles são visíveis, enquanto do meu lado, se eu colocar um componente no "espaço em branco", não consigo vê-lo ou movê-lo para qualquer lugar, e ele aparece na árvore de componentes .

ATUALIZAÇÃO:

Encontrei uma maneira de tornar o layout da restrição rolável na ferramenta de design, usando uma diretriz horizontal para empurrar a borda do layout da restrição e estendê-la para além do dispositivo. Depois disso, você pode usar a diretriz como a nova parte inferior do layout da restrição. ancorar os componentes.

gtovar
fonte

Respostas:

84

Parece que está funcionando, não sei com que dependência você estava trabalhando, mas neste

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

Está funcionando, foi o que eu fiz

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

Scroll Topinsira a descrição da imagem aqui

Scroll Bottominsira a descrição da imagem aqui

sealroto
fonte
3
obrigado, o problema era que eu não podia rolar na visualização, então construindo algo impossível, mas descobri que, usando uma diretriz, posso puxar o layout para criar um espaço de rolagem vazio e removê-lo quando terminar
gtovar
1
esta resposta deve estar no topo!
Kostanos
60

Há um tipo de restrição que quebra a função de rolagem:

Apenas certifique-se de não usar esta restrição em nenhuma visualização ao desejar que você ConstraintLayoutpossa rolar com ScrollView:

app:layout_constraintBottom_toBottomOf=“parent

Se você removê-los, seu pergaminho deve funcionar.

Explicação:

Definir a altura da criança para coincidir com a dos ScrollViewpais é contraditório com o que o componente deve fazer. O que queremos na maioria das vezes é que algum conteúdo de tamanho dinâmico seja rolável quando for maior que uma tela / quadro; combinar a altura com o pai ScrollViewforçaria todo o conteúdo a ser exibido em um quadro fixo (a altura do pai), invalidando assim qualquer funcionalidade de rolagem.

Isso também acontece quando os componentes filhos diretos regulares são definidos como layout_height="match_parent".

Se você deseja que o filho de ScrollViewcorresponda à altura do pai, quando não há conteúdo suficiente, simplesmente defina android:fillViewportcomo true para o ScrollView.

Suprimir avisos
fonte
1
@BasilBattikhi Adicionada uma explicação
SuppressWarnings
3
Porra, isso realmente funcionou! Eu odeio vistas de rolagem, a sério.
Uday
2
Obrigado @SuppressWarnings, realmente aprecio isso. Você sugere que a remoção de "app: layout_constraintBottom_toBottomOf =" parent "" funcione 100%
Jignesh
1
O +1, realmente útil, não sabia por que os itens na minha visualização de rolagem não estavam posicionados no local que eu queria.
Jesús Hagiwara
1
Sim, certo ... mas para atingir o mesmo requisito, siga a abordagem que mencionei acima.
Raghav Sharma
28

Usar o NestedScrollView com a viewport true está funcionando bem para mim

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

 <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
fonte
4
Obrigado! Era isso que eu procurava - android: fillViewport = "true" é a chave.
Pratt #
não se esqueça de adicionar dentro nestedscrollview, se você estiver usando AppBarLayoutapp:layout_behavior="@string/appbar_scrolling_view_behavior"
majurageerthan de 16/01
1
Até o momento, esta é a resposta correta!
madfree 15/06
11

Para resumir, você basicamente agrupa sua android.support.constraint.ConstraintLayoutexibição em um ScrollViewtexto do *.xmlarquivo associado ao seu layout.

Exemplo 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: As barras de rolagem aparecem apenas se for necessário um agrupamento, incluindo o teclado aparecendo.

Nota 2: Também não seria uma má idéia garantir que o ConstraintLayout seja grande o suficiente para alcançar a parte inferior e as laterais de qualquer tela, especialmente se você tiver um plano de fundo, pois isso garantirá que não haja espaço em branco estranho . Você pode fazer isso com espaços, se nada mais.

StackAttack
fonte
9

Basta usar o layout de restrição dentro 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>

é isso aí. aproveite sua codificação.

Mahendren
fonte
4

Para criar um layout rolável, o layout está correto. Não será rolável até que haja motivo para rolar (como em qualquer outro layout). Portanto, adicione conteúdo suficiente e ele poderá ser rolado, como em qualquer layout (Linear, Relativo etc.). No entanto, você não pode rolar corretamente no Blueprint ou no modo de design ao projetar com ConstraintLayout e ScrollView.

Significado:

Você pode criar um ConstraintLayout rolável, mas ele não rolará corretamente no editor devido a um bug / cenário que não foi considerado. Mas, mesmo que a rolagem não funcione no editor, ela funciona em dispositivos. (Eu fiz vários COnstraintLayouts de rolagem, então testei)

Nota

Em relação ao seu código. Está faltando uma tag de fechamento no ScrollView, não sei se é o caso no arquivo ou se há uma falha de copiar e colar, mas você pode querer dar uma olhada.

Zoe
fonte
1
Para criar um layout de restrição rolável, no estado atual de CL, ou seja, você pode expandir a altura do dispositivo e personalizá-lo. Defina a altura dos layouts (ScrollView e CL) para um número alto (por exemplo, 2000DP) e faça o design normal. Observe que você precisa de um bom computador para lidar com a expansão, pois os dispositivos personalizados realmente grandes exigem muito do computador. É uma pena que o CL não suporte o design com SCrollViews, mas existem soluções alternativas. como expandir a altura do dispositivo.
Zoe
3

Para concluir as respostas anteriores, estou adicionando o exemplo a seguir, que também leva em consideração o uso da AppBar. Com esse código, o editor de design do Android Studio parece funcionar bem com o 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
fonte
2

você precisa cercar meu layout de restrição com uma tag ScrollView e fornecer a propriedade android: isScrollContainer = "true".

Sam
fonte
1

Há um erro na versão 2.2 que torna impossível rolar o ConstraintLayout. Eu acho que ainda existe. Você pode usar LinearLayout ou RelativeLayout como alternativa.

Além disso, confira: É possível colocar um layout de restrição dentro de um ScrollView .

Ege Kuzubasioglu
fonte
Sugira a utilização de RelativeLayout, pois é o mais próximo a ConstraintLayout
Zoe
O bug foi corrigido.
X09
1

O layout de restrição é o padrão para um novo aplicativo. Agora estou "aprendendo com o Android" e tive muita dificuldade em descobrir como lidar com o código "amostra" padrão para rolar quando um teclado está ativo. Eu já vi muitos aplicativos nos quais tenho que fechar o teclado para clicar no botão "enviar" e, às vezes, ele não desaparece. Usando essa hierarquia [ScrollView / ContraintLayout / Fields], está funcionando muito bem agora. Dessa forma, podemos obter os benefícios e a facilidade de uso do ConstraintLayout em uma exibição rolável.

Renato Bourdon
fonte
1

Retire o botão inferior do nestedscrollview e use o layout linear como pai. Adicione bottom e nestedscrollview como seus filhos. Funcionará absolutamente bem. No manifesto da atividade, use isso - isso aumentará o botão quando o teclado for aberto

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

Você pode usar HorizontalScrollViewe vai funcionar também!

Morgan Koh
fonte
Por favor, explique como usá-lo
FindOutIslamNow
0

Foi assim que resolvi:
Se você estiver usando o ScrollView aninhado, ou seja, o ScrollView dentro de um ConstraintLayout, use a seguinte configuração para o ScrollView em vez 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
fonte
0

no scrollview make height e width 0 adicione restrições Top_toBottomOfand Bottom_toTopOf, é isso.

mohammad al-momani
fonte
Por favor, explique mais esta resposta, como um exemplo de código a ser implementado.
Jake
0

Para mim, nenhuma das sugestões sobre a remoção de restrições inferiores ou a configuração do contêiner de rolagem para true parecia funcionar. O que funcionou: expanda a altura das visualizações individuais / aninhadas no meu layout para que elas "se estendam" além do pai usando a opção "Expandir verticalmente" do Editor de layout de restrições, como mostrado abaixo.

Para qualquer abordagem, é importante que as linhas de visualização pontilhada se estendam verticalmente além das dimensões superior ou inferior do pai

Expandir verticalmente

kip2
fonte