Drawable селектор теряет состояние при наведении мыши

Я создал настраиваемое рисование (основано на селекторе рисования) для обычного Button и я решил протестировать свое приложение с помощью физической мыши и клавиатуры.

Именно тогда я заметил, что каждый раз, когда я нажимаю кнопку с физической мышью, он теряет hovered состояние в течение очень короткого момента и только через несколько миллисекунд он приобретает pressed государство.

Хотя это происходит только в течение очень короткого момента, оно вызывает раздражающее и очень заметное "моргание".

Я не знаю, дал ли я ясно понять, поэтому я воспроизведу шаги:

1 - кнопка находится в режиме ожидания, а указатель мыши не находится над кнопкой: кнопка отображается нормально с состоянием по умолчанию

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 и т. Д. И т. Д.). Это простая кнопка, помещенная в простую активность. Протестировано на Samsung A5 2017 (с USB-мышью) и на Asus 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 и используя таймеры / запланированные задержки / и т.д.

0 ответов

Другие вопросы по тегам