蓝色区域是输入框,获得焦点后弹出软键盘,右侧的表情按钮点击后下方会弹出表情窗口。那么弹出软键盘是什么样呢?可以看上方的图片被压缩
了。因为在Activity设置了
android:windowSoftInputMode="stateVisible|adjustResize
首先介绍一下android:windowSoftInputMode,它设置了主窗口和软键盘的交互方式,可以用来避免输入法面板遮挡问题。这个属性决定了两个问
题:
1.当有焦点产生时,软键盘是显示还是隐藏。
2.是否改变主窗口的大小以容纳软键盘。
取值有以下几种情况,可以是两个的组合。
【A】stateUnspecified:软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置
【B】stateUnchanged:当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示
【C】stateHidden:用户选择activity时,软键盘总是被隐藏
【D】stateAlwaysHidden:当该Activity主窗口获取焦点时,软键盘也总是被隐藏的
【E】stateVisible:软键盘通常是可见的
【F】stateAlwaysVisible:用户选择activity时,软键盘总是显示的状态
【G】adjustUnspecified:默认设置,通常由系统自行决定是隐藏还是显示
【H】adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间
【I】adjustPan:当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分
下面介绍一下关于软键盘的知识。
软键盘显示的原理
软键盘本质上是一个Dialog,InputMethodService为我们的输入法创建了一个Dialog,并且为我们的Dialog设置了某些window参数,如Gravity,可
以使其显示在底部或者全屏显示,通常在点击编辑框时,系统会对活动主窗口进行调整,使之腾出空间来放置软键盘在底部或者全屏显示。
主窗口的调整
windowsSoftInputMode该属性可选的值有两部分,软键盘的状态控制和主窗口的调整。现在只讨论主窗口的调整方式,有以下三个模式。
模式一:压缩模式(adjustResize)
本文前面所呈现的效果就是使用adjustResize的效果。该模式下Activity总是调整窗口的大小以腾出空间来容纳软键盘,这样原来的窗口的高度就会减少,这个视图会被压缩。
模式二:平移模式(adjustPan)
该模式下会将原来的视图向上平移,以便当前的焦点不被软键盘遮挡。这样可以让用户看到输入的内容,但这个视图向上平移了。
效果图如下,这里只会平移输入框及其上方的视图,如果在输入框下方有其他视图且未获取到焦点,那么不会将其顶到上方。事实上,当输入框不会被遮挡时,在该模式下并不会对布局进行调整,只有当输入框将要被遮挡时,窗口才会上移,所以可以说,该模式始终是保持输入框可见的。
模式三:自动模式(adjustUnspecified)
该模式下系统会从压缩模式和平移模式中选择一种,这主要依赖于布局中是否有滚动布局,如ListView,如果有那么将调整窗口的大小。
软键盘显示和隐藏的侦听
方法一:当软键盘在隐藏和显示时,会对主窗口视图进行重绘,这里我们利用这个特性来实现对软键盘的侦听。当模式为adjustResize时,会调用
onSizeChanged函数,如果是adjustPan,则不会被调用。(注意:onSizeChanged函数是在View的layout函数中调用的,我们要继承LinearLayout来
自定义布局,然后重写onSizeChanged,但是我们不能直接在onSizeChanged函数中就对视图进行调整(比如隐藏或显示表情框),因为这样会导致
重新调用layout函数,所以我们使用Handler。)
方法二:对ViewRoot进行监听
现在通过对软键盘显示和隐藏的侦听来实现:当点击表情图片,若软键盘是弹出的,要隐藏软键盘,显示表情框,点击编辑窗输入时,隐藏表情框,显示软键盘。
final View activityRootView=(View)findViewById(R.id.activityRootView);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener(){
@Override
public void onGlobalLayout() {
//当视图由于软键盘的加入导致改变时调用
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) {
// 如果高度差超过100像素,就很有可能是有软键盘...
if(faceLayout.isShown()){
//faceLayout是表情框,当表情框显示时,要隐藏到
faceLayout.setVisibility(View.GONE);
}
}
}
});