如何使windowSoftInputMode =“adjustPan”平移更多

发布于 2024-12-28 19:36:13 字数 268 浏览 1 评论 0原文

我有一个带有一堆 EditText 字段的活动,并且 windowSoftInputMode 设置为 adjustmentPan,这主要满足我的要求,但是对于布局底部的 editText,它平移不够。它将平移以显示多行编辑文本的顶行,但是一旦您按下 Enter 键,光标就会向下移动一行,现在隐藏在键盘下方。

无论如何,我可以让它进一步平移,以便 editText 的顶部一直位于窗口的顶部。

使用 adjustResize 肯定不会达到我想要的效果,平移是正确的,只需要它进一步平移即可。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

眼泪都笑了 2025-01-04 19:36:13

同样的事情也发生在我身上。

我要解决的问题是,我只是将所有控件放在 ScrollllView 中。

并设置 android:windowSoftInputMode adjustResize。因此,每当键盘打开时,它都会滚动屏幕来调整视图,并且 Edittext 始终显示在屏幕上。

希望这个想法对你有用。

谢谢

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

我很OK 2025-01-04 19:36:13

这是一篇非常古老的帖子,但我最近在我的项目中也遇到了这个问题。我想出了一个完美解决此问题的解决方案,因此我想分享以帮助其他人避免我所经历的挣扎。

将 windowSoftInputMode 设置为“调整调整大小”不起作用,因为我的应用程序是全屏的。(这是由于提到的 android bug 此处)。即使它确实有效,我相信这个选项也不是很好的用户界面。所以我也想让“Adjust Pan”选项与“more pan”一起工作,不幸的是Android没有提供API来调整这个边距。并且在editText中添加“paddingBottom”会使屏幕的UI不平衡。

经过大量研究,我能够按照以下步骤解决这个问题;
(我使用这个非常有帮助中等帖子)

1 - 从 AndroidManifest.xml 中创建 windowSoftInputMode="adjustUnspecified"。

2 - 添加以下方法作为扩展函数;

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 - 创建一个全局布局侦听器,用于检测键盘何时可见,如下所示;

  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 - 在 onKeyboardStateChanged 方法中,我将主要活动布局向上滚动 screenHeight/4,这通常就足够了,但您可以根据需要调整滚动量,并将布局更改为您想要滚动的任何布局。另外,我使用过渡动画来使过渡更加平滑,这对于功能来说不是必需的。

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 - 添加要在 onResume 上监听的视图,并在 onPause 上删除监听器,如下所示;

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

    override fun onPause() {
        super.onPause()
        val view = getRootView()
        view.viewTreeObserver?.removeOnGlobalLayoutListener(listener)
    }
  • 如果您将 windowSoftInputMode 设置为“adjustNothing”,此功能将不起作用。因为监听器逻辑将会失败。

  • 此外,如果您将其与“adjustPan”一起使用,它将无法按预期工作,因为此逻辑会从当前滚动点调整平移。假设您在同一个视图中有两个编辑文本,用户单击第一个,它会从 Android 逻辑中稍微向上平移布局,然后从我们在此处实现的逻辑中滚动。然后用户单击第二个视图,Android 逻辑从当前滚动 y 值开始平移,因此它再次非常接近 editText,而我们的逻辑不起作用,因为滚动 y 已经增加了。或者,您可以继续增加滚动 y ,这最终会导致您的布局变得不成比例,这是不希望的。

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.

提笔落墨 2025-01-04 19:36:13

将您的 EditText 放入 ScrollView 中,然后赋予属性 adjustResize,而不是 adjustPan,它会自动调整您的屏幕及其组成部分。

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

醉城メ夜风 2025-01-04 19:36:13

当我触摸它时,我在屏幕底部有编辑文本,打开软键盘,但它隐藏了编辑文本,因此在布局中进行更改(使用相对布局),它对我有用,无需使用 adjustPan。这里是我的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>

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>
菊凝晚露 2025-01-04 19:36:13

对于那些真正想要更多地平移页面的人。您可以在 rootView 上执行自己的上移/下移逻辑。您需要自行计算移动多少距离。

请参阅此示例 https://github.com/yatw/SoftKeyboardAdjust

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

香草可樂 2025-01-04 19:36:13

如果您要应用插入以使屏幕边缘到边缘,那么您是否在 AndroidManifest 中声明 adjustPanadjustResize 都没有关系

您只需要获取 WindowInsetsCompat.Type.ime() 并将其一起应用即可。

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)

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)
爱本泡沫多脆弱 2025-01-04 19:36:13

您需要将此行添加到您的活动中以调整屏幕。

        <activity android:name=".TodoEdit"
        android:windowSoftInputMode="adjustResize">

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

        <activity android:name=".TodoEdit"
        android:windowSoftInputMode="adjustResize">
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文