How to make windowSoftInputMode="adjustPan" pan more
Asked Answered
D

7

18

I have an activity with a bunch of EditText fields on it, and the windowSoftInputMode is set to adjustPan, this mostly does what I want, however for the editText at the bottom of the layout, it doesn't pan enough. It'll pan to show the top line of a multiline edit text, but as soon as you hit enter, the cursor moves down a line and is now hidden under the keyboard.

Is there anyway I can make it pan further so that the top of the editText is all the way at the top of the window.

Using adjustResize definitely won't do what I want, pan is the right thing, just need it to pan further.

Desmoid answered 25/1, 2012 at 4:18 Comment(1)
post your screen shot so it is easy for understating problemViscounty
C
6

Same thing was happen with me.

What I did to resolve is, I just put all the controls in ScrolllView.

And set android:windowSoftInputMode adjustResize. So whenever keyboard is open it will scroll the screen to adjust the view and Edittext always show on screen.

Hope this idea works for you.

Thanks

Cavit answered 29/10, 2014 at 10:53 Comment(2)
What do you mean by "put all the controls in ScrollView" ?Underling
Coming for the post title. How do you actually control how to pan more? Pan and resize only shift the page up just enough to not hide the current focused edittext. How to make it pan + some margin?Romansh
G
2

It is a very old post but I have also struggled with this very recently in my project. I have come up with a solution that solves this case perfectly, so I wanted to share to help someone avoid the struggles I've been through.

Setting windowSoftInputMode to "Adjust Resize" did not work since my application was full screen.(it is due to an android bug mentioned here) . Even if it did work, I believe this option is not very good UI. So I also wanted to make the "Adjust Pan" option work with "more pan", and unfortunately Android does not provide an API to adjust this margin. And adding "paddingBottom" to the editText makes the UI of the screen unbalanced.

After a lot of research, I was able to solve this by following these steps; (I used this very helpful medium post)

1 - Make windowSoftInputMode="adjustUnspecified" from AndroidManifest.

2 - Add the following methods as extension functions;

fun Activity.getRootView(): View {
    return findViewById<View>(android.R.id.content)
}
fun Context.convertDpToPx(dp: Float): Float {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        dp,
        this.resources.displayMetrics
    )
}
fun Activity.isKeyboardOpen(): Boolean {
    val visibleBounds = Rect()
    this.getRootView().getWindowVisibleDisplayFrame(visibleBounds)
    val heightDiff = getRootView().height - visibleBounds.height()
    val marginOfError = Math.round(this.convertDpToPx(50F))
    return heightDiff > marginOfError
}

3 - Create a global layout listener for detecting when the keyboard is visible as below;

  val listener = object : ViewTreeObserver.OnGlobalLayoutListener {
        // Keep a reference to the last state of the keyboard
        private var lastState: Boolean = isKeyboardOpen() ?: false
        /**
         * Something in the layout has changed
         * so check if the keyboard is open or closed
         * and if the keyboard state has changed
         * save the new state and invoke the callback
         */
        override fun onGlobalLayout() {
            val isOpen = isKeyboardOpen() ?: false
            if (isOpen == lastState) {
                return
            } else {
                onKeyboardStateChanged(isOpen)
                lastState = isOpen
            }
        }
    }

4 - In the onKeyboardStateChanged method, I scroll my main activity layout up by screenHeight/4 which is generally enough, but you can play around with the amount of scroll as you see fit and change the layout to whichever layout you want to scroll by. Also, I use a transition animation to make the transitions smoother, which is not necessary for functionality.

private fun onKeyboardStateChanged(open: Boolean) {
    runOnUiThread {
        if (open) {
            val screenHeight = resources.displayMetrics.heightPixels
            TransitionManager.beginDelayedTransition(main_activity_layout as ViewGroup)
            main_activity_layout.scrollTo(0, screenHeight / 4)
        } else {
            TransitionManager.beginDelayedTransition(main_activity_layout as ViewGroup)
            main_activity_layout.scrollTo(0, 0)
        }
    }
}

5 - Add the view to listen on your onResume, and remove the listener on onPause as follows;

 override fun onResume() {
        super.onResume()
        val view = getRootView()
        view.viewTreeObserver?.addOnGlobalLayoutListener(listener)
    }

    override fun onPause() {
        super.onPause()
        val view = getRootView()
        view.viewTreeObserver?.removeOnGlobalLayoutListener(listener)
    }
  • THIS WILL NOT WORK IF YOU SET THE windowSoftInputMode TO "adjustNothing". Because the listener logic will fail.

  • Also, it will not work as intended if you use it with "adjustPan", because this logic adjusts the pan from the current scroll point. So let's say you have two edit texts in the same view, user clicks the first one, it pans the layout up a little from Android logic, and then scrolls from the logic we implemented here. Then the user clicks on the second view, Android logic pans from the current scroll y value, so it is again very close to the editText, and our logic does not work because the scroll y is already increased. Alternatively you can keep incrementing the scroll y which will end up in your layout becoming out of proportion and is not desired.

Glassman answered 17/12, 2020 at 9:52 Comment(0)
M
1

Put your EditText inside the ScrollView and then give property adjustResize, instead of adjustPan, it will automatically adjust your screen and its components.

Magnanimous answered 31/10, 2014 at 11:47 Comment(0)
A
0

i have edittext at bottom of the screen when I touched on it open softkeyboard but it hide the edittext, so make the changes in layout(use relative layout )and it works for me without using adjustPan.Here is my XML.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/gen_mainlayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/bg"
    android:orientation="vertical" >

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

        <RelativeLayout
            android:id="@+id/headerlinearLayout"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/navigation_bar" >

            <Button
                android:id="@+id/chatterBack"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:background="@drawable/navigation_cancel_button"
                android:textColor="#FFFFFF" >
            </Button>

            <TextView
                android:id="@+id/ittletextView"
                style="@style/titleText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="Title" >
            </TextView>

            <Button
                android:id="@+id/blockhide"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="20dp"
                android:background="@drawable/navigation_cancel_button"
                android:padding="5dp"
                android:text="Block/Hide"
                android:textColor="#FFFFFF" >
            </Button>
        </RelativeLayout>

        <LinearLayout
            android:id="@+id/middlelinearLayout"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/headerlinearLayout"
            android:orientation="vertical" >

        </LinearLayout>


        <LinearLayout
            android:id="@+id/footerlinearLayout"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:background="@drawable/commnet_post_bg"
            android:gravity="center"
            android:paddingLeft="5dp"
            android:paddingRight="5dp" >


            <EditText
                android:id="@+id/sendeditText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:background="@drawable/comment_post_text_box"
                android:imeOptions="actionSend|flagNoEnterAction"
                android:inputType="text"
                android:paddingLeft="10dp"
                android:paddingRight="5dp"
                android:singleLine="true" >
            </EditText>

            <Button
                android:id="@+id/sendButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/send_button"
                android:text="Send"
                android:textColor="#FFFFFF" >
            </Button>
        </LinearLayout>
    </RelativeLayout>

</LinearLayout>
Apocope answered 25/1, 2012 at 6:28 Comment(0)
R
0

For those who actually want to pan the page up more. You can do your own shift up/ shift down logic on your rootView. You need to calculate how much distance to shift on your own.

See this example https://github.com/yatw/SoftKeyboardAdjust

Romansh answered 5/10, 2020 at 4:0 Comment(0)
B
0

If you are applying insets to get the screen to be edge-to-edge, it won't matter if you're declaring adjustPan or adjustResize in your AndroidManifest.

You will just need to get WindowInsetsCompat.Type.ime() and apply it together.

val rootView = window.decorView.rootView
ViewCompat.setOnApplyWindowInsetsListener(rootView) { _, insets ->
    insets.getInsets(WindowInsetsCompat.Type.ime() or WindowInsetsCompat.Type.systemGestures()).apply {
        binding.guidelineTop.setGuidelineBegin(top)
        binding.guidelineBottom.setGuidelineEnd(bottom)
    }
}
ViewCompat.requestApplyInsets(rootView)
Beautify answered 23/11, 2023 at 13:39 Comment(0)
W
-1

You need to add this line into your activity for adjusting screen.

        <activity android:name=".TodoEdit"
        android:windowSoftInputMode="adjustResize">
Weide answered 19/10, 2014 at 17:44 Comment(1)
as i said in the question adjustResize doesn't do it.Desmoid

© 2022 - 2024 — McMap. All rights reserved.