当键盘出现时,将屏幕向上滚动

40

我有一个带有EditText的活动页面。当我点击EditText时,键盘会出现,并且屏幕会移动以使EditText刚好位于键盘上方,覆盖其他位于下方的内容。

我不想改变布局大小或添加填充。我需要屏幕滚动到顶部,滚动的距离应该足够让我看到下面的内容。换句话说,在键盘出现时,我希望能够选择EditText的位置。如果屏幕完全向上滚动,显示布局底部,那也可以。

我尝试将布局放入一个scrollView中,并在EditText中添加以下代码:

    editText.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            //make the view scroll down to the bottom
            scrollView.scrollTo(0, scrollView.getBottom());

        }
    });

但它没起作用。有人有想法吗?谢谢!

10个回答

46

使用android:windowSoftInputMode="adjustPan"

"adjustResize"

将始终调整活动的主窗口大小,以为软键盘留出空间。

"adjustPan"

不会调整活动的主窗口大小以为软键盘留出空间,而是自动平移窗口内容,以便当前焦点永远不会被键盘遮挡,用户始终可以看到他们正在输入什么。这通常不如调整大小好,因为用户可能需要关闭软键盘才能访问和交互窗口中被遮挡的部分。

例如,在您的清单文件中:

       <activity
    android:windowSoftInputMode="adjustPan"
    android:name=".MainActivity"></activity>

回答晚了,但肯定对任何人有帮助。


26

我曾经遇到过类似的问题,我使用以下方法解决:

    android:windowSoftInputMode="adjustResize"

在AndroidManifest.xml中。

如果您使用RelativeLayout,请从必须连接到父级底部的底部元素开始,然后将其他元素钩在前一个元素上方。

如果您使用 LinearLayout,请将其包装在RelativeLayout中,并将LinearLayout钩连接到parentBottom。

这样当键盘弹出时,您会看到布局的底部。

希望这可以帮助。


6
“如果您使用RelativeLayout,请从必须连接到父级底部的底部元素开始,然后将其他元素钩在前面的元素上方。” 的意思是,要使用RelativeLayout布局时,应该先找到一个必须与父级底部相连的底部元素,然后再把其他元素钩在前一个元素的上方。"hook" 在此处指的是将一个元素与另一个元素相连。 - Josh
如果当键盘可见时,我想显示的屏幕部分不能连接到父视图底部,而是要居中于页面,该怎么办? - Raphael Royer-Rivard
在我的“fragment”中不起作用:getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); - user3402040
1
请澄清您的回答。 - aya salama
2
我认为意思是(并且对我有效)将LinearLayout包装在RelativeLayout中,并在前者中设置android:layout_alignParentBottom="true" - Matthias
如果父级是ConstraintLayout怎么办?我尝试使用android:windowSoftInputMode="adjustResize"并且父级是ConstraintLayout,但仍然无法将屏幕向上移动。 - MMK

11

我遇到了这个问题,我用以下代码解决:

myEdittext.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    myscrollview.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            View lastChild = myscrollview.getChildAt(myscrollview.getChildCount() - 1);
                            int bottom = lastChild.getBottom() + myscrollview.getPaddingBottom();
                            int sy = myscrollview.getScrollY();
                            int sh = myscrollview.getHeight();
                            int delta = bottom - (sy + sh);
                            myscrollview.smoothScrollBy(0, delta);
                        }
                    }, 200);
                }
            });

3
谢谢!我还添加了 myEdittext.setOnFocusChangeListener { _, hasFocus -> if (hasFocus) scrollUpLayout() },并将你的函数与之结合。同时,在 AndroidManifest 的 activity 中添加了 android:windowSoftInputMode="adjustResize" - CoolMind
谢谢,这对我也起作用了。使用android:windowSoftInputMode="adjustResize"并使用setOnFocusChangeListener而不是setOnClickListener。 - Krishna Upadhya
谢谢,很好地解决了问题。但是在我的情况下,使用setOnClickListener时第一次点击无效,而后续点击正常;而使用setOnFocusChangeListener时第一次点击就可以正常工作。 - Rahul Sharma

7
这对我起作用。
android:windowSoftInputMode="stateVisible|adjustResize"

在 AndroidManifest 中为活动声明。

他不想调整大小。 - Sid

5

这个有效:-

Constraint Layout存在键盘打开时向上滚动的问题。 不要使用它。

为了实现“键盘出现时滚动屏幕”,请尝试以下方法:

使用Linear layoutScrollView

在滚动视图中使用fill_parent, 以及滚动视图中的任何文本字段。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical"
   android:gravity="center">

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:fillViewport="true">


</ScrollView>
</LinearLayout>

不应该使用fill_parent。 - AlexS

4
将此 添加到您的Gradle依赖项中:
dependencies {
    compile 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:2.1.0'
}

并使用此代码:

KeyboardVisibilityEvent.setEventListener(getActivity(), new KeyboardVisibilityEventListener() {
    @Override
    public void onVisibilityChanged(boolean isOpen) {

        if (isOpen && MY_EDIT_TEXT.hasFocus()) {

            //scroll to last view
            View lastChild = scrollLayout.getChildAt(scrollLayout.getChildCount() - 1);
            int bottom = lastChild.getBottom() + scrollLayout.getPaddingBottom();
            int sy = scrollLayout.getScrollY();
            int sh = scrollLayout.getHeight();
            int delta = bottom - (sy + sh);

            scrollLayout.smoothScrollBy(0, delta);
        }
    }
});

1
在 Kotlin 中,这是一个简单的方法(从用户 user6581344 的答案中重用),我使用它来在设置焦点并显示键盘时手动滚动到 EditText 上,因为需要在键盘和 EditText 之间添加额外的底部填充。
    binding.scrollView.postDelayed(object:Runnable {

        override fun run() {

            val extraBottomPadding = 100

            val manualScroll = txtFullName.y + extraBottomPadding

            scrollView.smoothScrollBy(0, manualScroll.toInt())
        }

    }, 200)

1
只有在我从约束布局更改为线性布局并添加android:windowSoftInputMode="adjustResize"后,它才对我起作用。
同时,还需要从Activity样式中移除<item name="android:windowFullscreen">true</item>

1

只需添加

android:screenReaderFocusable="true"

将此代码添加到您的XML文件中,它将像魔法一样运行。

在 XML 中添加这行代码的位置在哪里? - Vivek Barai

0

这段代码对我有效,无需在您的活动中添加clickListener()或focusChanhgeListener(),只需覆盖onUserInteraction()函数即可。

@Override
public void onUserInteraction() {
    super.onUserInteraction();
    if (editText.hasFocus() ) { // to check if user is clicked on edit text 
        if (scroll.getVerticalScrollbarPosition() != scroll.getBottom())  // if scrollview is not already on the bottom 
            scroll.post(() -> scroll.scrollTo(0, scroll.getBottom()));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接