作者:我们要疯_475 | 来源:互联网 | 2023-07-31 17:26
1.背景相信大家在自己的项目中都会遇到EditText输入的问题,自然而然随之产生的就是让人头痛的键盘问题了,之所以说让人头疼是因为需求不同,设计不同,我们所要做的处理也不同,加上Googl
1.背景
相信大家在自己的项目中都会遇到EditText输入的问题,自然而然随之产生的就是让人头痛的键盘问题了,之所以说让人头疼是因为需求不同,设计不同,我们所要做的处理也不同,加上Google爸爸并没有针对键盘状态的API,所以只能靠我们自己处理。小白最近遇到的问题是:当键盘弹出的的时候,将输入框移到距离屏幕最上方20像素的地方,键盘收起时复位,所以有两个问题:
1.键盘弹出收起状态监听
2.将指定View移动到指定位置
来两张效果图:分别是弹出前和弹出后
第二个问题好处理,我们可以使用以下几种方式将View移动到指定位置
1.位移动画
2. 属性动画
3.scrollTo/scrollBy
4.改变View的param
本文的目的就是针对第一个问题进行处理,最后以工具类的的形式贴出,然后以接口的形式暴露出键盘改变后的状态。方便大家使用。
首先针对键盘与窗口的交互模式,Android提供了一个属性windowSoftInputMode,该属性为我们的输入法创建了一个Dialog,并且将该Dialog的Window的某些参数(如Gravity)进行了设置,使之能够在底部或者全屏显示。当我们点击输入框时,系统对活动主窗口进行调整,从而为输入法腾出相应的空间,然后将该Dialog显示在底部,或者全屏显示。
该属性可选的值有两部分,一部分为软键盘的状态控制,另一部分是活动主窗口的调整。
windowSoftInputMode的取值可以是下面中的一个或者一个state和一个adjust组合的形式,使用|连接。
- stateUnspecified:软键盘的状态(隐藏还是可见)没有确定,系统会根据主题当中的设置选取一个合适的状态(默认值),设置改属性之后和未设置属性值效果图一样,省略
- stateUnchanged:软键盘被保持无论它上次是什么状态,是否可见或隐藏,当主窗口出现在前面时
- stateHidden:用户选择activity时,软键盘总是被隐藏,适用于界面初始化键盘收起状态(从别的页面启动该页面)
- stateAlwaysHidden:软键盘总是被隐藏的,当该 Activity主窗口获取焦点时(即使从别的页面返回到该页面)
- stateVisible :软键盘是可见的,当那个是正常合适的时 (当用户导航到 Activity主窗口,即使该窗口没有EditText )
- stateAlwaysVisible :当用户选择这个 Activity时,软键盘是可见的,和stateVisible不同的是,当我们跳转到下个界面,如果下个页面软键盘是隐藏的,而我们再次回来的时候,软键盘就会显示出来
- adjustUnspecified:设置软键盘与软件的显示内容之间的显示关系。默认的设置模式,在这中情况下,系统会根据界面选择不同的模式
- adjustResize:窗口总是调整屏幕的大小用以保证软键盘的显示空间,设置这个模式以后,窗口的decorView 大小本身并不会改变,但是我们的内容区 contentView (id = android.R.content) 会相应的缩小,为键盘的显示挪出空间。软键盘弹出后 contentView 高度变化的差值即为软键盘高度。
- adjustPan: 窗口(DecorView) 大小不变。当获取到焦点的 EditText 位于屏幕下方。这个属性用的比较多,常常配合 ScrollView 来使用
- adjustNothing:窗口不会做任何调整,contentView 大小也不会改变
3.键盘弹出收起监听的原理
上面我们介绍过的属性,有一个属性特别重要,那就是:adjustSize,设置adjustSzie属性后,所在Activity的DecorView的大小会发生变化 ,那我们是不是可以利用这个变化来监测键盘状态呢?当然可以:
- 1.记录键盘未弹出时decorView 的高度,假设为:mOriginHeight,同时保存为变化之前的高度,假设为:mUnChangeHeight(这个可以监听ViewTreeObserver的OnGlobalLayoutListener接口-当一个视图树的布局发生改变时,可以被ViewTreeObserver监听)
- 2.当键盘弹出后,整个页面的视图树会进行重绘,再次获取decoView的高度,假设为mCurrentHeight,同时更新mUnChangeHeight(始终更新为最后一次Decoview的高度)
- 3.比较mOriginHeight和mCurrentHeight,若不相等则键盘状态发生变化,同时
- 4.若发生变化,则比较mCurrentHeight和mOriginHeight,若相等,则键盘收起,若不相等,则键盘弹出,且键盘高度为:mOriginHeight - mCurrentHeight
4.封装实现
1.新建一个类,实现ViewTreeObserver.OnGlobalLayoutListener接口
public class KeyboardManager implementsViewTreeObserver.OnGlobalLayoutListener {
}
2.定义记录状态的变量
private int mOriginHeight;
private int mPreHeight;
3.onGlobalLayout回调中判断键盘状态(键盘状态改变时,由于设置的adjustResize会触发该回调)
@Override
public void onGlobalLayout() {
int currentHeight = mContentView.getHeight();
if (currentHeight == 0) {
return;
}
boolean isChange = false;
if (mUnChangeHeight == 0) {
mUnChangeHeight = currentHeight;
mOriginHeight = currentHeight;
} else {
if (mUnChangeHeight != currentHeight) {
isChange = true;
mUnChangeHeight = currentHeight;
} else {
isChange = false;
}
}
if (isChange) {
boolean isShow;
int keyboardHeight = 0;
if (mOriginHeight == currentHeight) {
isShow = false;
} else {
keyboardHeight = mOriginHeight - currentHeight;
isShow = true;
}
}
}
5工具类和使用
/**
* 键盘管理类
* Created by fanxudong on 2017/7/11.
*/
public class KeyboardManager implements ViewTreeObserver.OnGlobalLayoutListener {
private View mContentView;
private int mOriginHeight;
private int mUnChangeHeight;
private KeyBoardChangeListener mKeyBoardListen;
public static KeyboardManager getInstance(Activity activity){
return new KeyboardManager(activity);
}
public interface KeyBoardChangeListener {
void onKeyboardChange(boolean isShow, int keyboardHeight);
}
public void addOnKeyBoardChangeListener(KeyBoardChangeListener keyBoardChangeListen) {
this.mKeyBoardListen = keyBoardChangeListen;
}
public KeyboardManager(Activity activity) {
if (activity == null) {
return;
}
mCOntentView= findContentView(activity);
if (mContentView != null) {
addContentTreeObserver();
}
}
private View findContentView(Activity contextObj) {
return contextObj.findViewById(android.R.id.content);
}
private void addContentTreeObserver() {
mContentView.getViewTreeObserver().addOnGlobalLayoutListener(this);
}
@Override
public void onGlobalLayout() {
int currentHeight = mContentView.getHeight();
if (currentHeight == 0) {
return;
}
boolean isChange = false;
if (mUnChangeHeight == 0) {
mUnChangeHeight = currentHeight;
mOriginHeight = currentHeight;
} else {
if (mUnChangeHeight != currentHeight) {
isChange = true;
mUnChangeHeight = currentHeight;
} else {
isChange = false;
}
}
if (isChange) {
boolean isShow;
int keyboardHeight = 0;
if (mOriginHeight == currentHeight) {
isShow = false;
} else {
keyboardHeight = mOriginHeight - currentHeight;
isShow = true;
}
if (mKeyBoardListen != null) {
mKeyBoardListen.onKeyboardChange(isShow, keyboardHeight);
}
}
}
public void destroy() {
if (mContentView != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mContentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
}
}
使用:
KeyboardManager.getInstance(this).addOnKeyBoardChangeListener(new KeyboardManager.KeyBoardChangeListener() {
@Override
public void onKeyboardChange(boolean isShow, int keyboardHeight) {
if(isShow){
}else {
}
}
});
以上就是小白对键盘状态的总结,希望对大家有用!