美文网首页
软键盘弹出高度监听及键盘遮挡处理

软键盘弹出高度监听及键盘遮挡处理

作者: 猫爸iYao | 来源:发表于2018-11-16 20:13 被阅读0次

    软键盘弹出高度监听工具类

    package com.iyao.inputmethodhelper;
    
    import android.annotation.TargetApi;
    import android.app.Activity;
    import android.app.Application;
    import android.graphics.Rect;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.annotation.RequiresApi;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.view.ViewCompat;
    import android.view.View;
    import android.view.ViewTreeObserver;
    
    /**
     * 软键盘帮助类
     * Created by HT on 2018/2/12.
     */
    @TargetApi(14)
    public class InputMethodHelper {
    
        private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener;
        private OnInputMethodListener onInputMethodListener;
        private Rect windowContentRect;
        private Rect keyboardRect;
        private InputMethodHelper(OnInputMethodListener listener) {
            this.onInputMethodListener = listener;
        }
    
    
        private void onAttach(Activity activity) {
            View decorView = activity.getWindow().getDecorView();
            windowContentRect = getDisplayVisibleFrameHeight(decorView);
            onGlobalLayoutListener = () -> {
    
                Rect displayVisibleFrame = getDisplayVisibleFrameHeight(decorView);
                if (keyboardRect == null) {
                    keyboardRect = new Rect(displayVisibleFrame);
                }
                keyboardRect.top = displayVisibleFrame.bottom;
                keyboardRect.bottom = windowContentRect.bottom;
                if (onInputMethodListener != null) {
                    onInputMethodListener.onInputMethodStatusChanged(keyboardRect, keyboardRect.height() != 0);
                }
            };
            decorView
                    .getViewTreeObserver()
                    .addOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    
        @RequiresApi(16)
        private void onDetach(Activity activity) {
            if (onInputMethodListener != null) {
                activity.getWindow()
                        .getDecorView()
                        .getViewTreeObserver()
                        .removeOnGlobalLayoutListener(onGlobalLayoutListener);
            }
        }
    
        public static void assistActivity(Activity host, OnInputMethodListener onInputMethodListener) {
            if (host == null) {
                return;
            }
            InputMethodHelper methodHelper = new InputMethodHelper(onInputMethodListener);
            host.getApplication().registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
    
                @Override
                public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    
                }
    
                @Override
                public void onActivityStarted(Activity activity) {
                    if (host == activity && methodHelper.onGlobalLayoutListener == null) {
                        methodHelper.onAttach(activity);
                    }
                }
    
                @Override
                public void onActivityResumed(Activity activity) {
                    if (host == activity && methodHelper.onGlobalLayoutListener == null) {
                        throw new IllegalStateException("assistActivity() must be called before onStart() called!");
                    }
                }
    
                @Override
                public void onActivityPaused(Activity activity) {
    
                }
    
                @Override
                public void onActivityStopped(Activity activity) {
    
                }
    
                @Override
                public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    
                }
    
                @Override
                public void onActivityDestroyed(Activity activity) {
                    if (activity == host) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                            methodHelper.onDetach(activity);
                        }
                        activity.getApplication().unregisterActivityLifecycleCallbacks(this);
                    }
                }
            });
    
        }
    
        public static void assistFragment(Fragment fragment, OnInputMethodListener onInputMethodListener) {
            if (fragment == null) {
                return;
            }
            InputMethodHelper methodHelper = new InputMethodHelper(onInputMethodListener);
            fragment.getFragmentManager().registerFragmentLifecycleCallbacks(new FragmentManager.FragmentLifecycleCallbacks() {
    
                @Override
                public void onFragmentViewCreated(FragmentManager fm, Fragment f, View v, Bundle savedInstanceState) {
                    if (f == fragment) {
                        methodHelper.onAttach(f.getActivity());
                    }
                }
    
                @Override
                public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {
                    if (f == fragment) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                            methodHelper.onDetach(f.getActivity());
                        }
                        f.getFragmentManager().unregisterFragmentLifecycleCallbacks(this);
                    }
                }
            }, false);
        }
    
    
        public static Rect getDisplayVisibleFrameHeight(View view) {
            Rect r = new Rect();
            view.getWindowVisibleDisplayFrame(r);
            return r;
        }
        
        public static void toggleInputMethod(View token, boolean show) {
            if (token == null)
                return;
            InputMethodManager manager = (InputMethodManager) token.getContext().getSystemService(Context
                            .INPUT_METHOD_SERVICE);
            token.setFocusableInTouchMode(show);
            token.setFocusable(show);
            if (token instanceof EditText) {
                ((EditText) token).setCursorVisible(show);
            }
            if (show) {
                if (!token.isFocused()) {
                    token.requestFocus();
                    if (token instanceof EditText) {
                        int length = ((EditText) token).getText().length();
                        ((EditText) token).setSelection(length);
                    }
                }
                if (manager != null) {
                    manager.showSoftInput(token, SHOW_FORCED);
                }
            } else {
                token.clearFocus();
                if (manager != null) {
                    manager.hideSoftInputFromWindow(token.getWindowToken(), 0);
                }
            }
        }
    
        public interface OnInputMethodListener {
    
            /**
             * 软键盘弹出/收起监听
             * @param keyboardRect 键盘弹出区域,宽,高
             *                     left = keyboardRect.left
             *                     top = keyboardRect.top
             *                     right = keyboardRect.right
             *                     bottom = keyboardRect.bottom
             *                     width = keyboardRect.width()
             *                     height = keyboardRect.height() 
             * @param show true 显示,false 隐藏
             */
            void onInputMethodStatusChanged(Rect keyboardRect, boolean show);
        }
    }
    
    
    

    处理随内容滚动的输入框遮挡问题(如包含在ScrollView或RecyclerView中的EditText)

    InputMethodHelper.assistActivity(this, (keyboardRect, show) -> {
                //1,获取当前焦点View
                View currentFocus = getCurrentFocus();
    
                //2,当键盘弹出,焦点View不为空(更严格的条件:焦点View就是需要处理的EditText),计算需要处理的被遮挡
                //的高度,相对滚动该高度
                if (show && currentFocus != null) {
                    int[] out = new int[2];
                    currentFocus.getLocationInWindow(out);
    
                    int offset = out[1] + currentFocus.getHeight() - keyboardRect.top;
                    if (offset > 0) {
                        //输入框被遮挡
                        scrollView.scrollBy(0, offset);
                    }
                }
                //3,计算键盘高度,处理内容区域可滚动距离少于遮挡高度的情况,保证滚动能够达到预期的效果
                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) parent.getLayoutParams();
                if (layoutParams.bottomMargin != keyboardRect.height()) {
                    layoutParams.bottomMargin = keyboardRect.height();
                    parent.requestLayout();
                }
    
            });
    

    处理部分ViewGroup中含吸底输入框的View组件遮挡问题

    InputMethodHelper.assistActivity(this, (keyboardRect, show) -> {
                if (bottomView == null || (show && !Objects.equals(getCurrentFocus(), editView))) {
                    return;
                }
                LayoutParams layoutParams = (LayoutParams) bottomView.getLayoutParams();
                int keyboardHeight = keyboardRect.height();
                if (layoutParams.height != keyboardHeight) {
                    layoutParams.height = keyboardHeight + bottomView.getMinimumHeight();
                    bottomView.requestLayout();
                }
            });
    

    或者

     InputMethodHelper.assistFragment(this, (keyboardRect, show) -> {
                if (bottomView == null || (show && !Objects.equals(getCurrentFocus(), editView))) {
                    return;
                }
                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)
                        bottomView.getLayoutParams();
                int keyboardHeight = keyboardRect.height();
                if (layoutParams.bottomMargin != keyboardHeight) {
                    layoutParams.bottomMargin = keyboardHeight;
                    bottomView.requestLayout();
                }
            });
    

    相关文章

      网友评论

          本文标题:软键盘弹出高度监听及键盘遮挡处理

          本文链接:https://www.haomeiwen.com/subject/nbdkoftx.html