1

我为常规创建了一个自定义可绘制对象(基于可绘制选择器)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 的悬停状态并使用计时器/计划延迟/等。

4

0 回答 0