我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

使用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实现一个悬浮在软键盘上的输入栏的文章就介绍到这了,更多相关Android实现悬浮输入栏内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

这篇文章主要介绍“如何使用Android实现一个悬浮在软键盘上的输入栏”,在日常操作中,相信很多人在如何使用Android实现一个悬浮在软键盘上的输入栏问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用A
2023-06-29

在Android开发中使用WindowManager实现一个悬浮按钮

这篇文章将为大家详细讲解有关在Android开发中使用WindowManager实现一个悬浮按钮,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。效果:整体思路360手机卫士的内存球其实就是一个
2023-05-31

Android如何使用Scroller实现一个可向上滑动的底部导航栏

这篇文章主要介绍了Android如何使用Scroller实现一个可向上滑动的底部导航栏,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。看下效果:首先这个控件是滑动的肯定就会用到
2023-05-31

怎么在Android应用中实现一个动态匹配输入的内容功能

怎么在Android应用中实现一个动态匹配输入的内容功能?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、AutoCompleteTextView独特属性:android:
2023-05-31

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录