在 Android 的 WebView 中修改选择时,文本选择菜单消失
Text selection menu disappears when modifying the selection in Android's WebView
我找遍了所有地方,似乎找不到遇到同样问题的人。
问题总结:
当我 select 一些文本时,会出现标准菜单(复制、粘贴等),但是当我修改 selection 使其包含 带有某些 CSS rules 菜单消失(而 selection 保持活动状态)。
到目前为止,我在以下设备上遇到过该问题:
- "Samsung Galaxy Tab S" (SM-T705), Android 6.0.1, Chrome/78.0.3904.108
- "Samsung Galaxy Tab A" (SM-T550), Android 7.1.1, Chrome/77.0.3865.92
- "Samsung Galaxy Tab S4" (SM-T830), Android 9, Chrome/78.0.3904.108
- "OnePlus 6T", Android 9, Chrome/79.0.3945.93
Android 6 以下的版本似乎没有受到影响(我假设是因为文本 selection 菜单不同)。
问题的较长版本:
我正在做一个项目,在这个项目中,我们的网页上充满了文本,并且该文本应该 select 可用。
问题是某些 HTML 元素的 CSS 规则会破坏文本 selection 菜单,我不知道为什么。
不幸的是,这些网页是由第三方生成的,所以我无法直接控制他们的 structure/CSS 规则。
我拿走了其中一页并尽可能地剥离它,只留下复制问题所需的内容。
这是页面的HTML:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta content="width=558, height=754" name="viewport">
<meta charset="utf-8">
<meta content="0:0:558.425:754.016" name="pagecontentbbox">
<title>Test Page</title>
<link href="css/page.css" rel="stylesheet" type="text/css">
</head>
<body>
<section>
<div id="container">
<div id="parent-p1">
<p><span class="vab lh1 psa" id="first_span"><span
class="sid19 sf19 sf1 sf20 di psr b0 l0" data-x="126" data-y="322" id="word8">ONE</span><span
class=" sf19 di psr b0 l0 fm sf22"> </span><span
class="sid23 sf19 sf1 sf20 di psr b0 l0" data-x="165" data-y="322" id="word9">TWO</span><span
class=" sf19 di psr b0 l0 fm sf24"> </span><span
class="sid25 sf19 sf1 sf20 di psr b0 l0" data-x="246" data-y="322" id="word10">THREE</span><span
class=" sf7 di psr b0 l0 fm sf8"> </span></span></p>
<p><span class="vab lh1 psa" id="second_span"><span
class="sid448 sf448 sf1 sf449 di psr b0 l0" data-x="126" data-y="580"
id="word234">FOUR</span><span class=" sf448 di psr b0 l0 fm sf451"> </span><span
class="sid452 sf448 sf452 sf449 di psr b0 l0" data-x="143" data-y="579"
id="word235">FIVE</span><span class=" sf448 di psr b0 l0 fm sf454"> </span><span
class="sid455 sf448 sf452 sf449 di psr b0 l0" data-x="179" data-y="579"
id="word236">SIX</span><span
class=" sf448 di psr b0 l0 fm sf456"> </span><span
class="sid457 sf448 sf1 sf449 di psr b0 l0" data-x="260" data-y="580"
id="word237">SEVEN</span><span class=" sf448 di psr b0 l0 fm sf458"> </span><span
class="sid459 sf448 sf1 sf449 di psr b0 l0" data-x="280" data-y="580"
id="word238">EIGHT</span><span
class=" sf7 di psr b0 l0 fm sf8"> </span></span></p></div>
</div>
</section>
</body>
</html>
这是页面的CSS:
body {
height: 754px;
margin: 0;
width: 558px;
}
span {
border: 0;
margin: 0;
white-space: pre;
position: relative;
}
#container {
height: 754.016px;
left: 0px;
overflow: hidden;
position: absolute;
top: 0px;
width: 558.425px;
}
#parent-p1 {
-moz-transform: scale(0.15613);
-moz-transform-origin: left bottom;
-ms-transform: scale(0.015613);
-ms-transform-origin: left bottom;
-o-transform: scale(0.015613);
-o-transform-origin: left bottom;
-webkit-transform: scale(0.015613);
-webkit-transform-origin: left bottom;
height: 100%;
position: absolute;
white-space: nowrap;
width: 100%;
}
#first_span {
bottom: 27661.888px;
left: 8073.216px;
}
#second_span {
-moz-transform: matrix(0.98, -0, -0, 1, 0, 0);
-moz-transform-origin: bottom left;
-ms-transform: matrix(0.98, -0, -0, 1, 0, 0);
-ms-transform-origin: bottom left;
-webkit-transform: matrix(0.98, -0, -0, 1, 0, 0);
-webkit-transform-origin: bottom left;
bottom: 11185.536px;
left: 8073.216px;
transform: matrix(0.98, -0, -0, 1, 0, 0);
transform-origin: bottom left;
}
.vab {
vertical-align: bottom;
}
.psa {
position: absolute;
}
.lh1 {
line-height: 1;
}
.psr {
position: relative;
}
.b0 {
bottom: 0;
}
.l0 {
left: 0;
}
.fm {
font-family: monospace;
}
.sf7 {
font-size: 0px;
}
.sf8 {
letter-spacing: 0px;
}
.sf19 {
font-size: 2048px;
}
.sf20 {
color: #D6AB52;
}
.sf22 {
letter-spacing: -807.117px;
}
.sf24 {
letter-spacing: -798.643px;
}
.sf448 {
font-size: 1280.002px;
}
.sf449 {
color: #CA9937;
}
.sf451 {
letter-spacing: -509.595px;
}
.sf454 {
letter-spacing: -548.36px;
}
.sf456 {
letter-spacing: -509.217px;
}
.sf458 {
letter-spacing: -509.749px;
}
.sid23 {
letter-spacing: -7.629px;
}
.sid25 {
letter-spacing: -2.664px;
}
.sid448 {
letter-spacing: -0px;
}
.sid452 {
letter-spacing: 9.408px;
}
.sid455 {
letter-spacing: 0px;
}
.sid457 {
letter-spacing: 0px;
}
.sid459 {
letter-spacing: -4.058px;
}
这是加载页面的方式:
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
webView.setWebContentsDebuggingEnabled(true);
webView.loadUrl("file:///android_asset/page.html");
}
}
如果有用,我可以上传测试应用到GitHub。
这里有几个案例可以说明这个问题。
案例 1:
- Select"ONE",出现菜单。 (好的)
案例二:
- Select"TWO",出现菜单。
- 更改 selection,使 "ONE" 也包含在内。菜单消失,而 selection 保持活动状态。 (不好)
案例 3:
- Select"TWO",出现菜单。
- 更改 selection,使 "THREE" 也包含在内。菜单还在。 (好的)
案例 4:
- Select"FOUR",出现菜单。 (好的)
案例 5:
- Select "FIVE",出现菜单。
- 更改 selection,使 "FOUR" 也包含在内。菜单消失,而 selection 保持活动状态。 (不好)
案例 6:
- Select "FIVE",出现菜单。
- 更改 selection,使 "SIX"(或 "SEVEN" 或 "EIGHT")也包括在内。菜单还在。 (好的)
基本上,如果您只 select 导致问题的词,就会出现菜单。它只会在创建包含有问题的单词的文本 selection 时消失。
在示例中提供的导致问题的词是 "ONE" 和 "FOUR" 但是我不认为它们本身就是原因。
碰巧这些单词中的每一个都位于 <span>
元素(id="first_span"
和 id="second_span"
)的开头,这些元素具有特定的 CSS 规则可能是导致问题的原因。
有问题的 CSS 规则是 "left: ...px;"
,在为两个 <span>
元素禁用它(或设置为 0)后,菜单的行为符合预期。
所以目前我不知道这是重叠元素、嵌套还是其他原因引起的问题。
希望我提供了所有必要的信息,如果有人能帮助我弄清楚发生了什么以及为什么会这样,我将不胜感激。
经过一些挖掘,我发现问题不是由 WebView 引起的,而是由 Chrome(在“71.0.3578.99”和“76.0.3793.0”之间的某个版本中引入的)引起的。
事实上,他们的错误跟踪器上已经有一个未解决的问题 link:
https://bugs.chromium.org/p/chromium/issues/detail?id=962413
我找遍了所有地方,似乎找不到遇到同样问题的人。
问题总结:
当我 select 一些文本时,会出现标准菜单(复制、粘贴等),但是当我修改 selection 使其包含 带有某些 CSS rules 菜单消失(而 selection 保持活动状态)。
到目前为止,我在以下设备上遇到过该问题:
- "Samsung Galaxy Tab S" (SM-T705), Android 6.0.1, Chrome/78.0.3904.108
- "Samsung Galaxy Tab A" (SM-T550), Android 7.1.1, Chrome/77.0.3865.92
- "Samsung Galaxy Tab S4" (SM-T830), Android 9, Chrome/78.0.3904.108
- "OnePlus 6T", Android 9, Chrome/79.0.3945.93
Android 6 以下的版本似乎没有受到影响(我假设是因为文本 selection 菜单不同)。
问题的较长版本:
我正在做一个项目,在这个项目中,我们的网页上充满了文本,并且该文本应该 select 可用。
问题是某些 HTML 元素的 CSS 规则会破坏文本 selection 菜单,我不知道为什么。
不幸的是,这些网页是由第三方生成的,所以我无法直接控制他们的 structure/CSS 规则。
我拿走了其中一页并尽可能地剥离它,只留下复制问题所需的内容。
这是页面的HTML:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta content="width=558, height=754" name="viewport">
<meta charset="utf-8">
<meta content="0:0:558.425:754.016" name="pagecontentbbox">
<title>Test Page</title>
<link href="css/page.css" rel="stylesheet" type="text/css">
</head>
<body>
<section>
<div id="container">
<div id="parent-p1">
<p><span class="vab lh1 psa" id="first_span"><span
class="sid19 sf19 sf1 sf20 di psr b0 l0" data-x="126" data-y="322" id="word8">ONE</span><span
class=" sf19 di psr b0 l0 fm sf22"> </span><span
class="sid23 sf19 sf1 sf20 di psr b0 l0" data-x="165" data-y="322" id="word9">TWO</span><span
class=" sf19 di psr b0 l0 fm sf24"> </span><span
class="sid25 sf19 sf1 sf20 di psr b0 l0" data-x="246" data-y="322" id="word10">THREE</span><span
class=" sf7 di psr b0 l0 fm sf8"> </span></span></p>
<p><span class="vab lh1 psa" id="second_span"><span
class="sid448 sf448 sf1 sf449 di psr b0 l0" data-x="126" data-y="580"
id="word234">FOUR</span><span class=" sf448 di psr b0 l0 fm sf451"> </span><span
class="sid452 sf448 sf452 sf449 di psr b0 l0" data-x="143" data-y="579"
id="word235">FIVE</span><span class=" sf448 di psr b0 l0 fm sf454"> </span><span
class="sid455 sf448 sf452 sf449 di psr b0 l0" data-x="179" data-y="579"
id="word236">SIX</span><span
class=" sf448 di psr b0 l0 fm sf456"> </span><span
class="sid457 sf448 sf1 sf449 di psr b0 l0" data-x="260" data-y="580"
id="word237">SEVEN</span><span class=" sf448 di psr b0 l0 fm sf458"> </span><span
class="sid459 sf448 sf1 sf449 di psr b0 l0" data-x="280" data-y="580"
id="word238">EIGHT</span><span
class=" sf7 di psr b0 l0 fm sf8"> </span></span></p></div>
</div>
</section>
</body>
</html>
这是页面的CSS:
body {
height: 754px;
margin: 0;
width: 558px;
}
span {
border: 0;
margin: 0;
white-space: pre;
position: relative;
}
#container {
height: 754.016px;
left: 0px;
overflow: hidden;
position: absolute;
top: 0px;
width: 558.425px;
}
#parent-p1 {
-moz-transform: scale(0.15613);
-moz-transform-origin: left bottom;
-ms-transform: scale(0.015613);
-ms-transform-origin: left bottom;
-o-transform: scale(0.015613);
-o-transform-origin: left bottom;
-webkit-transform: scale(0.015613);
-webkit-transform-origin: left bottom;
height: 100%;
position: absolute;
white-space: nowrap;
width: 100%;
}
#first_span {
bottom: 27661.888px;
left: 8073.216px;
}
#second_span {
-moz-transform: matrix(0.98, -0, -0, 1, 0, 0);
-moz-transform-origin: bottom left;
-ms-transform: matrix(0.98, -0, -0, 1, 0, 0);
-ms-transform-origin: bottom left;
-webkit-transform: matrix(0.98, -0, -0, 1, 0, 0);
-webkit-transform-origin: bottom left;
bottom: 11185.536px;
left: 8073.216px;
transform: matrix(0.98, -0, -0, 1, 0, 0);
transform-origin: bottom left;
}
.vab {
vertical-align: bottom;
}
.psa {
position: absolute;
}
.lh1 {
line-height: 1;
}
.psr {
position: relative;
}
.b0 {
bottom: 0;
}
.l0 {
left: 0;
}
.fm {
font-family: monospace;
}
.sf7 {
font-size: 0px;
}
.sf8 {
letter-spacing: 0px;
}
.sf19 {
font-size: 2048px;
}
.sf20 {
color: #D6AB52;
}
.sf22 {
letter-spacing: -807.117px;
}
.sf24 {
letter-spacing: -798.643px;
}
.sf448 {
font-size: 1280.002px;
}
.sf449 {
color: #CA9937;
}
.sf451 {
letter-spacing: -509.595px;
}
.sf454 {
letter-spacing: -548.36px;
}
.sf456 {
letter-spacing: -509.217px;
}
.sf458 {
letter-spacing: -509.749px;
}
.sid23 {
letter-spacing: -7.629px;
}
.sid25 {
letter-spacing: -2.664px;
}
.sid448 {
letter-spacing: -0px;
}
.sid452 {
letter-spacing: 9.408px;
}
.sid455 {
letter-spacing: 0px;
}
.sid457 {
letter-spacing: 0px;
}
.sid459 {
letter-spacing: -4.058px;
}
这是加载页面的方式:
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
webView.setWebContentsDebuggingEnabled(true);
webView.loadUrl("file:///android_asset/page.html");
}
}
如果有用,我可以上传测试应用到GitHub。
这里有几个案例可以说明这个问题。
案例 1:
- Select"ONE",出现菜单。 (好的)
案例二:
- Select"TWO",出现菜单。
- 更改 selection,使 "ONE" 也包含在内。菜单消失,而 selection 保持活动状态。 (不好)
案例 3:
- Select"TWO",出现菜单。
- 更改 selection,使 "THREE" 也包含在内。菜单还在。 (好的)
案例 4:
- Select"FOUR",出现菜单。 (好的)
案例 5:
- Select "FIVE",出现菜单。
- 更改 selection,使 "FOUR" 也包含在内。菜单消失,而 selection 保持活动状态。 (不好)
案例 6:
- Select "FIVE",出现菜单。
- 更改 selection,使 "SIX"(或 "SEVEN" 或 "EIGHT")也包括在内。菜单还在。 (好的)
基本上,如果您只 select 导致问题的词,就会出现菜单。它只会在创建包含有问题的单词的文本 selection 时消失。
在示例中提供的导致问题的词是 "ONE" 和 "FOUR" 但是我不认为它们本身就是原因。
碰巧这些单词中的每一个都位于 <span>
元素(id="first_span"
和 id="second_span"
)的开头,这些元素具有特定的 CSS 规则可能是导致问题的原因。
有问题的 CSS 规则是 "left: ...px;"
,在为两个 <span>
元素禁用它(或设置为 0)后,菜单的行为符合预期。
所以目前我不知道这是重叠元素、嵌套还是其他原因引起的问题。
希望我提供了所有必要的信息,如果有人能帮助我弄清楚发生了什么以及为什么会这样,我将不胜感激。
经过一些挖掘,我发现问题不是由 WebView 引起的,而是由 Chrome(在“71.0.3578.99”和“76.0.3793.0”之间的某个版本中引入的)引起的。
事实上,他们的错误跟踪器上已经有一个未解决的问题 link:
https://bugs.chromium.org/p/chromium/issues/detail?id=962413