Android开发软键盘遮挡问题汇总

先上效果图:

当软键盘出来的时候会自动把登录按钮顶上去,显示出来,就不会有遮挡的情况了



前言:

最近好多人在开发中都遇到了登录界面或者其他地方,弹出软键盘的时候遮挡按钮或者输入框的问题,所以在这里集思广益将网上大部分的思路整合一下,贴出来

写了一个Demo演示一下:


正常情况下是这样的,不过软键盘弹出来就变成了:




可以看到将两个按钮遮住了一个半.




正文:

Android虽然提供了WindowSoftInputMode,亲测,效果并不是很好,达不到预期的效果,这里从网上扒了扒主要的实现思路,这里感谢:
http://blog.csdn.net/nn955/article/details/17717749


开始了,主要有两种思路:


1.通过窗体的根View求出总的区域和可视区域就可以计算出被遮挡的区域的高度,如果超过一定的值就是软键盘弹出了,然后将根View ScrollTo到一个位置

2.自定义根View,集成(FrameLayout,LinearLayout,RelativeLayout需要什么集成什么),当软键盘弹出的时候肯定会走onSizeChange方法,这里重写onSizeChange方法,在里面做我们的逻辑即可

只要判断出了软键盘弹出之后,思路就很开阔了,可以根据自己的情况选择怎么实现,这里提供几种常用的思路:
(1) 移动到指定的位置,不让软键盘遮挡
(2) 改变布局的PaddingTop,网上移动一段距离,让遮挡的部分显示出来
(3) 改变某一个View的高度,让其他显示出来
(4) 隐藏某一个View,让其他的显示出来
........................

贴出代码:

<?xml version="1.0" encoding="utf-8"?>
<com.example.justin.takephotodemo.MyLinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp"
    tools:context="com.example.justin.takephotodemo.MainActivity">


    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@drawable/csdn"
        android:layout_marginBottom="10dp"
        />

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入用户名"/>

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入密码"/>

    </android.support.design.widget.TextInputLayout>

    <Button
        android:id="@+id/register"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="select"
        android:text="注册"/>

    <Button
        android:id="@+id/login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="登录"/>


</com.example.justin.takephotodemo.MyLinearLayout>

第一种思路的实现:





通过图可以看出,得到总的高度,和获取可见区域的高度就可以算出被隐藏的高度,通过比较即可判断是否是软键盘弹出了
计算RootView要移动的距离,需要知道被移动View的坐标,通过坐标的高度加上本身View的高度,减去可见区域的bottom就是要移动的距离
好吧,图画的有点抽象,........................

在onCreate中:
        mLayout = (LinearLayout) findViewById(R.id.layout);
        mIv = (ImageView) findViewById(R.id.iv);
        Button mLogin = (Button) findViewById(R.id.login);

        autoScrollView(mLayout,mLogin);

    /**这里判断出软键盘弹出,之后的逻辑可以自己定,1.隐藏 2.移动3.改变高度4.改变paddingTop.......都可以
     * @param root 最外层的View
     * @param scrollToView 不想被遮挡的View,会移动到这个Veiw的可见位置
     */
    private void autoScrollView(final View root, final View scrollToView) {
        root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect rect = new Rect();
                //获取root在窗体的可视区域
                root.getWindowVisibleDisplayFrame(rect);
                //获取root在窗体的不可视区域高度(被遮挡的高度)
                int rootInvisibleHeight = root.getRootView().getHeight() - rect.bottom;
                //若不可视区域高度大于150,则键盘显示
                if (rootInvisibleHeight > 150) {
                    int[] location = new int[2];
                    //获取scrollToView在窗体的坐标
                    scrollToView.getLocationInWindow(location);
                    //计算root滚动高度,使scrollToView在可见区域的底部
                    int srollHeight = (location[1] + scrollToView.getHeight()) - rect.bottom;
                    root.scrollTo(0, srollHeight);
                } else {
                    //键盘隐藏
                    root.scrollTo(0, 0);
                }
            }
        });
    }


第二种实现方式:


注意:需要在AndroidManifest中加上
android:windowSoftInputMode="adjustResize"

自定义layout
public class MyLinearLayout extends LinearLayout {
    public MyLinearLayout(Context context) {
        super(context);
    }

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

    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (oldh > 0) {
            int screenHeight = this.getRootView().getHeight();
            if (oldh - h >= screenHeight / 3) {//弹出 (之后的逻辑可以自己定,1.隐藏 2.移动3.高度4.paddingTop.......)
                Toast.makeText(getContext(), "弹出", Toast.LENGTH_SHORT).show();
            } else {//隐藏
                Toast.makeText(getContext(), "隐藏", Toast.LENGTH_SHORT).show();
            }
        }
    }

}

好的以上内容就是这些了,第一次写博客,有些仓促,如果有什么错误或不妥的地方,欢迎大家评论,我会积极改正...





猜你喜欢

转载自blog.csdn.net/Justin_1107/article/details/52290705