版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

演示获取软键盘高度并保存,然后根据输入框的原有位置是否被软键盘挡住了,如果被挡住了则将整体页面上移一定的高度,当软键盘隐藏的时候再下移回来的功能。

效果图

KeyboardUtil【软键盘弹出后输入框上移一定的高度】

代码分析

KeyboardUtil:显示、隐藏软键盘,以及保存软键盘的高度值;

KeyboardSharedPreferences:SharedPreferences存储工具类;

ViewAnimationUtil:上移、下移的动画效果;

首先,获取软键盘的高度值并保存【当点击输入框,弹出软键盘的时候会进行保存,具体逻辑见代码】

//计算整体view需要移动的高度值(总高度 - 可见区域高度 + top(标题栏高度) = 隐藏区域高度(软键盘高度值))
        ((RelativeLayout)rootLayout).getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                //当保存的高度值小于300的时候执行
                // 【当APP第一次打开的时候,这里的代码也会执行,那么此时keyboardHeight==0,那么会继续执行下面代码,但是keyboardHeight计算后的值一般会小于300,所以此时不能保存keyboardHeight!!!】
                // 【当触摸输入框的时候,不管输入框在软键盘上方还是下方,此时keyboardHeight计算后的值>300】【也就是弹出系统软键盘后整体view向上移动的距离(rect.bottom值变小了),也就可以理解为系统软键盘的高度】
                if(keyboardHeight < 300) {
                    Rect rect = new Rect();
                    rootLayout.getWindowVisibleDisplayFrame(rect);//rect指可见区域
                    Log.e(TAG, "{onGlobalLayout}rootLayout.getRootView().getHeight()=" + rootLayout.getRootView().getHeight());//【移动前的rootLayout的bottom】
                    Log.e(TAG, "{onGlobalLayout}rect.bottom=" + rect.bottom);//【移动后的rootLayout的bottom】
                    Log.e(TAG, "{onGlobalLayout}rect.top=" + rect.top);//【标题栏的高度值】
                    keyboardHeight = rootLayout.getRootView().getHeight() - rect.bottom + rect.top;
                    Log.e(TAG, "{onGlobalLayout}keyboardHeight=" + keyboardHeight);//
                    if (keyboardHeight > 300) {
                        KeyboardUtil.saveKeyboardHeight(MainActivity.this, keyboardHeight);
                    }
                }else {//方案一
                    Rect rect = new Rect();
                    rootLayout.getWindowVisibleDisplayFrame(rect);//rect指可见区域
                    Log.e(TAG, "{onGlobalLayout}rect.bottom=" + rect.bottom);//【移动后的rootLayout的bottom】
                    Log.e(TAG, "{onGlobalLayout}keyboardHeight=" + keyboardHeight);//
                    if(rect.bottom != keyboardHeight){//代表软键盘隐藏了,当软键盘显示的时候,rect.bottom == keyboardHeight
                        downEditRect();
                    }
                }
            }
        });

然后,输入框添加触摸事件监听,用于上移的动画

//输入框触摸的监听事件
        edt_user.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                //【注意:edt_user.getBottom()是指系统软键盘弹出来后的输入框的bottom值,,缺少顶部标题栏的区域高度,而且连续点击后值不变】
                Log.i(TAG, "{initViews}edt_user.getBottom()=" + edt_user.getBottom());
                //计算相对于Windows的坐标
                int[] locationW = new int[2];
                edt_user.getLocationInWindow(locationW);
                Log.i(TAG, "{onTouch}locationW=" + locationW[0] +";" + locationW[1]);
                //计算相对于Screen的坐标
                int[] locationS = new int[2];
                edt_user.getLocationOnScreen(locationS);
                Log.i(TAG, "{onTouch}locationS=" + locationS[0] +";" + locationS[1]);
                Log.i(TAG, "{onTouch}edt_user.getMeasuredHeight()=" + edt_user.getMeasuredHeight());//输入框的高度

                int edtBottom = locationW[1] + edt_user.getMeasuredHeight();//输入框的底部的Y坐标值== topY + Height;
                showEditRect(edt_user,edtBottom);
                return false;
            }
        });

最后,监听软键盘隐藏、整体页面添加点击事件,实现下移动画【监听软键盘隐藏是在上面的addOnGlobalLayoutListener方法中实现的

//整个界面区域的触摸事件
        rootLayout.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                Log.v(TAG, "{initialize}rootLayout=onTouch");
                //隐藏自定义的软键盘区域
                hideEditRect();
                return true;
            }
        });

使用步骤

一、项目组织结构图

KeyboardUtil【软键盘弹出后输入框上移一定的高度】

KeyboardUtil【软键盘弹出后输入框上移一定的高度】

注意事项:

1、  导入类文件后需要change包名以及重新import R文件路径

2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

二、导入步骤

将keyboard包复制到项目中

KeyboardUtil【软键盘弹出后输入框上移一定的高度】

package com.why.project.keyboardutildemo.keyboard;


import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;

import com.why.project.keyboardutildemo.R;


/**
 * Used 软键盘的操作类(显示、隐藏软件盘、保存软键盘的高度值——用于控制输入框的上升)
 */
public class KeyboardUtil {

    /**最后一次保存的键盘高度*/
    private static int LAST_SAVE_KEYBOARD_HEIGHT = 0;

    /**输入法软键盘区域的最大高度*/
    private static int MAX_PANEL_HEIGHT = 0;
    /**输入法软键盘区域的最小高度*/
    private static int MIN_PANEL_HEIGHT = 0;

    /**显示软键盘*/
    public static void showKeyboard(View view) {
        if(view != null){
            view.requestFocus();
            InputMethodManager inputManager = (InputMethodManager)view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            if (inputManager != null) {
                inputManager.showSoftInput(view, 0);
            }
        }
    }

    /**隐藏软键盘
     * 第一个参数中的windowToken应当是之前请求显示软键盘的View的windowToken,也就是执行showSoftInput()时第一个参数中的View的windowToken。
     * 但是实际情况是,用任意一个当前布局中的已经加载的View的windowToken都可以隐藏软键盘,哪怕这个View被设置为INVISIBLE或GONE。
     * 因此,如果不知道之前是谁请求显示的软键盘,可以随便传入一个当前布局中存在的View的windowToken。
     * 特别的,可以传入一个Activity的顶层View的windowToken,即getWindow().getDecorView().getWindowToken(),来隐藏当前Activity中显示的软键盘,
     * 而不用管之前调用showSoftInput()的究竟是哪个View。*/
    public static void hideKeyboard(Activity mActivity) {
        InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm != null) {
            imm.hideSoftInputFromWindow(mActivity.getWindow().getDecorView().getWindowToken(), 0);
        }
    }

    /**隐藏软键盘*/
    public static void hideKeyboard(View view) {
        InputMethodManager imm = (InputMethodManager)view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        view.clearFocus();
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

    /**是否正在显示软键盘*/
    public static boolean isShowKeyboard(Context context, View view)
    {
        boolean bool = false;
        InputMethodManager imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm.hideSoftInputFromWindow(view.getWindowToken(), 0))
        {
            imm.showSoftInput(view, 0);
            bool = true;
        }
        return bool;
    }

    /**保存软键盘的高度值*/
    public static boolean saveKeyboardHeight(Context context, int keyboardHeight) {

        Log.d("KeyboardUtil", "keyboardHeight="+keyboardHeight);
        if(keyboardHeight <= 300 || LAST_SAVE_KEYBOARD_HEIGHT == keyboardHeight) {
            return false;
        }
        LAST_SAVE_KEYBOARD_HEIGHT = keyboardHeight;

        return KeyboardSharedPreferences.save(context, keyboardHeight);
    }
    
    /**获取软键盘的高度值*/
    public static int getKeyboardHeight(Context context) {
        if(LAST_SAVE_KEYBOARD_HEIGHT == 0) {
            LAST_SAVE_KEYBOARD_HEIGHT = KeyboardSharedPreferences.get(context, getMinPanelHeight(context.getResources()));
        }
        return LAST_SAVE_KEYBOARD_HEIGHT;
    }

    /**获取面板的最大高度值-自定义的*/
    private static int getMaxPanelHeight(Resources res) {
        if(MAX_PANEL_HEIGHT == 0) {
            MAX_PANEL_HEIGHT = res.getDimensionPixelSize(R.dimen.keyboard_content_panel_max_height);
        }
        return MAX_PANEL_HEIGHT;
    }

    /**获取面板的最小高度值-自定义的*/
    private static int getMinPanelHeight(Resources res) {
        if(MIN_PANEL_HEIGHT == 0) {
            MIN_PANEL_HEIGHT = res.getDimensionPixelSize(R.dimen.keyboard_content_panel_min_height);
        }
        return MIN_PANEL_HEIGHT;
    }
}
KeyboardUtil.java

相关文章:

  • 2021-10-24
  • 2022-12-23
  • 2021-12-30
  • 2022-12-23
  • 2021-07-01
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案