/ / ConstraintLayout envolto em ScrollView ainda é redimensionado quando o teclado é aberto - android, android-scrollview, android-coordinatorlayout, android-constraintlayout

O ConstraintLayout envolto em ScrollView ainda é redimensionado quando o teclado é aberto - android, android-scrollview, android-coordinatorlayout, android-constraintlayout

Eu gostaria de poder abrir o teclado semmeu layout redimensionando. Eu não quero usar adjustNothing, porque eu preciso de uma das minhas vistas de baixo para levantar com o teclado. Eu também prefiro não usar adjustPan, porque isso levanta a totalidade do layout fora da tela que é uma espécie de feio.

Então, eu envolvi meu layout (ConstraintLayout) em um ScrollView assim:

<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<data>
<variable
name="viewModel"
type="com.mypackage.MyViewModel"/>
</data>

<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="none">

<!-- I don"t want anything in this ConstraintLayout to move or resize when I open the keyboard, hence why I wrapped it in a ScrollView. -->
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<FrameLayout
android:id="@+id/scene_container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<ImageView
android:id="@+id/scene"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"
android:background="@color/black"
android:scaleType="fitCenter"
android:src="@drawable/grumpy"/>
</FrameLayout>

<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".7"/>

<View
android:id="@+id/status_bar"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="@color/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/guideline"/>

<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="48dp"
android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/status_bar"/>

</android.support.constraint.ConstraintLayout>

</ScrollView>

<!-- The bottom sheet contains a 48dp high peekable area (a bar with an EditText) that I need to raise with the keyboard. -->
<include
android:id="@+id/bottom_sheet"
layout="@layout/bottom_sheet"
app:viewModel="@{viewModel}"/>

</android.support.design.widget.CoordinatorLayout>

Isso funciona bem nas duas primeiras vezes em que abro o teclado. Aqui está o problema bizarro que eu estou tendo. Cada TERCEIRO vez que eu levanto o teclado, meu layout é redimensionado e espremido como se o ScrollView não estivesse lá. Isso ocorre consistentemente a cada TERCEIRO vez que eu abro o teclado assim:

1) Open keyboard. Layout remains same size.
Close keyboard.
2) Open keyboard. Layout remains same size.
Close keyboard.
3) Open keyboard. *LAYOUT RESIZES/SQUISHES TOGETHER!*
Close keyboard.

The above cycle repeats as I continue to open/close the keyboard.

Alguma idéia de como resolver isso? Por que o layout é redimensionado toda vez que eu abro o teclado?

Respostas:

2 para resposta № 1

Na verdade, se você usar match_parent como o tamanho de ScrollView criança, também irá redimensionar quando o teclado irá aparecer e encaixar ScrollView Tamanho.

Para entender como ScrollView trabalho, você pode pensar em um navegador. Em cada link que você vá, se a página não se encaixar nas janelas do seu navegador, você verá a barra de rolagem para permitir que você navegue na página. ScrollView são os mesmos, você só precisa dar a eles o tamanho que você quer ocupar na tela (como a janela do navegador) e você pode colocar tudo nele (como a página do site), mesmo que seja maior que o ScrollView Tamanho.

De acordo com isso, seu ConstraintLayout precisa de um tamanho fixo. Poderia ser wrap_content se você quiser que o usuário acesse todo o componente nele. Este não é o seu caso. Você quer que ele mantenha seu tamanho original, ou seja, como eu posso ver no seu código, também o tamanho do seu primeiro CoordinatorLayout.

A única maneira que encontrei para consertar um interior ConstraintLayout para o tamanho da visualização original é por código.

Vamos simplificar o seu xml para o exemplo:

<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:id="@+id/parentView"
android:layout_height="match_parent">

<ScrollView
android:id="@+id/scrollViewItem"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.constraint.ConstraintLayout
android:id="@+id/childView"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<!--ALL YOUR ITEMS-->

</android.support.constraint.ConstraintLayout>

</ScrollView>

</android.support.design.widget.CoordinatorLayout>

Você precisa corrigir o tamanho de childView no carregamento da tela. No onCreate, você pode adicionar este código:

private int first = 0;

public class ConstaintLayoutCanScroll extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

first = childView.getMeasuredHeight();

final CoordinatorLayout parentView = findViewById(R.id.parentView);
parentView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (first < parentView.getMeasuredHeight()) {
ConstraintLayout childView = findViewById(R.id.childView);
childView.setMinHeight(parentView.getMeasuredHeight());
first = childView.getMeasuredHeight();
}
return true;
}
});

}

}

Eu uso um ouvinte porque a OnCreate, o tamanho ainda não é init. first está aqui porque onPreDraw Não é chamado apenas uma vez pelo Android. É uma variável da classe que eu fixo para 0 por padrão.


0 para resposta № 2

Usando match_parent como o tamanho de ScrollView criança não é ideal. Você deve preferir usar tamanho fixo ou wrap_content. Na sua configuração atual, o ConstraintLayout tenta definir a sua altura para o ScrollView"s altura e isso muda de acordo com o teclado sendo exibido ou não.

Você poderia tentar definir o seu ConstraintLayout para uma altura fixa, assim que é exibido na tela.

Para testar se essa abordagem funciona, você pode tentar definir, por exemplo android:layout_height="400dp" Nas suas ConstraintLayout e veja se o "ciclo" que você mencionou estará acontecendo ou não. Se isso funcionar, você pode passar a usar uma dimensão real do ConstraintLayout combinando o tamanho da tela.