从纵向旋转到横向时,iPad 布局会放大

Posted

技术标签:

【中文标题】从纵向旋转到横向时,iPad 布局会放大【英文标题】:iPad layout scales up when rotating from portrait to landscape 【发布时间】:2011-07-23 00:32:33 【问题描述】:

我在"viewport" 元标记"width=device-width,initial-scale=1.0" 中添加了一个,在 iPad 上,页面在横向模式下加载良好,它很好地切换到纵向,当我将其旋转回横向时,它会放大页面并我必须将其缩放回 1 级。

我可以通过添加 "maximum-scale=1.0, user-scalable=no" 来解决此问题,但我想知道是否有一种方法可以在不剥夺用户放大页面的能力的情况下解决此问题。

如果您有任何建议,我很想听听, 谢谢!

【问题讨论】:

140% 有效还是 100% 有效? 【参考方案1】:

当您说它放大页面时,是所有元素,还是只是文本字体大小?...对于固定字体大小,您可以使用:

html 
    -webkit-text-size-adjust: 100%;

【讨论】:

它放大所有元素,基本上只是放大页面。 我将其修改为使用 100% 而不是无,这会阻止文本大小在方向更改时发生变化,但仍允许用户缩放。您还遇到了哪些其他类型的元素?我假设有一些元素,比如横幅,您希望宽度具有一定的流动性,但使用 CSS 控制高度。 我曾尝试使用 100% 进行 webkit-text-size-adjust,但它不会阻止网页在 iPad 旋转时不正确缩放。 我也有同样的问题(虽然这不是文本大小调整,但设置也很重要),流畅的网站似乎在 iPad 上出现这个问题,从纵向到横向启用缩放,同样的问题在这里:How do I reset the scale/zoom of a web app on an orientation change on the iPhone? 但还没有适合我的解决方案。【参考方案2】:

------更新------

这在 ios7 中不再是问题。 Scott Jehl 在 github scottjehl/iOS-Orientationchange-Fix 上有更好的解决方案,适用于 iOS6。

------原始答案------

Jeremy Keith (@adactio) 在他的博客 Orientation and scale 上有一个很好的解决方案

保持标记可扩展

<meta name="viewport" content="width=device-width, initial-scale=1">

然后使用 javascript 禁用可伸缩性,直到 gesturestart 使用此脚本:

if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) 
    var viewportmeta = document.querySelector('meta[name="viewport"]');
    if (viewportmeta) 
        viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0';
        document.body.addEventListener('gesturestart', function () 
            viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
        , false);
    

【讨论】:

谢谢。不过,这似乎不是一个真正的解决方案——iPad 的行为很糟糕,我会说这是他们的糟糕设计。 此错误已在 iOS6 中修复。查看 Jeremy Keith 关于此问题的最新帖子:iOS Six Fix。下面提到的fix by Scott Jehl 改编了 iOS 错误修复。 @Ludder iOS 6 修复应该是一个单独的答案,cmets 太容易错过了。 我在 iOS6 上使用相同的视口标签。但我仍然面临同样的问题。 我在 iOS 6 下也遇到了同样的问题。【参考方案3】:

这似乎是 iOS 4 中的一个错误,可以使用以下 Javascript sn-p 进行修复,但它会禁用用户进行捏合缩放的能力:

https://gist.github.com/901295/229d163414e22ebb14a6a6ba0b9777118f02e52d

【讨论】:

【参考方案4】:

希望这会有所帮助...

<head>

<style type="text/css">
<!--

/*
    I began with the goal to prevent font scaling in Landscape orientation.
    To do this, see: http://***.com/questions/2710764/

    Later, I just wanted to magnify font-size for the iPad, leaving
    the iPhone rendering to the css code.  So ...

    (max-device-width:480px) = iphone.css
    (min-device-width:481px) and
        (max-device-width:1024px) and
            (orientation:portrait) = ipad-portrait.css
    (min-device-width:481px) and
        (max-device-width:1024px) and
            (orientation:landscape) = ipad-landscape.css
    (min-device-width:1025px) = ipad-landscape.css

*/

@media only screen and (min-device-width: 481px)

    html 
        -webkit-text-size-adjust: 140%;   /* none for no scaling */
    


-->
</style>

</head>

【讨论】:

Hmm... 这么多提议的 javascript 解决方案要找到,但它仍然会跳来跳去(当你有绝对定位的元素等时)或禁用缩放或类似的东西。然后我找到了这个简单的解决方案——在 CSS 中!这使得平滑的非缩放旋转。这简直是​​完美的,应该是这个问题所有问题的正确答案!非常感谢@John Love。这绝对是惊人的 关于您删除约翰的问题,当您对其他人投反对票时,它也会记录对您不利的情况。 在想了一会儿之后,我确实记得很久以前读过我认为是某人粗鲁的评论......所以我打电话给他。我真的很感谢您对这个问题的一些解释。 尝试值 none 和 100%:这在第一次旋转时有效,但在随后的旋转中我得到奇怪的结果(在 iOS6 模拟器上) 非常好 - 解决了我在媒体查询中指定的 font-size 更改在 iPhone 5S 的横向模式下无法正确呈现的问题。【参考方案5】:

Scott Jehl 提出了一个出色的解决方案,该解决方案使用加速度计来预测方向变化。此解决方案反应灵敏,不会干扰缩放手势。

https://github.com/scottjehl/iOS-Orientationchange-Fix

工作原理:此修复程序通过监听设备的 加速度计来预测何时将发生方向变化。 当它认为即将改变方向时,脚本会禁用用户 缩放,允许正确发生方向变化,与 缩放禁用。设备恢复后,脚本会再次恢复缩放 要么接近直立,要么在它的方向已经 改变了。这样,当页面在时,用户缩放永远不会被禁用 使用。

缩小来源:

/*! A fix for the iOS orientationchange zoom bug. Script by @scottjehl, rebound by @wilto.MIT License.*/(function(m)if(!(/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1))returnvar l=m.document;if(!l.querySelector)returnvar n=l.querySelector("meta[name=viewport]"),a=n&&n.getAttribute("content"),k=a+",maximum-scale=1",d=a+",maximum-scale=10",g=true,j,i,h,c;if(!n)returnfunction f()n.setAttribute("content",d);g=truefunction b()n.setAttribute("content",k);g=falsefunction e(o)c=o.accelerationIncludingGravity;j=Math.abs(c.x);i=Math.abs(c.y);h=Math.abs(c.z);if(!m.orientation&&(j>7||((h>6&&i<8||h<8&&i>6)&&j>5)))if(g)b()elseif(!g)f()m.addEventListener("orientationchange",f,false);m.addEventListener("devicemotion",e,false))(this);

【讨论】:

这里的想法很好,但是因为这个解决方案使用加速度计来预测方向变化,如果 iPad 以一定角度握持,它有时无法检测到变化,即它需要几乎完美地握持直立以使其正常工作。 如果检测到这种情况,这将是一个更好的解决方案:1) 用户处于纵向,设备相对平坦 2) 旋转设备而不倾斜 3) 向上倾斜设备以提示设备更改方向 措辞那样的话,听起来并不常见,但是当我一直在阅读时,这种情况就会发生在我身上。 仅供参考:(/iPhone|iPad|iPod/.test(navigator.platform) 在 iOS/iPadOS 13(移动 Safari 13)上的桌面模式下被破坏,因为它现在在 iOS/iPadOS 上设置为 MacIntel(在 Beta 2 上测试)。【参考方案6】:

我想出了一个不同的解决方案来保持旋转缩放为 1,但允许用户捏合缩放。基本上,当用户缩放时,javascript 会更改视口缩放级别(并且本机浏览器缩放功能被禁用)。

在这里查看:https://***.com/a/11878932/436776

【讨论】:

【参考方案7】:

这个有效!

 <script >
// BUG orientation portrait/lanscape IOS //
if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) 
var viewportmeta = document.querySelector('meta[name="viewport"]');
if (viewportmeta) 
    viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0';
    document.addEventListener('orientationchange', function () 
        viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1';
    , false);
  

</script>

【讨论】:

【参考方案8】:

到元:

%metacontent: "width=device-width, initial-scale=1.0, minimum-scale=0.25, maximum-scale=1.6, user-scalable=yes", name: "viewport"

到全局脚本:

if navigator.platform.toLowerCase() is "ipad"
  viewport = $ "meta[name='viewport']"
  viewport_content = viewport.attr("content")

  # reset initial zoom
  viewport.attr "content", "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=yes"
  setTimeout =>
    viewport.attr "content", viewport_content
  , 0

  # reset zoom on rotate
  timeout = null
  window.onorientationchange = ->
    clearTimeout timeout if timeout?
    viewport.attr "content", "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=yes"
    timeout = setTimeout =>
      viewport.attr "content", viewport_content
    , 1000

【讨论】:

【参考方案9】:

jQuery mobile 使用的修复在这里

https://github.com/scottjehl/iOS-Orientationchange-Fix

缩小

/*! A fix for the iOS orientationchange zoom bug. Script by @scottjehl, rebound by @wilto.MIT / GPLv2 License.*/(function (a)  function m()  d.setAttribute("content", g), h = !0  function n()  d.setAttribute("content", f), h = !1  function o(b)  l = b.accelerationIncludingGravity, i = Math.abs(l.x), j = Math.abs(l.y), k = Math.abs(l.z), (!a.orientation || a.orientation === 180) && (i > 7 || (k > 6 && j < 8 || k < 8 && j > 6) && i > 5) ? h && n() : h || m()  var b = navigator.userAgent; if (!(/iPhone|iPad|iPod/.test(navigator.platform) && /OS [1-5]_[0-9_]* like Mac OS X/i.test(b) && b.indexOf("AppleWebKit") > -1)) return; var c = a.document; if (!c.querySelector) return; var d = c.querySelector("meta[name=viewport]"), e = d && d.getAttribute("content"), f = e + ",maximum-scale=1", g = e + ",maximum-scale=10", h = !0, i, j, k, l; if (!d) return; a.addEventListener("orientationchange", m, !1), a.addEventListener("devicemotion", o, !1) )(this);

完整来源

/*! A fix for the iOS orientationchange zoom bug.
 Script by @scottjehl, rebound by @wilto.
 MIT / GPLv2 License.
*/
(function(w)

    // This fix addresses an iOS bug, so return early if the UA claims it's something else.
    var ua = navigator.userAgent;
    if( !( /iPhone|iPad|iPod/.test( navigator.platform ) && /OS [1-5]_[0-9_]* like Mac OS X/i.test(ua) && ua.indexOf( "AppleWebKit" ) > -1 ) )
        return;
    

    var doc = w.document;

    if( !doc.querySelector ) return; 

    var meta = doc.querySelector( "meta[name=viewport]" ),
        initialContent = meta && meta.getAttribute( "content" ),
        disabledZoom = initialContent + ",maximum-scale=1",
        enabledZoom = initialContent + ",maximum-scale=10",
        enabled = true,
        x, y, z, aig;

    if( !meta ) return; 

    function restoreZoom()
        meta.setAttribute( "content", enabledZoom );
        enabled = true;
    

    function disableZoom()
        meta.setAttribute( "content", disabledZoom );
        enabled = false;
    

    function checkTilt( e )
        aig = e.accelerationIncludingGravity;
        x = Math.abs( aig.x );
        y = Math.abs( aig.y );
        z = Math.abs( aig.z );

        // If portrait orientation and in one of the danger zones
        if( (!w.orientation || w.orientation === 180) && ( x > 7 || ( ( z > 6 && y < 8 || z < 8 && y > 6 ) && x > 5 ) ) )
            if( enabled )
                disableZoom();
                       
        
        else if( !enabled )
            restoreZoom();
        
    

    w.addEventListener( "orientationchange", restoreZoom, false );
    w.addEventListener( "devicemotion", checkTilt, false );

)( this );

【讨论】:

【参考方案10】:

第一个修复对我有用,并进行了以下更改。

将初始比例更改为 0.8,最小更改为 0.25,最大更改为 1.6。

使用“元”标签

<meta name="viewport" content="width=device-width, initial-scale=1">


<script ="text/javascript">
if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) 
    var viewportmeta = document.querySelector('meta[name="viewport"]');
    if (viewportmeta) 
        viewportmeta.content = 'width=device-width, minimum-scale=.25, maximum-scale=1.6, initial-scale=.8';
        document.body.addEventListener('gesturestart', function () 
            viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
        , false);
    

【讨论】:

【参考方案11】:

为了使脚本正常工作并绕过第二次手势微调,例如在方向更改事件中,请将最大值设置为 1.00099 而不是 1.0

【讨论】:

以上是关于从纵向旋转到横向时,iPad 布局会放大的主要内容,如果未能解决你的问题,请参考以下文章

元素无法从纵向切换到横向 ipad

响应式网站显示为 iPad 放大

将 ipad 从纵向旋转到横向时,Div 保持相同的宽度

从纵向模式旋转到横向模式时,搜索栏会丢失 FirstResponder

当我在 iOS7 的 iPad 中将视图从纵向旋转到横向或反之亦然时,UITextfield shouldChangeCharactersInRange 没有调用

在两个视图之间切换以及从纵向切换到横向时出现 iPad 方向问题,反之亦然