Search code examples
androidandroid-layoutandroid-softkeyboardandroid-gridlayout

GridLayout doesn't reset after size adjustment from hiding keyboard


My Android fragment is using the support GridLayout to display equally-spaced views (first image). In my manifest I'm changing how the soft keyboard displays so it resizes the GridLayout when I tap on the EditText and the keyboard is displayed (second image):

android:windowSoftInputMode="adjustResize|stateHidden"

When the soft keyboard is hidden, the GridLayout does not reset back to its initial size (last image).

Screenshot showing full screen Screenshot with soft keyboard open Screenshot with soft keyboard closed and GridLayout no longer looking like first screenshot

Any idea on how to get the GridLayout to go back to its original configuration in the first screenshot? I know if I remove the android:windowSoftInputMode from the manifest the problem goes away, but that is not something I can change in another app from which this demo is created.

Here's the fragment's layout file:

<android.support.v7.widget.GridLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:grid="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    grid:columnCount="2"
    grid:rowCount="3"
    grid:orientation="horizontal">

    <EditText
        android:layout_width="100sp"
        android:layout_height="80sp"
        grid:layout_gravity="center"
        grid:layout_columnWeight="1"
        grid:layout_rowWeight="1"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="80sp"
        grid:layout_gravity="center"
        grid:layout_columnWeight="1"
        grid:layout_rowWeight="1"
        android:text="B"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="80sp"
        grid:layout_gravity="center"
        grid:layout_columnWeight="1"
        grid:layout_rowWeight="1"
        android:text="C"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="80sp"
        grid:layout_gravity="center"
        grid:layout_columnWeight="1"
        grid:layout_rowWeight="1"
        android:text="D"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="80sp"
        grid:layout_gravity="center"
        grid:layout_columnWeight="1"
        grid:layout_rowWeight="1"
        android:text="E"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="80sp"
        grid:layout_gravity="center"
        grid:layout_columnWeight="1"
        grid:layout_rowWeight="1"
        android:text="F"/>

</android.support.v7.widget.GridLayout>

Solution

  • Apparently there is a bug in GridLayout.Axis.layout() (which is called in onLayout())

    If you indeed need to use GridLayout calling requestLayout to fire its private method invalidateStructure() seems to address the problem.

    class FixedGridLayout : GridLayout {
        constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)
        constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
        constructor(context: Context) : super(context)
    
        override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
            super.onLayout(changed, left, top, right, bottom)
            if (changed) {
                post {
                    requestLayout()
                }
            }
        }
    }