Android软件盘顶起底部控件的解决方案

 情景描述:当Activity的布局中有RecyclerView,ListView等列表控件时,软件盘弹出会将底部控件顶起,这时底部控件可能遮挡住一些我们想要显示的内容,如下图所示,输入框就被遮挡住了,这肯定不是我们想要的结果。

 

解决方案:这里提供两种解决方案。(只需要使用其中一种即可)

1. 在AndroidManifest文件中,给当前Activity配置android:windowSoftInputMode="adjustPan|stateHidden"属性。

作用:adjustPan 软件弹出布局自适应,stateHidden 进入页面时隐藏软键盘(不需要隐藏的话可以不设置该值)
此种方式当软键盘弹出时,布局会整体向上移动,且不可滑动。效果图如下:

 

2. 监听软键盘的显示和隐藏,当软键盘显示时隐藏底部控件,当软件盘隐藏时显示底部控件。此种方式当软键盘弹出时,NestedScrollView之上的内容不会移动(例如图中的ActionBar和TextView),NestedScrollView中的内容会向上移动,且NestedScrollView中的内容可滑动。效果图如下:

 

键盘监听源码:

Java版:

package com.lct.softkeyboard;

import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;

/**
 * Author:SkySmile
 * Date:2018/11/6
 * Description:软键盘显示与隐藏的监听
 */
public class SoftKeyBoardUtil {
    //纪录根视图的显示高度
    private static int rootViewVisibleHeight;

    public static void addOnSoftKeyBoardListener(Activity activity,
                                                 final OnSoftKeyBoardListener listener) {
        //activity的根视图
        final View rootView = activity.getWindow().getDecorView();

        //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        //获取当前根视图在屏幕上显示的大小
                        Rect rect = new Rect();
                        rootView.getWindowVisibleDisplayFrame(rect);
                        int visibleHeight = rect.height();
                        if (rootViewVisibleHeight == 0) {
                            rootViewVisibleHeight = visibleHeight;
                            return;
                        }
                        //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
                        if (rootViewVisibleHeight == visibleHeight) {
                            return;
                        }
                        //根视图显示高度变小超过200,可以看作软键盘显示了
                        if (rootViewVisibleHeight - visibleHeight > 200) {
                            listener.keyBoardShow();
                            rootViewVisibleHeight = visibleHeight;
                            return;
                        }
                        //根视图显示高度变大超过200,可以看作软键盘隐藏了
                        listener.keyBoardHide();
                        rootViewVisibleHeight = visibleHeight;
                    }
                });
    }

    public interface OnSoftKeyBoardListener {
        void keyBoardShow();

        void keyBoardHide();
    }
}

 

Kotlin版:

/**
 * 软件盘隐藏||显示的监听
 */
fun Activity.setOnSoftKeyBoardListener(listener: OnSoftKeyBoardChangeListener) {
    //activity的根视图
    val rootView = window.decorView
    //纪录根视图的显示高度
    var rootViewVisibleHeight = 0
    //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
    rootView.viewTreeObserver.addOnGlobalLayoutListener {
        //获取当前根视图在屏幕上显示的大小
        val rect = Rect()
        rootView.getWindowVisibleDisplayFrame(rect)
        val visibleHeight = rect.height()
        if (rootViewVisibleHeight == 0) {
            rootViewVisibleHeight = visibleHeight
            return@addOnGlobalLayoutListener
        }
        //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
        if (rootViewVisibleHeight == visibleHeight) {
            return@addOnGlobalLayoutListener
        }
        //根视图显示高度变小超过200,可以看作软键盘显示了
        if (rootViewVisibleHeight - visibleHeight > 200) {
            listener.keyBoardShow()
            rootViewVisibleHeight = visibleHeight
            return@addOnGlobalLayoutListener
        }
        //根视图显示高度变大超过200,可以看作软键盘隐藏了
        listener.keyBoardHide()
        rootViewVisibleHeight = visibleHeight
        return@addOnGlobalLayoutListener
    }
}

interface OnSoftKeyBoardChangeListener {
    fun keyBoardShow()

    fun keyBoardHide()
}

 

使用方法(这里只给出了java版的调用方式。kotlin版的调用也很简单,因为定义为了Activity的扩展函数,所以在Activity中直接调用setOnSoftKeyBoardListener即可): 

package com.lct.softkeyboard;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

/**
 * 当Activity的布局中有RecyclerView,ListView等列表控件时,软件盘弹出会将底部控件顶起。
 * 这里总结两种解决方式:
 * 1.在AndroidManifest文件中,给当前Activity配置android:windowSoftInputMode="adjustPan|stateHidden"属性,
 * 作用:adjustPan 软件弹出布局自适应,stateHidden 进入页面时隐藏软键盘(不需要隐藏的话可以不设置该值)
 * 此种方式当软键盘弹出时,布局会整体向上移动,且不可滑动
 * <p>
 * 2.监听软键盘的显示和隐藏,当软键盘显示时隐藏底部控件,当软件盘隐藏时显示底部控件
 * 此种方式当软键盘弹出时,NestedScrollView之上的内容不会移动,NestedScrollView中的内容会向上移动,
 * 且NestedScrollView中的内容可滑动
 */
public class MainActivity extends AppCompatActivity {
    private Button btnBottom;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnBottom = findViewById(R.id.btn_bottom);

        //软键盘监听事件
        SoftKeyBoardUtil.addOnSoftKeyBoardListener(this,
                new SoftKeyBoardUtil.OnSoftKeyBoardListener() {

                    @Override
                    public void keyBoardShow() {
                        //软键盘弹出,隐藏底部控件
                        btnBottom.setVisibility(View.INVISIBLE);
                    }

                    @Override
                    public void keyBoardHide() {
                        //软键盘消失,显示底部控件
                        btnBottom.setVisibility(View.VISIBLE);
                    }
                });
    }
}

activity_main.xml文件 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_top"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="NestedScrollView之上的内容" />

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_top">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/tv"
                android:layout_width="match_parent"
                android:layout_height="230dp"
                android:paddingTop="20dp"
                android:text="NestedScrollView中的测试填充内容,高度设置为230dp是为了使键盘弹出时遮住输入框" />

            <EditText
                android:id="@+id/et"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/tv"
                android:hint="测试输入框" />

            <!--当布局中有RecyclerView,ListView等列表控件时,软件盘弹出时会顶起底部控件-->
            <!--此处添加的RecyclerView,只是为了展示效果-->
            <android.support.v7.widget.RecyclerView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/et" />
        </RelativeLayout>
    </android.support.v4.widget.NestedScrollView>

    <Button
        android:id="@+id/btn_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="被顶起的底部控件" />
</RelativeLayout>

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值