androidandroid-layoutandroid-constraintlayoutandroid-xmlconstraintlayout-guideline

how to set items when soft keyboard is shown with using guideLine in constraint layout?


I am using ConstraintLayout in my application.

When soft keyboard is shown, I want to only button move above that And other items do not move up. I did this with using a scrollView.

Now I used guideLine to support all screen sizes, but after soft keyboard is shown, all items move to up again.

How should I use guideLine for this?

Manifest :

<activity
    android:name=".RegisterActivity"
    android:exported="false"
    android:windowSoftInputMode="adjustResize" />
<activity

Xml :

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <ScrollView
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toTopOf="@id/button_register_sendVerification"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:fillViewport="true"
        >

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <androidx.constraintlayout.widget.Guideline
                android:id="@+id/guideline_register_topParent"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="0.04" />

            <androidx.constraintlayout.widget.Guideline
                android:id="@+id/guideline_register_bottomParent"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="0.96" />

            <androidx.constraintlayout.widget.Guideline
                android:id="@+id/guideline_register_leftParent"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_constraintGuide_percent="0.08" />

            <androidx.constraintlayout.widget.Guideline
                android:id="@+id/guideline_register_rightParent"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_constraintGuide_percent="0.92" />

            <androidx.constraintlayout.widget.Guideline
                android:id="@+id/guideline_register_topMobileNumber"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="0.4"/>

            <androidx.constraintlayout.widget.Guideline
                android:id="@+id/guideline_register_bottomMobileNumber"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="0.49"/>

            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/textInputLayout_register_mobileNumber"
                style="@style/TextInputLayout.All"
                android:layout_width="0dp"
                android:layout_height="0dp"
                app:layout_constraintLeft_toRightOf="@id/guideline_register_leftParent"
                app:layout_constraintRight_toLeftOf="@id/guideline_register_rightParent"
                app:layout_constraintTop_toTopOf="@+id/guideline_register_topMobileNumber"
                app:layout_constraintBottom_toBottomOf="@id/guideline_register_bottomMobileNumber">

                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/textInputEditText_register_mobileNumber"
                    style="@style/TextInputEditText.All"
                    android:hint="@string/text_all_enterPhoneNumber"
                    android:inputType="phone"
                    android:maxLength="11"
                    android:textAlignment="center" />

            </com.google.android.material.textfield.TextInputLayout>


        </androidx.constraintlayout.widget.ConstraintLayout>

    </ScrollView>

    <Button
        android:id="@+id/button_register_sendVerification"
        style="@style/Button.all"
        android:layout_width="0dp"
        android:layout_height="48dp"
        android:text="@string/text_button_registerActivity_sendVerification"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

enter image description here


Solution

  • Unfortunately, all windowSoftInputModes will either shift the text view or hide the button.

    If you want to use a windowSoftInputMode of adjustResize, you will have to accommodate a ConstraintLayout that will change it's height when the soft keyboard is shown and hidden. Since a percentage Guideline specifies its position as a percentage of the ConstraintLayout's height (not the screen height), the Guideline's position will shift as the layout's height changes.

    In your case, the easiest way around this problem is to specify Guideline positions using an offset from the top of the ConstraintLayout. Since this offset will remain a constant distance from the top of the ConstraintLayout even as the ConstraintLayout's height changes, it will behave as you want.

    You can also leave the percent Guidelines in and convert them programmatically to fixed Guidelines. That way you can get the 40% offset regardless of the device.

    The following code will replace a percentage Guideline with a fixed offset Guideline.

    private fun replaceGuideline(layout: ConstraintLayout, oldGuideline: Guideline) {
        require(layout.height > 0) { "ConstraintLayout must have gone through a layout pass." }
        Guideline(layout.context).apply {
            val lp = ConstraintLayout.LayoutParams(
                ConstraintLayout.LayoutParams.WRAP_CONTENT,
                ConstraintLayout.LayoutParams.WRAP_CONTENT
            )
            lp.orientation = ConstraintLayout.LayoutParams.HORIZONTAL
            layoutParams = lp
            id = oldGuideline.id
            setGuidelineBegin(oldGuideline.top)
            layout.removeView(oldGuideline)
            layout.addView(this)
        }
    }
    

    You could also specify a windowSoftInputMode of adjustNothing (which is strangely missing from the docs). You can then detect when the soft keyboard is opened and closed to adjust the position of the button, although detecting soft keyboard status is oddly tricky.