点击EditText弹出软键盘遮挡其下面控件

时间:2021-05-19 15:58:05

一、概述

—–我们在开发中可能会遇到当我们的输入框EditText获取到焦点后,软件盘弹出遮挡了我们的一些控价。这种情况尤其带注册和登录的界面比较常见。虽然这不是什么大问题,但它却是很影响我们的用户体验。本文就是来解决这个小题目。

二、需解决两个问题

  • 1、当第一次进入界面是,EditText控件会获取到焦点,弹出软件盘

——–解决办法:在activity中的onCreate()方法中加入以下代码:

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

—–该方法的调用放在setContentView()方法之前。这句代码的意思是设置软件盘隐藏并且在弹出软件盘后能自适应屏幕。

  • 2、在用到上述的设置后,弹出的软件盘会遮挡EditText下的第一个控件(本例是第一个Button)以下的部分,这里不加margin属性。

——在我们知道了问题后,解决问题也就有了方向。经过测试,得出结论,当软件盘弹出后,我们布局变化的原因是因为屏幕发生了上移,然而我们最外层的布局就是依赖屏幕的尺寸而创建的(高度设置为match-parent)。换言之,我们只要操作最外层的layout布局就可以了。当其高度大小发生改变时,给我们一个回调,我们根据其变化就知道是否弹出软件盘,当弹出软件盘时,我们给它设置padding-top为一定的负值,这个值就是遮挡的高度,肯定是可以得到的。当软件盘消失时,将这个值置零。我们的问题解决思路就是这个样子。

—–接下来就是自定义我们最外层布局的时候了,就叫他SoftInputJustLayout吧(这个随便你了),别说话,看代码:

package view;  
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Display;
import android.widget.RelativeLayout;
/**
* Created by we on 10/15/15.
*/

public class SoftInputJustLayout extends RelativeLayout {
private int width;
private int height;
private int screenHeight;
private boolean sizeChanged = false;
private OnSizeChangedListener onSizeChangedListener;
public SoftInputJustLayout(Context context) {
super(context);
init(context);
}
public SoftInputJustLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SoftInputJustLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}

private void init(Context context) {
DisplayMetrics dm=new DisplayMetrics();
((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(dm);
screenHeight = dm.heightPixels;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
this.width = widthMeasureSpec;
this.height = heightMeasureSpec;
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//监听不为空、宽度不变、当前高度与历史高度不为0
if (this.onSizeChangedListener != null && w == oldw && h != 0 && oldh != 0)
{
if (h >= oldh )
//有的此处是获取了屏幕的高度,当高度变化1/4屏高时才认为发生变化,我认为这是没必要的。现在的高度小于原来的高度不就是软件盘弹出所致么。这里可能有人考虑到有的手机下面会有虚拟的手机按键(home mune back)我在这里就忽略这个问题
{
sizeChanged = false;
} else {
sizeChanged = true;
}
this.onSizeChangedListener.onSizeChange(sizeChanged);
measure(this.width - w + getWidth(), this.height - h + getHeight());
}
}

//设置监听
public void setOnSizeChangedListener(OnSizeChangedListener onSizeChangedListener) {
this.onSizeChangedListener = onSizeChangedListener;
}
//定义回调接口
public abstract interface OnSizeChangedListener {
public abstract void onSizeChange(boolean isChanged);
}
}

—– 可能会有细心的朋友会问为什么onSizeChange()方法中设置的pading-top为-btn的两倍,因为我最后一个EditText下面有3个button要显示,而软件盘弹出时会遮挡EditText下面的一个(为啥是一个,原因我也不知道)。当然如果你设置了e最后一个EditText以下的控价的margin值,那也必须的都得加上才不会使有些控件被遮挡。

——正是因为这个padding-top值的计算有些麻烦,那么我们就必须找到更好的解决办法,很简单的多哦,只需在我们的activity_main.xml文件中的id=ll_main_login的布局外加上ScrollView,找到该控件,然后在onSizeChange()方法里面做处理(具体代码自己参考如下写吧,肯定没错的。

    @Override  
public void onSizeChange(boolean isChanged)
{
if (isChanged) {
mScrollView.scrollTo(00);
}

最后实现的效果图

————-点击EditText弹出软键盘遮挡其下面控件

—————源码下载源码链接

这是我程序员生涯的第一次写博客,欢迎大家评阅