204

I would like to adjust/re-size the layout when the soft-keyboard activated, as below:

Before and After:

enter image description hereenter image description here


Found couple resources in SO:

  1. How to keep all fields and texts visible while the soft keyboard is shown
  2. android soft keyboard spoils layout when appears
  3. Adjust layout when soft keyboard is on

But the questions & answers are rather ambiguous, here's the question with clearer picture of what I want.

Requirements:

  • It should work on phone with any screen sizes.
  • Noticed that the margin/padding space at "FACEBOOK" and "Sign Up for Facebook" has changed before and after.
  • No scroll view is involved.
Community
  • 1
  • 1
Roy Lee
  • 10,572
  • 13
  • 60
  • 84
  • 4
    It is also worth remembering that resizing doesn't work in full screen (`Theme.AppCompat.Light.NoActionBar.FullScreen`), as per this answer -> https://stackoverflow.com/a/7509285/1307690 – Roman Nazarevych Apr 10 '19 at 12:57

18 Answers18

244

Just add

android:windowSoftInputMode="adjustResize"

in your AndroidManifest.xml where you declare this particular activity and this will adjust the layout resize option.

enter image description here

some source code below for layout design

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        android:text="FaceBook"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_marginTop="30dp"
        android:ems="10"
        android:hint="username" >

        <requestFocus />
    </EditText>

    <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/editText1"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="password" />

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/editText2"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="18dp"
        android:layout_marginTop="20dp"
        android:text="Log In" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginTop="17dp"
        android:gravity="center"
        android:text="Sign up for facebook"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>
Jeffrey Bosboom
  • 13,313
  • 16
  • 79
  • 92
Venkatesh S
  • 5,466
  • 1
  • 25
  • 30
  • 2
    +1 That simple? Any extra conditions? What was the image you posted about? – Roy Lee May 07 '13 at 04:17
  • 2
    friends just to show alignparentbottom="true" if the screen not adjusted properly ..hence i placed that image friend – Venkatesh S May 07 '13 at 04:25
  • Very good answer indeed. Thanks for the help, pal. Glad you'd came. – Roy Lee May 07 '13 at 04:31
  • 11
    Friend it seems that only the TextView with "Sign up for facebook" adjusted itself when softkeyboard activated, others remain no change. I hope others get to adjust as well. Any workaround? And The whole layout should be at center before keyboard was activated, – Roy Lee May 07 '13 at 04:51
  • friend only the bottom content can be adjusted using the resize option. you create the above layout as centered and place the bottom with some bottom margin to look centered .. – Venkatesh S May 07 '13 at 04:54
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/29519/discussion-between-captain-america-and-roylee) – Venkatesh S May 07 '13 at 04:58
  • You can make a trick, write custom view, and it will work exactly like facebook app works (I guess they implemented custom view as well) – AlexKorovyansky Jan 15 '15 at 04:58
  • 1
    Is there a way to give some extra padding when it does adjustResize? Currently it resizes so that the bottom of the text cursor aligns EXACTLY with bottom of screen. I want to have extra 5dp gap below text cursor visible. – Noitidart Apr 07 '18 at 22:47
  • Hello @VenkateshS Do you have any idea how to do it using constraints layout? I have tried your solution but it doesn't work :( – kinza May 16 '18 at 06:15
  • @Roylee To make whole layout keep centered your 1. outermost layout must be match_parent in height and width,Linear Layout and android:layout_gravity = "center_vertical" inside it make a liner layout and make it cent android:orientation="vertical" android:layout_gravity="center_vertical" This will align the layout according to screen size always. – Deepak Yadav Jun 23 '18 at 17:49
45

This question has beeen asked a few years ago and "Secret Andro Geni" has a good base explanation and "tir38" also made a good attempt on the complete solution, but alas there is no complete solution posted here. I've spend a couple of hours figuring out things and here is my complete solution with detailed explanation at the bottom:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_above="@+id/mainLayout"
            android:layout_alignParentTop="true"
            android:id="@+id/headerLayout">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:gravity="center_horizontal">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/textView1"
                    android:text="facebook"
                    android:textStyle="bold"
                    android:ellipsize="marquee"
                    android:singleLine="true"
                    android:textAppearance="?android:attr/textAppearanceLarge" />

            </LinearLayout>

        </RelativeLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:id="@+id/mainLayout"
            android:orientation="vertical">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/editText1"
                android:ems="10"
                android:hint="Email or Phone"
                android:inputType="textVisiblePassword">

                <requestFocus />
            </EditText>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:id="@+id/editText2"
                android:ems="10"
                android:hint="Password"
                android:inputType="textPassword" />

            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:id="@+id/button1"
                android:text="Log In"
                android:onClick="login" />

        </LinearLayout>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_below="@+id/mainLayout"
            android:id="@+id/footerLayout">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true">

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:id="@+id/textView2"
                        android:text="Sign Up for Facebook"
                        android:layout_centerHorizontal="true"
                        android:layout_alignBottom="@+id/helpButton"
                        android:ellipsize="marquee"
                        android:singleLine="true"
                        android:textAppearance="?android:attr/textAppearanceSmall" />

                    <Button
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_alignParentRight="true"
                        android:id="@+id/helpButton"
                        android:text="\?"
                        android:onClick="help" />

                </RelativeLayout>

            </LinearLayout>

        </RelativeLayout>

    </RelativeLayout>

</ScrollView>

And in AndroidManifest.xml, don't forget to set:

android:windowSoftInputMode="adjustResize"

on the <activity> tag that you want such layout.

Thoughts:

I've realized that RelativeLayout are the layouts that span thru all available space and are then resized when the keyboard pops up.

And LinearLayout are layouts that don't get resized in the resizing process.

That's why you need to have 1 RelativeLayout immediately after ScrollView to span thru all available screen space. And you need to have a LinearLayout inside a RelativeLayout else your insides would get crushed when the resizing occurs. Good example is "headerLayout". If there wouldn't be a LinearLayout inside that RelativeLayout "facebook" text would get crushed and wouldn't be shown.

In the "facebook" login pictures posted in the question I've also noticed that the whole login part (mainLayout) is centered vertical in relation to the whole screen, hence the attribute:

android:layout_centerVertical="true"

on the LinearLayout layout. And because mainLayout is inside a LinearLayout this means that that part does't get resized (again see picture in question).

Yani2000
  • 854
  • 8
  • 11
  • 1
    Works like a charm!! but footer is stick to bottom of the layout which is not looking nice. how can I avoid footer stick to bottom! instead if I wanna give some margin to footer so that layout looks good. I made some changes by giving layout_margin attribute to relative layout of the footer but with this it is covering last half of the Edit Text. Plz help me out. – Tara May 11 '16 at 12:27
  • In _RelativeLayout_ with _@+id/footerLayout_ you have a _LinearLayout_ that has this attribute: `android:layout_alignParentBottom="true"`. This makes it stick to the bottom. – Yani2000 May 11 '16 at 12:42
  • ya, keeping in mind that, i asked you how to do arrangements of the footer components that should have bottom margin at least 10dp or 15dp – Tara May 12 '16 at 09:34
  • I have no idea what you're talking about. I just tested this myself by giving `android:layout_marginBottom="15dp"` to _footerLayout_ and then _RelativeLayout_ that is holding _textView2_ and _helpButton_. In both cases _helpButton_ gets crushed (even without the marginBottom attribute). In no way _editText1_ or _editText2_ ever gets crushed, because they're inside a _LinearLayout_. Did you maybe set margin on any other Layout (not only _footerLayout_)? Try from scratch if you're getting nowhere! You could also play with `android:windowSoftInputMode` attribute in AndroidManifest. – Yani2000 May 12 '16 at 10:25
  • Instead of giving marginBottom attribute to other layouts,Just Removed android:paddingTop="10dp" and added android:paddingBottom="10dp" to the RelativeLayout of the ScrollView's Child. And got the expected result. Thank You @Yani2000 – Tara May 17 '16 at 12:24
  • May I ask what my answer is missing? Your solution contains a lot of unneeded layout nesting. – tir38 Aug 18 '16 at 17:03
  • @tir38 Essentially your answer is not missing a thing, but it's not 100% complete and devs like to have a complete answer that they can adjust to their needs. Therefore I made a complete working layout that resembles the above Facebook behavior. What probably bugs you are those additional `LinearLayout` elements. Like I already mentioned in **Thoughts**, if you have a small screen device your text would get crushed. I would suggest you try to make a replica of that Facebook behavior yourself (you can use my values) and try to improve my answer with your findings in your answer. – Yani2000 Aug 19 '16 at 08:03
  • @tir38 Maybe there's an XML attribute I'm missing that doesn't crush text on resize? – Yani2000 Aug 19 '16 at 08:06
  • @Yani2000 fair enough =) – tir38 Sep 05 '16 at 19:58
  • 1
    "And LinearLayout are layouts that don't get resized in the resizing process." - this is a really helpful information. – cylon May 05 '19 at 07:23
36

Add this line in your Manifest where your Activity is called

android:windowSoftInputMode="adjustPan|adjustResize"

or

you can add this line in your onCreate

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE|WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
ehehhh
  • 1,066
  • 3
  • 16
  • 27
Ashish Jaiswal
  • 804
  • 1
  • 9
  • 23
  • 15
    You should never use both `adjustPan` and `adjustResize`. These are different modes. Read more about them here: https://stackoverflow.com/a/17410528/1738090 And here: https://developer.android.com/guide/topics/manifest/activity-element – w3bshark May 14 '18 at 12:32
29

It can work for all kind of layout.

  1. add this to your activity tag in AndroidManifest.xml

android:windowSoftInputMode="adjustResize"

for example:

<activity android:name=".ActivityLogin"
    android:screenOrientation="portrait"
    android:theme="@style/AppThemeTransparent"
    android:windowSoftInputMode="adjustResize"/>
  1. add this on your layout tag in activitypage.xml that will change its position.

android:fitsSystemWindows="true"

and

android:layout_alignParentBottom="true"

for example:

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:fitsSystemWindows="true">
hofs
  • 469
  • 4
  • 12
user3725137
  • 291
  • 3
  • 4
14

Android Developer has the right answer, but the provided source code is pretty verbose and doesn't actually implement the pattern described in the diagram.

Here is a better template:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true">

    <RelativeLayout android:layout_width="match_parent"
                    android:layout_height="match_parent">

        <LinearLayout android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:orientation="vertical">

                <!-- stuff to scroll -->

        </LinearLayout>

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true">

            <!-- footer -->

        </FrameLayout>

    </RelativeLayout>

</ScrollView>

Its up to you to decide what views you use for the "scrolling" and "footer" parts. Also know that you probably have to set the ScrollViews fillViewPort .

tir38
  • 9,810
  • 10
  • 64
  • 107
  • Tried following your solution but using two `LinearLayout`s instead of the Frame and Relative, but all views are still on top of eachother. – Henrique de Sousa Aug 12 '16 at 11:33
11

This makes it possible to show any wanted layout previously hidden by the keyboard.

Add this to the activity tag in AndroidManifest.xml

android:windowSoftInputMode="adjustResize"


Surround your root view with a ScrollView, preferably with scrollbars=none. The ScrollView will properly not change any thing with your layout except be used to solve this problem.

And then set fitsSystemWindows="true" on the view that you want to make fully shown above the keyboard. This will make your EditText visible above the keyboard, and make it possible to scroll down to the parts below the EditText but in the view with fitsSystemWindows="true".

android:fitsSystemWindows="true"

For example:

<ScrollView
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="none">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        ...

    </android.support.constraint.ConstraintLayout>
</ScrollView>   

If you want to show the full part of fitsSystemWindows="true" view above the keyboard in the moment the keyboard appears, you will need some code to scroll the view to the bottom:

// Code is in Kotlin

setupKeyboardListener(scrollView) // call in OnCreate or similar


private fun setupKeyboardListener(view: View) {
    view.viewTreeObserver.addOnGlobalLayoutListener {
        val r = Rect()
        view.getWindowVisibleDisplayFrame(r)
        if (Math.abs(view.rootView.height - (r.bottom - r.top)) > 100) { // if more than 100 pixels, its probably a keyboard...
            onKeyboardShow()
        }
    }
}

private fun onKeyboardShow() {
    scrollView.scrollToBottomWithoutFocusChange()
}

fun ScrollView.scrollToBottomWithoutFocusChange() { // Kotlin extension to scrollView
    val lastChild = getChildAt(childCount - 1)
    val bottom = lastChild.bottom + paddingBottom
    val delta = bottom - (scrollY + height)
    smoothScrollBy(0, delta)
}

Full layout example:

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fitsSystemWindows="true">

    <RelativeLayout
        android:id="@+id/statisticsLayout"
        android:layout_width="match_parent"
        android:layout_height="340dp"
        android:background="@drawable/some"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/logoImageView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="64dp"
            android:src="@drawable/some"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/authenticationLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginEnd="32dp"
        android:layout_marginStart="32dp"
        android:layout_marginTop="20dp"
        android:focusableInTouchMode="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/statisticsLayout">

        <android.support.design.widget.TextInputLayout
            android:id="@+id/usernameEditTextInputLayout"
            android:layout_width="match_parent"
            android:layout_height="68dp">

            <EditText
                android:id="@+id/usernameEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

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

        <android.support.design.widget.TextInputLayout
            android:id="@+id/passwordEditTextInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/usernameEditTextInputLayout">

            <EditText
                android:id="@+id/passwordEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

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

        <Button
            android:id="@+id/loginButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/passwordEditTextInputLayout"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="20dp" />

        <Button
            android:id="@+id/forgotPasswordButton"
            android:layout_width="wrap_content"
            android:layout_height="40dp"
            android:layout_below="@id/loginButton"
            android:layout_centerHorizontal="true" />

    </RelativeLayout>

</android.support.constraint.ConstraintLayout>

Morten Holmgaard
  • 7,484
  • 8
  • 63
  • 85
8

For those using ConstraintLayout, android:windowSoftInputMode="adjustPan|adjustResize" will not work.

What you can do is use a soft keyboard listener, set constraints of the views from bottom to bottom of the upper views, then set a vertical bias for each view (as a positional percentage between constraints) to a horizontal guideline (also positioned by percentage, but to the parent).

For each view, we just need to change app:layout_constraintBottom_toBottomOf to @+id/guideline when the keyboard is shown, programmatically of course.

        <ImageView
        android:id="@+id/loginLogo"
        ...
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.15" />


        <RelativeLayout
        android:id="@+id/loginFields"
        ...
        app:layout_constraintVertical_bias=".15"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/loginLogo">

        <Button
        android:id="@+id/login_btn"
        ...
        app:layout_constraintVertical_bias=".25"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/loginFields"/>

Generally a soft keyboard takes up no more than 50% of the height of the screen. Thus, you can set the guideline at 0.5.

        <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="0.5"/>

Now programmatically, when the keyboard is not shown, we can set all the app:layout_constraintBottom_toBottomOf back to parent, vice-versa.

            unregistrar = KeyboardVisibilityEvent.registerEventListener(this, isOpen -> {
            loginLayout.startAnimation(AnimationManager.getFade(200));
            if (isOpen) {
                setSoftKeyViewParams(loginLogo, R.id.guideline, ConstraintLayout.LayoutParams.PARENT_ID, -1, "235:64", 0.15f,
                        63, 0, 63, 0);
                setSoftKeyViewParams(loginFields, R.id.guideline, -1, R.id.loginLogo, null, 0.15f,
                        32, 0, 32, 0);
                setSoftKeyViewParams(loginBtn, R.id.guideline, -1, R.id.useFingerPrintIdText, null, 0.5f,
                        32, 0, 32, 0);
            } else {
                setSoftKeyViewParams(loginLogo, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintLayout.LayoutParams.PARENT_ID, -1, "235:64", 0.15f,
                        63, 0, 63, 0);
                setSoftKeyViewParams(loginFields, ConstraintLayout.LayoutParams.PARENT_ID, -1, R.id.loginLogo,null, 0.15f,
                        32, 0, 32, 0);
                setSoftKeyViewParams(loginBtn, ConstraintLayout.LayoutParams.PARENT_ID, -1, R.id.useFingerPrintIdText,null, 0.25f,
                        32, 0, 32, 0);
            }
        });

Call this method:

    private void setSoftKeyViewParams(View view, int bottomToBottom, int topToTop, int topToBottom, String ratio, float verticalBias,
                                  int left, int top, int right, int bottom) {
    ConstraintLayout.LayoutParams viewParams = new ConstraintLayout.LayoutParams(view.getLayoutParams().width, view.getLayoutParams().height);
    viewParams.dimensionRatio = ratio;
    viewParams.bottomToBottom = bottomToBottom;
    viewParams.topToTop = topToTop;
    viewParams.topToBottom = topToBottom;
    viewParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
    viewParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
    viewParams.verticalBias = verticalBias;
    viewParams.setMargins(Dimensions.dpToPx(left), Dimensions.dpToPx(top), Dimensions.dpToPx(right), Dimensions.dpToPx(bottom));
    view.setLayoutParams(viewParams);
}

The important thing is to be sure to set the vertical bias in a way that would scale correctly when the keyboard is shown and not shown.

6rchid
  • 1,074
  • 14
  • 19
  • 3
    A simpler method is to wrap the ConstraintLayout inside a ScrollView or a NestedScrollView. The calculations end up being too much of a work around. But your answer is great if a ScrollView would end up causing other issues – Devenom Aug 12 '19 at 13:22
6

Many answers are right. In AndroidManifest I wrote:

<activity
    android:name=".SomeActivity"
    android:configChanges="orientation|keyboardHidden|screenSize" // Optional, doesn't affect.
    android:theme="@style/AppTheme.NoActionBar"
    android:windowSoftInputMode="adjustResize" />

In my case I added a theme in styles.xml, but you can use your own:

<style name="AppTheme.NoActionBar" parent="AppTheme">
    <!--  Hide ActionBar -->
    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
</style>

I noiced that if I use full-screen theme, resizing doesn't occur:

<style name="AppTheme.FullScreenTheme" parent="AppTheme">
    <!--  Hide ActionBar -->
    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
    <!--  Hide StatusBar -->
    <item name="android:windowFullscreen">true</item>
</style>

Also in my case adjustResize works, but adjustPan doesn't.

For full-screen layouts see a workaround in Android How to adjust layout in Full Screen Mode when softkeyboard is visible or in https://gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584.

Also https://medium.com/@sandeeptengale/problem-solved-3-android-full-screen-view-translucent-scrollview-adjustresize-keyboard-b0547c7ced32 works, but it's StatusBar is transparent, so battery, clock, Wi-Fi icons are visible.

If you create an activity with File > New > Activity > Fullscreen Activity, where in code is used:

fullscreen_content.systemUiVisibility =
    View.SYSTEM_UI_FLAG_LOW_PROFILE or
    View.SYSTEM_UI_FLAG_FULLSCREEN or
    View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
    View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
    View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION

you also won't achieve a result. You can use android:fitsSystemWindows="true" in a root container, but StatusBar appears. So use workarounds from the first link.

CoolMind
  • 26,736
  • 15
  • 188
  • 224
  • @Harshilkakadiya, thanks! Notice, that if you then want to revert to normal mode (non-fullscreen), this workaround should be removed. I wasted many hours on it. In my case below layout I got a white space. Good luck! – CoolMind Feb 04 '19 at 07:26
4

In Kotlin or in ConstraintLayout you just add :

android:windowSoftInputMode="stateHidden|adjustResize"

OR

android:windowSoftInputMode="stateVisible|adjustResize"

Which state you need after activity launch, you can set from manifest.

in your AndroidManifest.xml like this:

      <activity
        android:name=".ActivityName"
        android:windowSoftInputMode="stateHidden|adjustResize"
        />
Jamil Hasnine Tamim
  • 4,389
  • 27
  • 43
3

You can simply set these options in the AndroidManifest.xml file.

<activity
    android:name=".YourACtivityName"
    android:windowSoftInputMode="stateVisible|adjustResize">

The use of adjustPan is not recommended by Google because the user may need to close the keyboard to see all the input fields.

More info: Android App Manifest

vovahost
  • 34,185
  • 17
  • 113
  • 116
  • Did you really try this? This is no different to `ajustNothing` – Farid Feb 04 '22 at 11:41
  • @Farid It might be because your screen is big enough so there's enough space. Also make sure you applied this to the right activity. – vovahost Feb 04 '22 at 14:16
3

For me it worked with this line of code:

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

Just put it into onCreate method. Best!

Peter94
  • 33
  • 7
3

Add this line into Manifiest File:

android:windowSoftInputMode="adjustResize"
3

Easy way in kotlin

In your fragment

requireActivity().window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE or WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)

In your layout :

android:fitsSystemWindows="true"
2

In my case it helped.

main_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main2"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.livewallpaper.profileview.loginact.Main2Activity">

<TextView
    android:layout_weight="1"
    android:layout_width="match_parent"
    android:text="Title"
    android:gravity="center"
    android:layout_height="0dp" />
<LinearLayout
    android:layout_weight="1"
    android:layout_width="match_parent"
    android:layout_height="0dp">
    <EditText
        android:hint="enter here"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>
<TextView
    android:layout_weight="1"
    android:text="signup for App"
    android:gravity="bottom|center_horizontal"
    android:layout_width="match_parent"
    android:layout_height="0dp" />
</LinearLayout>

Use this in manifest file

<activity android:name=".MainActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize"/>

Now the most important part! Use theme like this in either Activity or Application tag.

android:theme="@style/AppTheme"

And the theme tooks like this

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="windowActionModeOverlay">true</item>
</style>

So I was missing the theme. Which made me frustrated all day.

Pradeep Kumar Kushwaha
  • 2,231
  • 3
  • 23
  • 34
1

I use this Extended class frame And when I need to recalculate the height size onLayout I override onmeasure and subtract keyboardHeight using getKeyboardHeight()

My create frame who needs resize with softkeyboard

SizeNotifierFrameLayout frameLayout = new SizeNotifierFrameLayout(context) {
            private boolean first = true;

            @Override
            protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
                super.onLayout(changed, left, top, right, bottom);

                if (changed) {
                    fixLayoutInternal(first);
                    first = false;
                }
            }

            @Override
            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - getKeyboardHeight(), MeasureSpec.EXACTLY));
            }

            @Override
            protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
                boolean result = super.drawChild(canvas, child, drawingTime);
                if (child == actionBar) {
                    parentLayout.drawHeaderShadow(canvas, actionBar.getMeasuredHeight());
                }
                return result;
            }


        };

SizeNotifierFrameLayout

public class SizeNotifierFrameLayout extends FrameLayout {

    public interface SizeNotifierFrameLayoutDelegate {
        void onSizeChanged(int keyboardHeight, boolean isWidthGreater);
    }

    private Rect                            rect            = new Rect();
    private Drawable                        backgroundDrawable;
    private int                             keyboardHeight;
    private int                             bottomClip;
    private SizeNotifierFrameLayoutDelegate delegate;
    private boolean                         occupyStatusBar = true;

    public SizeNotifierFrameLayout(Context context) {
        super(context);
        setWillNotDraw(false);
    }

    public Drawable getBackgroundImage() {
        return backgroundDrawable;
    }

    public void setBackgroundImage(Drawable bitmap) {
        backgroundDrawable = bitmap;
        invalidate();
    }

    public int getKeyboardHeight() {
        View rootView = getRootView();
        getWindowVisibleDisplayFrame(rect);
        int usableViewHeight = rootView.getHeight() - (rect.top != 0 ? AndroidUtilities.statusBarHeight : 0) - AndroidUtilities.getViewInset(rootView);
        return usableViewHeight - (rect.bottom - rect.top);
    }

    public void notifyHeightChanged() {
        if (delegate != null) {
            keyboardHeight = getKeyboardHeight();
            final boolean isWidthGreater = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y;
            post(new Runnable() {
                @Override
                public void run() {
                    if (delegate != null) {
                        delegate.onSizeChanged(keyboardHeight, isWidthGreater);
                    }
                }
            });
        }
    }

    public void setBottomClip(int value) {
        bottomClip = value;
    }

    public void setDelegate(SizeNotifierFrameLayoutDelegate delegate) {
        this.delegate = delegate;
    }

    public void setOccupyStatusBar(boolean value) {
        occupyStatusBar = value;
    }

    protected boolean isActionBarVisible() {
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (backgroundDrawable != null) {
            if (backgroundDrawable instanceof ColorDrawable) {
                if (bottomClip != 0) {
                    canvas.save();
                    canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight() - bottomClip);
                }
                backgroundDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
                backgroundDrawable.draw(canvas);
                if (bottomClip != 0) {
                    canvas.restore();
                }
            } else if (backgroundDrawable instanceof BitmapDrawable) {
                BitmapDrawable bitmapDrawable = (BitmapDrawable) backgroundDrawable;
                if (bitmapDrawable.getTileModeX() == Shader.TileMode.REPEAT) {
                    canvas.save();
                    float scale = 2.0f / AndroidUtilities.density;
                    canvas.scale(scale, scale);
                    backgroundDrawable.setBounds(0, 0, (int) Math.ceil(getMeasuredWidth() / scale), (int) Math.ceil(getMeasuredHeight() / scale));
                    backgroundDrawable.draw(canvas);
                    canvas.restore();
                } else {
                    int actionBarHeight =
                            (isActionBarVisible() ? ActionBar.getCurrentActionBarHeight() : 0) + (Build.VERSION.SDK_INT >= 21 && occupyStatusBar ? AndroidUtilities.statusBarHeight : 0);
                    int   viewHeight = getMeasuredHeight() - actionBarHeight;
                    float scaleX     = (float) getMeasuredWidth() / (float) backgroundDrawable.getIntrinsicWidth();
                    float scaleY     = (float) (viewHeight + keyboardHeight) / (float) backgroundDrawable.getIntrinsicHeight();
                    float scale      = scaleX < scaleY ? scaleY : scaleX;
                    int   width      = (int) Math.ceil(backgroundDrawable.getIntrinsicWidth() * scale);
                    int   height     = (int) Math.ceil(backgroundDrawable.getIntrinsicHeight() * scale);
                    int   x          = (getMeasuredWidth() - width) / 2;
                    int   y          = (viewHeight - height + keyboardHeight) / 2 + actionBarHeight;
                    canvas.save();
                    canvas.clipRect(0, actionBarHeight, width, getMeasuredHeight() - bottomClip);
                    backgroundDrawable.setBounds(x, y, x + width, y + height);
                    backgroundDrawable.draw(canvas);
                    canvas.restore();
                }
            }
        } else {
            super.onDraw(canvas);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        notifyHeightChanged();
    }
}
Arthur Melo
  • 454
  • 5
  • 13
1

This code works for me. When keyboard appears, you can scroll screen

In AndroidManifest.xml

<activity android:name=".signup.screen_2.SignUpNameAndPasswordActivity"
                  android:screenOrientation="portrait"
                  android:windowSoftInputMode="adjustResize">
</activity>

activity_sign_up.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        tools:context=".signup.screen_2.SignUpNameAndPasswordActivity">
    <LinearLayout
            android:fitsSystemWindows="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

        <LinearLayout
                android:layout_marginTop="@dimen/dp_24"
                android:layout_marginStart="@dimen/dp_24"
                android:layout_marginEnd="@dimen/dp_24"
                android:id="@+id/lin_name_password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:fontFamily="sans-serif-medium"
                    android:text="@string/name_and_password"
                    android:textColor="@color/colorBlack"
                    android:layout_marginTop="@dimen/dp_5"
                    android:textSize="@dimen/ts_16"/>

            <EditText
                    android:id="@+id/edit_full_name"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/dp_44"
                    app:layout_constraintTop_toTopOf="parent"
                    android:hint="@string/email_address_hint"
                    android:inputType="textPersonName"
                    android:imeOptions="flagNoFullscreen"
                    android:textSize="@dimen/ts_15"
                    android:background="@drawable/rounded_border_edittext"
                    android:layout_marginTop="@dimen/dp_15"
                    android:paddingStart="@dimen/dp_8"
                    android:paddingEnd="@dimen/dp_8"
                    android:maxLength="100"
                    android:maxLines="1"/>

            <EditText
                    android:id="@+id/edit_password"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/dp_44"
                    app:layout_constraintTop_toTopOf="parent"
                    android:hint="@string/password"
                    android:inputType="textPassword"
                    android:imeOptions="flagNoFullscreen"
                    android:textSize="@dimen/ts_15"
                    android:background="@drawable/rounded_border_edittext"
                    android:layout_marginTop="@dimen/dp_15"
                    android:paddingStart="@dimen/dp_8"
                    android:paddingEnd="@dimen/dp_8"
                    android:maxLength="100"
                    android:maxLines="1"/>

            <TextView
                    android:id="@+id/btn_continue_and_sync_contacts"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/dp_44"
                    android:gravity="center"
                    android:clickable="true"
                    android:focusable="true"
                    android:layout_marginTop="@dimen/dp_15"
                    android:background="@drawable/btn_blue_selector"
                    android:enabled="false"
                    android:text="@string/continue_and_sync_contacts"
                    android:textColor="@color/colorWhite"
                    android:textSize="@dimen/ts_15"
                    android:textStyle="bold"/>

            <TextView
                    android:id="@+id/btn_continue_without_syncing_contacts"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/dp_44"
                    android:gravity="center"
                    android:clickable="true"
                    android:focusable="true"
                    android:layout_marginTop="@dimen/dp_10"
                    android:enabled="false"
                    android:text="@string/continue_without_syncing_contacts"
                    android:textColor="@color/colorBlue"
                    android:textSize="@dimen/ts_15"
                    android:textStyle="bold"/>

        </LinearLayout>
        <!--RelativeLayout is scaled when keyboard appears-->
        <RelativeLayout
                android:layout_marginStart="@dimen/dp_24"
                android:layout_marginEnd="@dimen/dp_24"
                android:layout_marginBottom="@dimen/dp_20"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            <LinearLayout
                    android:layout_alignParentBottom="true"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">
                <TextView
                        android:id="@+id/tv_learn_more_1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:clickable="true"
                        android:focusable="true"
                        android:layout_gravity="center_horizontal"
                        android:text="@string/learn_more_syncing_contacts"
                        android:textColor="@color/black_alpha_70"
                        android:gravity="center"
                        android:layout_marginBottom="1dp"
                        android:textSize="@dimen/ts_13"/>

                <TextView
                        android:id="@+id/tv_learn_more_2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:clickable="true"
                        android:focusable="true"
                        android:layout_gravity="center_horizontal"
                        android:text="@string/learn_more"
                        android:fontFamily="sans-serif-medium"
                        android:textColor="@color/black_alpha_70"
                        android:textSize="@dimen/ts_13"/>
            </LinearLayout>
        </RelativeLayout>
    </LinearLayout>
</ScrollView>

rounded_border_edittext.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_activated="true">
        <shape android:shape="rectangle">
            <solid android:color="#F6F6F6"/>
            <corners android:radius="3dp"/>
            <stroke
                    android:width="1dp"
                    android:color="@color/red"/>
        </shape>
    </item>
    <item android:state_activated="false">
        <shape android:shape="rectangle">
            <solid android:color="#F6F6F6"/>
            <corners android:radius="3dp"/>
            <stroke
                    android:width="1dp"
                    android:color="@color/colorGray"/>
        </shape>
    </item>
</selector>

btn_blue_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="true" android:state_pressed="true">
        <shape android:shape="rectangle">
            <corners android:radius="3dp"/>
            <solid android:color="@color/colorBlueLight"/>
            <stroke android:width="1dp" android:color="@color/colorBlueLight"/>
        </shape>
    </item>
    <item android:state_enabled="true">
        <shape android:shape="rectangle">
            <corners android:radius="3dp"/>
            <solid android:color="@color/colorBlue"/>
            <stroke android:width="1dp" android:color="@color/colorBlue"/>
        </shape>
    </item>
    <item android:state_enabled="false">
        <shape android:shape="rectangle">
            <corners android:radius="3dp"/>
            <solid android:color="@color/colorBlueAlpha"/>
            <stroke android:width="0dp" android:color="@color/colorBlueAlpha"/>
        </shape>
    </item>
</selector>
Anh Duy
  • 1,145
  • 15
  • 25
1

In my case only this solution worked:

  1. In Manifest:

      <activity
        android:name=".TTSpeech"
        android:windowSoftInputMode="adjustPan"
        android:exported="false" />
    
  2. In Activity call

clearFocus();

on edittext.

mahamrauf
  • 21
  • 4
0

In Xamarin register below code in your activity

 WindowSoftInputMode = Android.Views.SoftInput.AdjustResize | Android.Views.SoftInput.AdjustPan

I used a Relative Layout if you're using Constraint Layout, the above code will work code below

logeshpalani31
  • 1,416
  • 12
  • 33