android 软件盘未弹出如何获取高度,Android 软键盘的那些坑,一招搞定!

3

软键盘高度获取

对于上面的问题1,既然想要EditText单独顶上去,那么就需要知道当前键盘弹出的高度,再设置EditText坐标即可。

问题的关键转变为如何获取键盘的高度。

Activity窗口的构成

通常来说,手机由状态栏、内容区域、导航栏组成。

一般情况下(除去导航栏隐藏,状态栏沉浸)对于我们来说,写的布局文件都会展示在内容区域,这部分是"能看到的"。

当键盘弹出的时候,会遮盖部分内容区域:

20ec2c9ac240701a69e8f7099abe68df.png

因此,需要将被遮住的部分往上移动,移动多少呢?

通过调用方法:

#View.java

publicvoidgetWindowVisibleDisplayFrame( Rect outRect){

...

}

可见区域的位置记录在outRect里,而整个屏幕高度是已知的,因此就可以计算出被遮挡的区域需要顶上去的偏移量。

一个通用的计算方式

根据上面的分析,将计算方法封装一下:

publicclassSoftInputUtil{

privateintsoftInputHeight = 0;

privatebooleansoftInputHeightChanged = false;

privatebooleanisNavigationBarShow = false;

privateintnavigationHeight = 0;

privateView anyView;

privateISoftInputChanged listener;

privatebooleanisSoftInputShowing = false;

publicinterfaceISoftInputChanged{

voidonChanged( booleanisSoftInputShow, intsoftInputHeight, intviewOffset);

}

publicvoidattachSoftInput( finalView anyView, finalISoftInputChanged listener){

if(anyView == null|| listener == null)

return;

//根View

finalView rootView = anyView.getRootView;

if(rootView == null)

return;

navigationHeight = getNavigationBarHeight(anyView.getContext);

//anyView为需要调整高度的View,理论上来说可以是任意的View

this.anyView = anyView;

this.listener = listener;

rootView.addOnLayoutChangeListener( newView.OnLayoutChangeListener {

@Override

publicvoidonLayoutChange(View v, intleft, inttop, intright, intbottom, intoldLeft, intoldTop, intoldRight, intoldBottom){

//对于Activity来说,该高度即为屏幕高度

introotHeight = rootView.getHeight;

Rect rect = newRect;

//获取当前可见部分,默认可见部分是除了状态栏和导航栏剩下的部分

rootView.getWindowVisibleDisplayFrame(rect);

if(rootHeight - rect.bottom == navigationHeight) {

//如果可见部分底部与屏幕底部刚好相差导航栏的高度,则认为有导航栏

isNavigationBarShow = true;

} elseif(rootHeight - rect.bottom == 0) {

//如果可见部分底部与屏幕底部平齐,说明没有导航栏

isNavigationBarShow = false;

}

//cal softInput height

booleanisSoftInputShow = false;

intsoftInputHeight = 0;

//如果有导航栏,则要去除导航栏的高度

intmutableHeight = isNavigationBarShow == true? navigationHeight : 0;

if(rootHeight - mutableHeight > rect.bottom) {

//除去导航栏高度后,可见区域仍然小于屏幕高度,则说明键盘弹起了

isSoftInputShow = true;

//键盘高度

softInputHeight = rootHeight - mutableHeight - rect.bottom;

if(SoftInputUtils. this.softInputHeight != softInputHeight) {

softInputHeightChanged = true;

SoftInputUtils. this.softInputHeight = softInputHeight;

} else{

softInputHeightChanged = false;

}

}

//获取目标View的位置坐标

int[] location = newint[ 2];

anyView.getLocationOnScreen(location);

//条件1减少不必要的回调,只关心前后发生变化的

//条件2针对软键盘切换手写、拼音键等键盘高度发生变化

if(isSoftInputShowing != isSoftInputShow || (isSoftInputShow && softInputHeightChanged)) {

if(listener != null) {

//第三个参数为该View需要调整的偏移量

//此处的坐标都是相对屏幕左上角(0,0)为基准的

listener.onChanged(isSoftInputShow, softInputHeight, location[ 1] + anyView.getHeight - rect.bottom);

}

isSoftInputShowing = isSoftInputShow;

}

}

});

}

//***************STATIC METHOD******************

publicstaticintgetNavigationBarHeight(Context context){

if(context == null)

return0;

Resources resources = context.getResources;

intresourceId = resources.getIdentifier( "navigation_bar_height", "dimen", "android");

intheight = resources.getDimensionPixelSize(resourceId);

returnheight;

}

publicstaticvoidshowSoftInput(View view){

if(view == null)

return;

InputMethodManager inputMethodManager = (InputMethodManager)view.getContext.getSystemService(Context.INPUT_METHOD_SERVICE);

if(inputMethodManager != null) {

inputMethodManager.showSoftInput(view, 0);

}

}

publicstaticvoidhideSoftInput(View view){

if(view == null)

return;

InputMethodManager inputMethodManager = (InputMethodManager)view.getContext.getSystemService(Context.INPUT_METHOD_SERVICE);

if(inputMethodManager != null) {

inputMethodManager.hideSoftInputFromWindow(view.getWindowToken, 0);

}

}

}

使用方式如下:

在 Activity里加如下代码:

privatevoidattachView{

//editText2为需要调整的View

editText2 = findViewById(R.id.et2);

SoftInputUtil softInputUtil = newSoftInputUtil;

softInputUtil.attachSoftInput(editText2, newSoftInputUtil.ISoftInputChanged {

@Override

publicvoidonChanged( booleanisSoftInputShow, intsoftInputHeight, intviewOffset){

if(isSoftInputShow) {

editText2.setTranslationY(et2.getTranslationY - viewOffset);

} else{

editText2.setTranslationY( 0);

}

}

});

}

并且将windowSoftInputMode设置为SOFT_INPUT_ADJUST_RESIZE。

android:windowSoftInputMode= "adjustResize|stateAlwaysHidden"

stateAlwaysHidden为默认不显示键盘。

再来看Activity的布局文件:

< LinearLayoutxmlns:android= "http://schemas.android.com/apk/res/android"

xmlns:tools= "http://schemas.android.com/tools"

android:id= "@+id/myviewgroup"

android:layout_width= "match_parent"

android:layout_height= "match_parent"

android:orientation= "vertical"

android:layout_gravity= "center_vertical"

tools:context= ".MainActivity">

< ImageView

android:id= "@+id/iv"

android:src= "@drawable/test"

android:background= "@color/colorGreen"

android:layout_marginTop= "20dp"

android:layout_marginBottom= "20dp"

android:layout_width= "match_parent"

android:layout_height= "300dp">

ImageView>

< EditText

android:hint= "输入框2"

android:id= "@+id/et2"

android:layout_marginTop= "100dp"

android:background= "@drawable/bg"

android:layout_gravity= "bottom"

android:layout_marginHorizontal= "10dp"

android:layout_width= "match_parent"

android:layout_height= "40dp">

EditText>

LinearLayout>

最终效果如下:

a545e15765ef59105982428069ef1128.gif

可以看出,EditText被顶上去了,其它布局没有变化。在动态切换导航栏是否展示之间EeditText也能正常显示。

这就回答了上面的问题1:当键盘弹出时,只想EditText顶上去,ImageView保持不动。

当然对于问题1的还有其它更简单的解决方式,在下一篇会分析。

以上是关于软键盘弹出、关闭、是否展示、软键盘高度、软键盘模式等效果的解析。

你可能还有如下疑惑:

SOFT_INPUT_ADJUST_PAN为什么能够将布局顶上去?

SOFT_INPUT_ADJUST_RESIZE为什么能够重新设置布局区域?

SOFT_INPUT_ADJUST_UNSPECIFIED内部逻辑如何判断?

键盘弹起为什么会执行 onLayout?

...

由于篇幅所限,这些问题将在后续推送:Android 软键盘一招搞定(原理篇)分析。

本文基于 Android 10.0。

如果您有需求,请直接拷贝文章里的SoftInputUtil.java 尝试控制键盘。若有问题,请留言,谢谢!返回搜狐,查看更多

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值