我为常规创建了一个自定义可绘制对象(基于可绘制选择器)Button
,我决定使用物理鼠标和键盘测试我的应用程序。
那时我注意到,每次我用物理鼠标单击按钮时,它都会在hovered
很短的时间内失去状态,并且仅在几毫秒后才恢复pressed
状态。
即使这种情况只发生很短的时间,它也会产生令人讨厌且非常明显的“眨眼”。
我不知道我是否说清楚了,所以我将重现这些步骤:
1 - 按钮处于空闲状态,并且鼠标指针不在按钮上方:按钮以默认状态呈现 ok
2 - 我将鼠标光标移到按钮上,然后鼠标不动:按钮呈现悬停状态
3 - 我按下鼠标左键:按钮以默认状态(未悬停)呈现片刻,然后以按下状态呈现,产生视觉闪烁
Button
通过用覆盖 drawableStateChanged()的自定义类替换按钮,可以轻松复制/验证这种奇怪的行为:
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
final int[] states = getDrawableState();
StringBuilder builder = new StringBuilder("@@@ ");
if (states != null) {
for (int i = states.length - 1; i >= 0; i--) {
switch (states[i]) {
case android.R.attr.state_pressed:
builder.append("p");
break;
case android.R.attr.state_focused:
builder.append("f");
break;
case android.R.attr.state_hovered:
builder.append("h");
break;
}
}
}
System.out.println(builder.toString());
}
Logcat 显示:
@@@ [the button is in the default state]
@@@ h [the button is in the hovered state]
[I physically click the left mouse button]
@@@ [the button goes back to the default state even though it *is* hovered and pressed]
@@@ p [after a visual blink, the button goes to its pressed state]
...
我几乎尝试了一切:压倒一切onHoverChanged()
,setHovered()
等等...我什至尝试在isHovered()
内部调用drawableStateChanged()
以查看是否有区别...什么都没有!!!!在设置按下状态之前,Android 会主动将可绘制状态和hovered
属性更改为 false。那是故意的!
我在网上到处找,甚至在 SO。没有什么!好像还没有人注意到它,或者我一定忘记了一些非常简单的事情......
仅供参考:我没有使用任何库(如 AppCompat 等)。它是一个普通的按钮,放置在一个普通的 Activity 中。在三星 A5 2017(使用 USB 鼠标)和华硕 Chromebook Flip C100(使用触控板)上进行了测试。
仅供参考 2:实际样式为v21/styles.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<style name="AppBaseTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
<item name="android:colorPrimary">#ff3344bb</item>
<item name="android:colorAccent">#ff3344bb</item>
<item name="android:colorControlNormal">#ff6d6d6d</item>
</style>
</resources>
仅供参考 3:我也尝试覆盖onGenericMotionEvent()
. 同样,只要我单击按钮 logcat 显示@@@ HEXIT
。此后不久,logcat 显示@@@ HENTER
...但我什至从未将鼠标光标移动一个像素...更不用说将其移到按钮之外!
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_HOVER_ENTER:
System.out.println("@@@ HENTER");
break;
case MotionEvent.ACTION_HOVER_EXIT:
System.out.println("@@@ HEXIT");
break;
}
return super.onGenericMotionEvent(event);
}
我怎样才能摆脱这种行为?有谁知道禁用此闪烁的标志或技巧?
重要提示:我不想使用到目前为止我想出的唯一解决方法:创建私有标志来手动控制悬停状态,忽略 Android 的悬停状态并使用计时器/计划延迟/等。