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 № 1Na 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.