关于Android中的软键盘

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Android中的软键盘相关的知识,希望对你有一定的参考价值。

参考技术A

原文链接:彻底搞定android开发中软键盘的常见问题
软件盘的本质是什么?软键盘其实是一个Dialog。

InputMethodService为我们的输入法创建了一个Dialog,并且将该Dialog的Window的某些参数(如Gravity)进行了设置,使之能够在底部或者全屏显示。当我们点击输入框时,系统对活动主窗口进行调整,从而为输入法腾出相应的空间,然后将该Dialog显示在底部,或者全屏显示。
软键盘显示的调整
Android 定义了一个属性,名字为windowSoftInputMode, 这个属性用于设置Activity主窗口与软键盘的交互模式,用于避免软键盘遮挡内容的问题。我们可以在AndroidManifet.xml中对Activity进行设置。如:android:windowSoftInputMode=”stateUnchanged|adjustPan”。 该属性可选的值有两部分,一部分为软键盘的状态控制,控制软键盘是隐藏还是显示,另一部分是Activity窗口的调整,以便腾出空间展示软键盘。 android:windowSoftInputMode的属性设置必须是下面中的一个值,或一个”state”值加一个”adjust”值的组合,各个值之间用 | 分开。
stateUnspecified-未指定状态 :当我们没有设置android:windowSoftInputMode属性的时候,软件默认采用的就是这种交互方式,系统会根据界面采取相应的软键盘的显示模式。
stateUnchanged-不改变状态 :当前界面的软键盘状态,取决于上一个界面的软键盘状态,无论是隐藏还是显示。
stateHidden-隐藏状态 :当设置该状态时,软键盘总是被隐藏,不管是否有输入的需求。
stateAlwaysHidden-总是隐藏状态 :当设置该状态时,软键盘总是被隐藏,和stateHidden不同的是,当我们跳转到下个界面,如果下个页面的软键盘是显示的,而我们再次回来的时候,软键盘就会隐藏起来。
stateVisible-可见状态 :当设置为这个状态时,软键盘总是可见的,即使在界面上没有输入框的情况下也可以强制弹出来出来。
stateAlwaysVisible-总是显示状态 :当设置为这个状态时,软键盘总是可见的,和stateVisible不同的是,当我们跳转到下个界面,如果下个页面软键盘是隐藏的,而我们再次回来的时候,软键盘就会显示出来。
adjustUnspecified-未指定模式 :设置软键盘与软件的显示内容之间的显示关系。当你跟我们没有设置这个值的时候,这个选项也是默认的设置模式。在这中情况下,系统会根据界面选择不同的模式。
adjustResize-调整模式 :该模式下窗口总是调整屏幕的大小用以保证软键盘的显示空间;这个选项不能和adjustPan同时使用,如果这两个属性都没有被设置, 系统会根据窗口中的布局自动选择其中一个
adjustPan-默认模式 :该模式下通过不会调整来保证软键盘的空间,而是采取了另外一种策略,系统会通过布局的移动,来保证用户要进行输入的输入框肯定在用户的视野范围里面,从而让用户可以看到自己输入的内容。

案例
没有滚动布局xml

对于没有滚动控件的布局来说,adjustPan就是默认的设置,比如我们案例应用中的文本输入8,上面的文本输入框123和按钮都会被顶上去,且页面布局不可以滚动。

对于没有滚动控件的布局来说,整个布局会网上偏移(包括标题等)以保证输入框的可见。如果有滚动控件,那么就是内容网上偏移,标题不会动,还可以通关滚动来查看被顶上去的内容,而这点是不可滚动的布局所不具备的

有滚动布局xml

对于有滚动控件的布局,则是采用的adjustResize方式,比如我们案例应用中的文本输入8,上面的文本输入框123和按钮都会被顶上去, 可以通过滚动来查看被顶上去的内容。

** 根据这一原理,我们就可以把开发中遇到的软键盘遮挡页面的问题,利用ScrollView当做根布局,让系统采用adjustResize模式,很好地解决这一问题。**

自动弹出软键盘
有时候需要一进入Activity后就自动弹出软键盘,可以通过设置一个时间函数来实现,具体写法如下:
方法一:

方法二:

有时进入Activity后不希望系统自动弹出软键盘,我们可以按照下面的方法来实现:
方法一:
在AndroidMainfest.xml中选择那个activity,设置windowSoftInputMode属性为adjustUnspecified|stateHidden

方法二:
让EditText失去焦点,使用EditText的clearFocus方法

方法三:
强制隐藏Android输入法窗口

方法四:
EditText始终不弹出软件键盘

EditText设置ScrollView压缩背景图片解决办法
在你的Activity里加上

有时希望根据条件动态关闭软键盘,我们可以使用InputMethodManager类,按照下面的方法来实现:
方法一:

方法二:
强制隐藏软键盘,这个方法倒是很实用。

方法三:

方法四:

在onclick事件下.以下方法可行.(如果是EditText失去焦点/得到焦点,没有效果)

InputMethodManager的具体用法可以参考下面的链接: http://www.apihome.cn/api/android/InputMethodManager.html

使用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添加相应的监听器,捕捉用户点击了软键盘右下角按钮的监听事件,以便进行处理。

开发中有个需求是将页面底部的一个按钮顶起,但是开发时发现Android5.0以后的版本设置了adjustResize属性后无法成功顶起。纠结了好久,最后在stackoverflow找到解决方案,那就是在根布局上加上fitsSystemWindow=”true”即可。

这里的fitsSystemWindow具体的作用就是你的**contentview是否忽略actionbar,title,屏幕的底部虚拟按键,将整个屏幕当作可用的空间。 **
正常情况,contentview可用的空间是去除了actionbar,title,底部按键的空间后剩余的可用区域;这个属性设置为true,则忽略,false则不忽略

在edittext上加入Android:imeOptions=”actionSearch”这个属性没响应,最后发现在2.3及以上版本不起作用,解决方案:加上

因为输入法键盘右下角默认的回车键本来就是换行用的,当设置单行后,回车换行就失去作用了,这样就可以设置为搜索、发送、go等等。

如何确定移动浏览器中的软键盘是不是触发了调整大小事件?

【中文标题】如何确定移动浏览器中的软键盘是不是触发了调整大小事件?【英文标题】:How to determine if a resize event was triggered by soft keyboard in mobile browser?如何确定移动浏览器中的软键盘是否触发了调整大小事件? 【发布时间】:2013-02-15 19:53:52 【问题描述】:

关于软键盘的讨论很多,但我还没有找到解决问题的好方法。

我有一个调整大小的功能,例如:

$(window).resize(function() 
    ///do stuff
);

我想对所有调整大小事件执行该函数中的“东西”,除非它由软键盘触发。如何判断软键盘是否触发了resize?

【问题讨论】:

所有手机软键盘都会触发resize事件吗?在我看来,它们的行为类似于“叠加层”并且不会调整浏览器窗口的大小.. 如果您不调整内容大小,它们就像叠加层。但它们会触发 window.resize 事件。 有没有办法检查软键盘是否正在显示? 如果没有,resize 事件是否会触发移动环境中的其他任何内容?当用户使用捏合手势放大/缩小时怎么样?如果不是...那么您根本不需要检查。 【参考方案1】:

我最近遇到了一些需要检查的问题。我设法像这样解决它:

$(window).on('resize', function()
   // If the current active element is a text input, we can assume the soft keyboard is visible.
   if($(document.activeElement).attr('type') === 'text') 
      // Logic for while keyboard is shown
    else 
      // Logic for while keyboard is hidden
   

我只需要它用于文本输入,但显然这可以扩展为任何可能触发软键盘/数字选择器等的元素。

【讨论】:

只有在您的 html 代码中明确将属性设置为“text”时,这才有效。最好使用 prop() 而不是 attr()。 另外,如果我在 android 中通过底部后退按钮关闭键盘,它仍将 activeElement 作为 type=text(或最后聚焦的输入),并且由于隐藏键盘仍触发调整大小事件。这个解决方案很好,但不完整和充分证明。【参考方案2】:

我刚刚修复了 kirisu_kun 使用 prop() 而不是 attr() 的答案:

$(window).on('resize', function()
   // If the current active element is a text input, we can assume the soft keyboard is visible.
   if($(document.activeElement).prop('type') === 'text') 
      // Logic for while keyboard is shown
    else 
      // Logic for while keyboard is hidden
   

【讨论】:

【参考方案3】:

问题是,如果活动元素有焦点,你可以通过关闭键盘而不改变焦点来触发resize事件。所以,键盘会隐藏,但代码会进入焦点条件。

【讨论】:

【参考方案4】:

这个问题依赖于一种可靠的方法来检测屏幕键盘何时在移动设备上出现(或消失)。不幸的是,没有可靠的方法来检测这一点。类似的问题已经多次出现在 SO 上,并提出了各种技巧、技巧和解决方法(请参阅 this answer 以获取几个相关答案线程的链接)。

另请注意,屏幕键盘出现时并不总是触发调整大小事件(请参阅this answer)。

我的一般建议是检测触摸屏的存在 + 检测活动元素是否属于触发屏幕键盘的类型(类似于this answer)。但是,对于混合 Windows 设备(例如 Surface Pro),这种方法仍然会失败,有时屏幕键盘可能会在浏览器调整大小时出现,有时硬件键盘可能会在浏览器调整大小时使用。

【讨论】:

不幸的是,我似乎得出了同样的结论。我继续尝试取消默认缩放事件,但那是just as fruitless。 @lpd,我试图解决这个问题,但似乎找不到任何解决方案可以涵盖所有用例,只要屏幕键盘的更改没有触发特定事件能见度。这意味着我们剩下的黑客和变通方法可能适用于某些(但不是全部)用例。【参考方案5】:

与之前的答案类似,但针对所有具有焦点的表单子项(显然,在没有表单父项的情况下输入会失败)

$(window).resize(function() 
    if($('form *').focus()) 
        alert('ignore this');
     else 
        // do the thing
    
);

所以也许这个...

$(window).resize(function() 
    if($('input, select, etc').focus()) 
        alert('ignore this');
     else 
        // do the thing
    
);

【讨论】:

【参考方案6】:

我一直在寻找类似问题的解决方案。我的调整大小事件在 url 输入进出视图时触发。这是我一直在做的事情……有可能的解决方案吗?

所以基本上你只检查屏幕的宽度是否改变了,如果它不同,只有在调整大小时触发你的函数:

例如:

var saveWindowWidth = true;
    var savedWindowWidth;

//set the initial window width
    if (saveWindowWidth = true)
        savedWindowWidth = windowWidth;
        saveWindowWidth = false;
    


//then on resize...


$(window).resize(function() 

//if the screen has resized then the window width variable will update
        windowWidth = window.innerWidth;


//if the saved window width is still equal to the current window width do nothing
        if (savedWindowWidth == windowWidth)
            return;
        


//if saved window width not equal to the current window width do something
        if(savedWindowWidth != windowWidth) 
           // do something

            savedWindowWidth = windowWidth;
        

    );

【讨论】:

【参考方案7】:

有几件事你需要集中精力

    所有软键盘只影响高度而不影响宽度。 焦点元素标签可以是 input 或 textarea。 当元素获得焦点时高度会降低(或)当焦点离开时高度会增加。

当浏览器调整大小时,您可以使用这些组合

function getWidth()
return $( window ).width();


function getHeight()
return $( window ).height();


function isFocus()
return $(document.activeElement).prop('tagName')=='INPUT' || $(document.activeElement).prop('tagName')=='TEXTAREA';


var focused = false;
var windowWidth=getWidth(),windowHeight=getHeight();

//then on resize...    
$(window).resize(function() 

var tWidth=getWidth(),tHeight=getHeight(),tfocused=isFocus();

//if the saved window width is still equal to the current window width do nothing
if (windowWidth == tWidth && ((tHeight < windowHeight && !focused && tfocused) || (tHeight > windowHeight && focused && !tfocused)))
 windowWidth=tWidth;
 windowHeight=tHeight;
 focused=tfocused;
 return;

else
 windowWidth=tWidth;
 windowHeight=tHeight;
 focused=tfocused;

 //Your Code Here


);

【讨论】:

打开键盘可能触发缩放变化,这至少会影响一些宽度测量。 哦...是的...如果是这样,我们可以更改条件。宽度和高度都会随着任何输入的焦点同时不同,对吧? 此外,至少在 Android chrome/firefox 中,可以在不模糊输入元素的情况下关闭屏幕键盘。 你能给我一些小提琴吗?最好准确地测试一下 谢谢!我只把这部分function isFocus() return $(document.activeElement).prop('tagName')=='INPUT' || $(document.activeElement).prop('tagName')=='TEXTAREA'; 和转换器变成了这个: $(window).resize(function() var focusTagName = $(document.activeElement).prop('tagName'); if (focusedTagName == 'INPUT' | |focusedTagName == 'TEXTAREA' ||focusedTagName == 'SELECT' ||focusedTagName == 'IFRAME' ) // 修复 android 键盘。什么都不做。 else );【参考方案8】:

在当前版本的 chrome webview 中工作正常。 我刚刚使用以下代码在 Angular 中实现了窗口调整大小功能。

@HostListener('window:resize', ['$event'])
  onResize(event) 
  // Do you handling here.

注意:同样可以使用

 window.addEventListener('resize', () => 
   // Do handling here
 );

【讨论】:

以上是关于关于Android中的软键盘的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式在android中的软输入键盘上禁用语音到文本按钮(麦克风)

如何通过android中的软键盘以编程方式将我的EditText输入限制为反斜杠(/),tild(〜)等特殊字符

Android 3:模拟虚拟钢琴键盘的软键盘行为

显示/隐藏 Phonegap Android 的软键盘插件

Android - 隐藏EditText弹出的软键盘输入(SoftInput)

如何在 Android TV 上显示带有数字和符号的软键盘?