当软键盘弹出时调整布局

37

我在一些应用程序中看到当软键盘展示时布局会发生变化。这肯定不是 adjustPan,因为整个布局(可能是内部布局)都会移动,而不仅仅是当前的 EditText。例如,在 Evernote 登录屏幕中就有此现象。请问如何实现这种效果?


你的问题是键盘弹出时布局上移吗? - Lalit Poptani
1
问题是如何做到这一点。 - Eugene
你的意思是你不想让你的布局向上拉起,对吗? - Lalit Poptani
2
如果您为活动设置了adjustPan选项,并且当软键盘显示时,界面将向上移动以显示您当前输入文本的editText,这是完全可以的。我的问题是如何使整个布局不可见,而只显示活动的editText(s)。 - Eugene
1
我不太明白你的意思,你只想让EditText可见,而不是整个布局。如果你能附上一些屏幕截图会更好。 - Lalit Poptani
6个回答

70

这里有一个类似Evernote登录界面的解决方案:

首先,定义一个类,并将其设置为您特殊的LinearLayout类型,如下所示:

public class MyLayout extends LinearLayout {

public MyLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public MyLayout(Context context) {
    super(context);
}

private OnSoftKeyboardListener onSoftKeyboardListener;

@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
    if (onSoftKeyboardListener != null) {
        final int newSpec = MeasureSpec.getSize(heightMeasureSpec); 
        final int oldSpec = getMeasuredHeight();
        if (oldSpec > newSpec){
            onSoftKeyboardListener.onShown();
        } else {
            onSoftKeyboardListener.onHidden();
        }
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

public final void setOnSoftKeyboardListener(final OnSoftKeyboardListener listener) {
    this.onSoftKeyboardListener = listener;
}

public interface OnSoftKeyboardListener {
    public void onShown();
    public void onHidden();
}

}

该布局会监听大小的变化,如果新的测量值小于旧的测量值,那就意味着键盘挡住了屏幕的一部分。

然而,为了使其正常工作,在您的清单中需要设置android:windowSoftInputMode="adjustResize",这样内容将被调整大小而不仅仅是移动位置。

整个系统的工作方式如下:

<MyLayout id="layout">
  <SomeImage id="image"/>
  <SomeText>
  <SomeInput>
</MyLayout>

它就像 Evernote 的登录界面。 然后,在您的活动中:

((MyLayout)findViewById(R.id.layout)).setOnSoftKeyboardListener(new OnSoftKeyboardListener() {
        @Override
        public void onShown() {
            findViewById(R.id.image).setVisibility(View.GONE);
        }
        @Override
        public void onHidden() {
            findViewById(R.id.image).setVisibility(View.VISIBLE);
        }
    });

然后转到manifest.xml并设置

android:windowSoftInputMode="adjustResize"

当软键盘弹出时,会隐藏图片并调整其余内容的大小。(您实际上可以在Evernote中看到文本如何被调整)

隐藏图像当然是众多可行方案之一。但是必须小心,因为不同的布局更改也将调用onMeasure。

当然,这是一个不太优雅的变体。您需要检查方向更改,并在实际测量时间和比较新规格与旧规格时可能需要一些额外的逻辑。但我认为这是唯一的方法。


1
我们在项目中也采用了相同的方法。虽然不太喜欢,但似乎这是在 Android 2.x 上挂钩 IME 显示/隐藏事件的唯一方法。 - Michael
4
有时会出现一些错误。这个版本更好:https://dev59.com/WHI95IYBdhLWcg3wyRM0#4737265 - Patrick Boos
3
在Galaxy S4上运行不正确。要更正,需要将if (oldSpec > newSpec) ... else ...替换为if (oldSpec < newSpec),并在测量保持不变时用if语句替换'else'以避免当前代码触发onHidden()函数。 - Jonathan Wareham
正如其他链接答案中提到的那样,@JonathanWareham,您还应该采取类似于100像素的任意边距来避免误报。 - Marc Plano-Lesay

10

在AndroidManifest.xml中使用"adjustResize"代替"adjustPan"

<activity
    ...
    android:windowSoftInputMode="adjustResize" />

根据文档:

"adjustResize"
无论何时软键盘出现,activity的主窗口都会被调整大小以腾出空间。

"adjustPan"
activity的主窗口不会被调整大小来为软键盘腾出空间。相反,窗口的内容会自动平移,以确保当前焦点不被键盘遮挡,用户可以随时看到他们正在输入什么内容。通常情况下调整大小比这种方式更可取,因为用户可能需要关闭软键盘才能访问和与窗口中被遮盖的部分进行交互。



2

谢谢,它正在工作。在我的情况下,布局太复杂了,在活动中进行一些定位后,当键盘出现时,它可能会崩溃(内存不足)。 - CoolMind
这些变通方法很危险,因为如果库更新了,就会出现冲突,事实上对我并不起作用。有时最好的解决方案不是变通,而是从另一个角度看问题。 - AlexPad

2
这对我很有帮助。将此放在您的oncreate中即可。
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE|WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

0

在父布局中使用滚动视图,并从清单文件中删除adjustpan或adjustresize设置。 在您的布局中使用ScrollView将为您提供免费的功能,可以滚动您的面板或布局,并保护您的布局不被工具栏或操作栏覆盖,也不会隐藏布局内的按钮或文本字段。请记住,您必须在基本布局中使用ScrollView,因此此ScrollView将作为整个屏幕的基本布局。 示例

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

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

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <!-- Add here which you want -->
    </LinearLayout>
</ScrollView>


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