【问题标题】:Force correct CSS3 transform percentage interpretation on Android在 Android 上强制正确的 CSS3 转换百分比解释
【发布时间】:2012-10-31 11:24:40
【问题描述】:

tl;博士?获取以下链接中演示的机制,以在 Android Chrome 和默认浏览器上使用 GPU 加速。

更新 2 (2014-01-13 13:25:30Z):根据下面bref.it 的评论,报告的行为自 Android 4.4 KitKat 起已修复 — 但修复我下面介绍一下吧!索德定律。

更新 1 (2012-11-01 17:54:09Z):错误的行为可以从转换矩阵中推断出来,由转换后元素的计算样式报告,它返回一个像素值.我将尝试为此编写一个 Modernizr 测试,为任何可能的解决方案铺平道路。

我开发了一种滑动容器的机制,以显示全宽、水平排列的子部分。基本上是滑动标签。因为有很多性能密集型的东西和复杂的 Javascript 正在进行,所以我希望将 JS 保持在最低限度,并在 CSS 中做尽可能多的纯粹风格。我认为我做得很好,考虑到 — JS 只是更改了包装器上的一个属性:

(带左侧)

http://jsfiddle.net/barney/VPJuq/ (移动设备可以将 /show/ 附加到这些小提琴 URL 以自行查看结果)

关于它如何工作的一句话:将标签视为inline-blocks 允许我指定white-space: nowrap(最后几条规则中的其余代码基本上折叠了标签之间的空白)并允许它们堆叠水平而不清除/返回,同时每个都保持其父级的完整宽度。从那里开始,为包装器设置一个负的左偏移量就可以了。很酷吧?

现在,有点背景:我正在开发的界面将在原生移动应用程序中运行——应用程序的核心功能依赖于尖端的移动特定技术(不要问——NDA)——通过 UIWebView,目前唯一支持该技术的平台是 Android。

这里我的问题是双重的:transform: translate 比left 或margin-left 转换工作/很多/更平滑(translate3d 甚至更多),到一个非常理想的点,临界点至关重要——尤其是在Android,在具有最新操作系统的最新手机上,看到非翻译转换仍然结结巴巴。考虑到这一点,问题的症结在于 Android 在与 translate 相关时似乎以不同的方式推断盒子模型。为了演示,这里有一个基于transform 的版本,它和之前的小提琴做同样的事情,并且适用于所有支持 translate3d 的浏览器……

(带翻译)

http://jsfiddle.net/barney/EJ7ve

如果您在 iPhone 上检查这一点(同样,通过附加 /show),您会发现 iPhone 上的帧速率有所提高。在 Android 上运行的 Firefox 也是如此,可以说在 Chrome 和 Android 上的默认浏览器上也是如此,除了这里,-100% 的translateX 偏移量不知何故是指所有三个选项卡占用的空间,所以包装器只是滑动足以使所有选项卡都不可见。这很奇怪,因为变换百分比被指定为与被变换元素的完整盒子模型相关——并且计算样式明确地将包装器宽度描述为与其父级相同(而不是,正如结果所暗示的那样,拉伸 3 倍到容纳标签)。

我们可以将此描述为一个错误吗?

据我所知,没有纯 CSS(我不反对媒体查询功能检测、CSS 供应商分叉或属性黑客)方法来推断和解决这个问题。事实上,我现在能想到的使相同的 CSS 机制起作用的唯一方法是嗅探 Android 的 UA 字符串并有条件地应用不同的规则。呸!如果我要制作一个仅限 Android-WebKit 的解决方案,并在其他任何地方破坏功能,我可以考虑事实上的行为并使百分比指的是分数:

(带翻译 - 对于 Android 更新:Android 4.4 KitKat 上的更新:不必要和中断)

http://jsfiddle.net/barney/nFt5t/

不理想,因为这使得 UI 浏览器特定,并且要求我们在编写 CSS 之前预先知道组中选项卡的数量。但这甚至不能完全解决那里的问题,因为在方向改变时(这真的很奇怪),偏移量会切换到其他浏览器显示的规范正确行为!

我还尝试将翻译应用到实际的选项卡,这在其他任何地方都可以使用,但是尽管正确地选择并应用了规则,Android 的浏览器不会呈现效果。陌生人和陌生人:

(带翻译,研究 Android 的理论,根本不研究 Android)

http://jsfiddle.net/barney/EJ7ve/9

非常感谢您对跨浏览器解决方案的任何见解或想法。

【问题讨论】:

  • 我从经验中知道,使用 css3 和 Android 是一件很痛苦的事情(使用完全错误的三星浏览器更是如此)。您可以尝试检测容器的宽度并通过 javascript offsetWidth 或 clientWidth 应用 css 转换。元视口也可能是问题的根源。
  • 这就是我最终要做的。很遗憾,因为演示代码是完全程序化的……
  • 对不起,我没有意识到这个问题太老了。时至今日,Android HTML5(css 和 js)的支持仍然令人遗憾,最让我惊讶的是,似乎几乎没有人关心。我不再为我的 Android 端口的丑陋而担心。
  • 当时我正在编写一个 Android 专有的 HTML5 应用程序,因此从头开始编写高度定制的高性能 UI 的任务在某种程度上因单一目标而变得轻松。但这是一个巨大的痛苦。第一个主要问题是不支持多个转换属性。还有无数其他人,但我离题了。
  • 您的所有示例都在最新 Chrome 上刚刚更新的 (4.4) Nexus 7 2013 上完美运行。除了“for android”版本,讽刺的是,标签似乎只滑动了 40 左右像素。

标签: javascript android jquery css uiwebview


【解决方案1】:

我使用的是 Android 2.3,无法产生您描述的确切问题(关于您的评论 “-100% 不知何故是指所有三个选项卡占用的空间”)。但是,我遇到了其他问题,导致间歇性/跳跃式转换和其他一些我没有真正调查过的奇怪现象。

为了便于讨论,我们假设“包装器”的宽度为 500 像素。

通过使用您的 inline-block/nowrap 技术(这是 YUI 中一种未被充分重视的布局技术),您的 3 个选项卡面板占用了 1500 像素的水平空间。根据您的描述,您需要欺骗浏览器,使其认为所有选项卡面板一起占用了 500 像素的水平空间。查看我的小提琴,它本质上使用了一些负边距并转换为以我认为应该有效的方式欺骗​​浏览器,但我无法对其进行测试。无论哪种方式,我的示例修复了我在我的 Android 2.3 上遇到的怪异现象 - 所以你可能想以任何一种方式使用它。

http://jsfiddle.net/ryanwheale/EJ7ve/29/

(以及相关的 CSS)

.tabs > * {
    width: 100%;
    margin-left: -100%;
}
.tabs > *:first-child {
    -webkit-transform: translate3d(0%, 0, 0);
    -moz-transform: translate3d(0%, 0, 0);
    -ms-transform: translate3d(0%, 0, 0);
    -o-transform: translate3d(0%, 0, 0);
    transform: translate3d(0%, 0, 0);
}
.tabs > *:first-child + * {
    -webkit-transform: translate3d(100%, 0, 0);
    -moz-transform: translate3d(100%, 0, 0);
    -ms-transform: translate3d(100%, 0, 0);
    -o-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
}
.tabs > *:first-child + * + * {
    -webkit-transform: translate3d(200%, 0, 0);
    -moz-transform: translate3d(200%, 0, 0);
    -ms-transform: translate3d(200%, 0, 0);
    -o-transform: translate3d(200%, 0, 0);
    transform: translate3d(200%, 0, 0);
}
.tabs > *:first-child + * + * + * {
    -webkit-transform: translate3d(300%, 0, 0);
    -moz-transform: translate3d(300%, 0, 0);
    -ms-transform: translate3d(300%, 0, 0);
    -o-transform: translate3d(300%, 0, 0);
    transform: translate3d(300%, 0, 0);
}

注意:我尝试使用相对定位而不是上面的变换,但我仍然得到与上面描述的相同的怪异。

【讨论】:

  • 在 android mobile ( 上的原生 webkit mobile 之外,在所有操作系统和浏览器中,以下 jsFiddle 都可以正常工作
  • 在这个操作系统修复问题上使用 chrome 浏览器,但就像说的那样,我们的目标是为原生系统修复它。这是复制问题的简单 jsFiddle:jsfiddle.net/xw85P 在我的银河选项卡 2 上,翻译不会在第二个 DIV 的开头而是在结尾处停止。
  • 我实际上在 Eclipse 中打开了一个 phonegap 应用程序......不知道为什么我不考虑在其中加载小提琴,以便我可以在 4.x 模拟器上进行测试。因此,我将上述技术应用于您的最后一个示例并且它有效(jsfiddle.net/ryanwheale/xw85P/1)。但是,我在上面的答案中发布的示例存在一些问题......现在测试。
  • 实际上,我上面的示例确实有效。它在 PhoneGap b/c 中不起作用我没有 code.jquery.com 的访问源。
  • 这很有趣,因为使用 translate3D() 而不是 left 属性来设置银河选项卡 2 中的滑动位置修复问题。我会在有更多时间时进行调查,希望明天早上在赏金到期之前... ;)
【解决方案2】:

我遇到了类似的问题。

对我来说,问题是:

* {
    box-sizing: border-box;
}

我将边框框应用于所有元素。一旦我删除它,百分比 translate3d 就被正确应用了。

【讨论】:

  • 不幸的是,这并不能解决问题,在 Android 4.1.2 上测试
  • 自从我上一篇文章以来,我发现我的问题也是由于使用 translate3d 值的百分比值引起的。将此设置为像素宽度也解决了 Android 4.3 中的问题
  • 谢谢,这对我有帮助)
【解决方案3】:

如果 CSS 不工作(并且应该工作),您需要一个解决方法。请检查我的修改版本:

http://jsfiddle.net/EG9v8/1/

function makeCss(index){
    // Calculate the offset, given the tabs size
    var size = -$('.tabs').width() * index;
    // Create style for the given offset.
    var css = '-webkit-transform: translate3d('+size+'px, 0, 0);';
    css += '-moz-transform: translate3d('+size+'px, 0, 0);';
    css += '-ms-transform: translate3d('+size+'px, 0, 0);';
    css += '-o-transform: translate3d('+size+'px, 0, 0);';
    css += 'transform: translate3d('+size+'px, 0, 0);';
    return css;
}

$('.tabLinks a').on('click', function(e){
    e.preventDefault();

    var index = $(this).index();

    // Set the current style
    $('.tabs').attr('style', makeCss(index));
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多