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

Posted

技术标签:

【中文标题】如何确定移动浏览器中的软键盘是不是触发了调整大小事件?【英文标题】: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中的软键盘

移动 chrome 在滚动时触发调整大小事件

浏览器调整大小时的CSS转换“触发器”

H5防止安卓手机软键盘弹出挤压页面导致变形的方法