Domanda

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.

È stato utile?

Soluzione

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

Altri suggerimenti

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

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.

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>

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

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

        <activity android:name=".TodoEdit"
        android:windowSoftInputMode="adjustResize">
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top