温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何使用Android实现一个悬浮在软键盘上的输入栏

发布时间:2022-04-11 14:27:06 来源:亿速云 阅读:909 作者:iii 栏目:开发技术

这篇文章主要介绍“如何使用Android实现一个悬浮在软键盘上的输入栏”,在日常操作中,相信很多人在如何使用Android实现一个悬浮在软键盘上的输入栏问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用Android实现一个悬浮在软键盘上的输入栏”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

    悬浮栏

    实现悬浮栏很简单

    chatInputPanel.setVisibility(View.VISIBLE);
    chatInputEt.setFocusable(true);
    chatInputEt.setFocusableInTouchMode(true);
    chatInputEt.requestFocus();
    InputMethodManager inputManager = (InputMethodManager)chatInputEt.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
    inputManager.showSoftInput(chatInputEt, 0);

    chatInputPanel就是悬浮栏整个layout,mChatPanelContent才是悬浮栏实际部分,chatInputEt是其中的EditText,对它做一些设置就可以实现将chatInputPanel悬浮在软件盘上。

    这里chatInputPanel是全屏的(点击mChatPanelContent以外部分隐藏键盘),mChatPanelContent是在它的bottom底部,默认隐藏(INVISIBLE)。

    横屏时软键盘全屏

    横屏时,安卓默认会将软键盘全屏显示,这样无法实现悬浮栏。所以需要取消全屏显示

    在EditText中使用android:imeOptinos可对Android自带的软键盘进行一些界面上的设置

    • android:imeOptions="flagNoExtractUi" //使软键盘不全屏显示,只占用一部分屏幕

    • android:imeOptions="actionNone" //输入框右侧不带任何提示

    • android:imeOptions="actionGo" //右下角按键内容为'开始'

    • android:imeOptions="actionSearch" //右下角按键为放大镜图片,搜索

    • android:imeOptions="actionSend" //右下角按键内容为'发送'

    • android:imeOptions="actionNext" //右下角按键内容为'下一步'

    • android:imeOptions="actionDone" //右下角按键内容为'完成'

    所以我们为EditText设置android:imeOptions="flagNoExtractUi"即可实现在横屏时不全屏显示。同时,可能EditText添加相应的监听器,捕捉用户点击了软键盘右下角按钮的监听事件,以便进行处理。

    editText.setOnEditorActionListener(new OnEditorActionListener() {   
            @Override  
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {   
                Toast.makeText(MainActivity.this, "text2", Toast.LENGTH_SHORT).show();   
                return false;   
            }   
        });

    监听软键盘(该方法不可靠,废弃,下面有靠谱的)

    注意:这是网上的一个错误方法,所以特意拿出来说一下,不感兴趣直接去看(3)即可。

    显示没问题了,但是软键盘隐藏的时候要求悬浮栏同步隐藏起来。

    系统并没有提供监听软键盘收起的api,所以我们只能自己实现。

    chatInputPanel.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if(chatInputPanel.getBottom() > container.getRootView().getHeight() / 2){
                chatInputPanel.setVisibility(View.INVISIBLE);
            }
            else{
                chatInputPanel.setVisibility(View.VISIBLE);
            }
        }
    });

    监听chatInputPanel(悬浮栏整体布局)的布局变化,当底部大于rootview高度一半的时候隐藏,否则显示。

    因为我们的功能是横屏的,所以键盘弹起时,chatInputPanel因为悬浮在键盘上,所以底部一定小于rootview高度(屏幕宽度)一半。

    当收起键盘,chatInputPanel会回到最底部(设置是在父布局底部),所以底部一定大于一半。

    这个方法不靠谱,而且重绘会导致onGlobalLayout频繁的执行,虽然可以加上一个时间来控制,但是不推荐使用这个方式来监听软键盘,下面看看另外一种方式。

    靠谱的监听软键盘的方法

    上面的方法为什么不考虑,是因为全屏显示FLAG_FULLSCREEN(隐藏通知栏)导致问题

    当我们需要全屏显示隐藏通知栏时,会使用FLAG_FULLSCREEN属性

    getActivity().getWindow().setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    但是会影响上面的悬浮栏,因为发现chatInputPanel.getBottom()始终没变化,但是我们判断显示隐藏就靠这个变化。

    没变化是因为android在全屏FLAG_FULLSCREEN的处理方式导致的,全屏时软键盘会出现很多问题,这个网上有很多。

    如何解决?

    我们换一种方式监听软键盘即可

    getActivity().getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect rect = new Rect();
            rootView.getWindowVisibleDisplayFrame(rect);
            int rootHeight=rootView.getRootView().getHeight();
    
            int displayHeight=rect.height();
            int diffHeight=rootHeight-displayHeight;
            if(diffHeight==0){
                //键盘收起
                chatInputPanel.setVisibility(View.INVISIBLE);
            }else{
                //键盘弹出
                chatInputPanel.setVisibility(View.VISIBLE);
            }
        }
    });

    通过监听根布局种的content布局的变化来判断,目前这个方法是最靠谱的。

    但是还存在一个小问题,就是全屏状态下键盘会覆盖悬浮栏底部的一小部分,这个怎么办?

    终极悬浮方式

    上面解决了软键盘的监听问题,但是全屏状态下悬浮栏总会被遮住一部分,那怎么办?

    其实这里还有一个问题,当显示键盘后,app中的布局整体被向上推起,这样导致部分组件缩小等情况。

    我们要首先解决这个问题,让app的布局整体保持不动,键盘覆盖在其上面,这需要在弹起键盘前手动设置一下,如下:

    mChatInput.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            DisplayMetrics metric = new DisplayMetrics();
            getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric);
            chatInputPanel.setY(-metric.heightPixels);//解决首次可能向上推的问题
            
            chatInputEt.setFocusable(true);
            chatInputEt.setFocusableInTouchMode(true);
            chatInputEt.requestFocus();
            InputMethodManager inputManager = (InputMethodManager)chatInputEt.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            inputManager.showSoftInput(chatInputEt, 0);
        }
    });

    这样将悬浮栏移到了最顶部以上,就不会出现上推的情况了(猜测与键盘的机制有关,因为键盘弹出如果遮挡了有焦点的输入组件就好重新调整窗口,我们将悬浮窗放在最上面,键盘怎么也不会遮挡到焦点的EditText,所以不会重新调整窗口)。

    但是这样悬浮栏就一直看不见了,而且我们可以看到在这里去掉了chatInputPanel.setVisibility(View.VISIBLE);代码,那么如何显示?

    上面我们提到使用OnGlobalLayoutListener方式监听键盘,我们就在这里显示即可,同时优化一下显示的位置,在这里计算窗口显示区域上移多少,让chatInputPanel也上移相应位置即可,如:

    private int mLastHeight = 0;
    getActivity().getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect rect = new Rect();
            getActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
            int height = rect.height();
            int rawHeight = getResources().getDisplayMetrics().heightPixels - rect.top;
            if (height == mLastHeight)
                return;
                
            if (height < rawHeight) {
                UiThreadHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        chatInputPanel.setVisibility(View.VISIBLE);
                        chatInputPanel.setTranslationY(-(rawHeight - height));
                    }
                }, 200);
            } else {
                UiThreadHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        chatInputPanel.setVisibility(View.GONE);
                    }
                }, 100);
            }
                    
            mLastHeight = height;    
        }
    });

    可以看到先得到当前窗口的显示高度和屏幕的实际高度(窗口部分)

    然后先判断窗口显示区域是否变化了,如果没变化则不处理。

    如果有变化,则判断变大还是变小了。

    如果变小了

    说明键盘弹起,这时候显示chatInputPanel,同时设置translationY为-(rawHeight - height)

    首先chatInputPanel初始位置底部是与屏幕底部对齐的,虽然设置了setY,但是setY实际上就是setTranslationY,初始位置没变,源码:

    public void setY(float y) {
        setTranslationY(y - mTop);
    }

    而弹起键盘后想要显示在键盘以上,那么就需要从最底部向上移动一个键盘的高度,键盘高度就是rawHeight - height,所以向上移动是将translationY设置为-(rawHeight - height)。

    如果变大了

    说明键盘收起,隐藏chatInputPanel即可。

    这样不仅解决了窗口推起的问题,也同时解决了软键盘遮挡部分悬浮栏的问题,因为悬浮栏的位置是通过计算得到的,不是通过软键盘上推导致布局调整而改变位置的。

    到此,关于“如何使用Android实现一个悬浮在软键盘上的输入栏”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI