На Android есть ли способ отключить долгое нажатие Spinner?

Поведение счетчика по умолчанию таково, что когда он «закрыт», долгое нажатие на него «откроет» его и покажет вам раскрывающийся список. Я считаю такое поведение потенциально очень проблематичным для пользователя. Например, если они пытаются прокрутить что-то на экране и случайно «схватили» место с прядильщиком, то вместо прокрутки через секунду или около того он откроет раскрывающийся список, и пользователь в основном они оставили палец на одном из раскрывающихся меню (теперь они могут случайно нажать).

Итак, я хотел бы отключить это поведение при длительном нажатии, и чтобы счетчик «открывался» только тогда, когда по нему щелкают, а не при длительном нажатии. Это возможно?


person user496854    schedule 13.01.2015    source источник
comment
m_spinner.setLongClickable(false); может помочь вам здесь   -  person Chris Handy    schedule 13.01.2015
comment
Да, я попробовал это сначала, но на Spinner это не повлияло.   -  person user496854    schedule 13.01.2015


Ответы (4)


Если вам нужно только восстановить стандартное поведение щелчка, это более простая и компактная версия ответа Джорди:

spinner.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                v.performClick();
            }
            return true;
        }
    });

Дальнейшие мысли

Меня это поведение тоже раздражало. После расследования выяснилось, что у него есть имя: перетащить, чтобы открыть. Вы можете увидеть, как это определено в источнике _ 2_.

Некоторые проблемы, которые я вижу с этим принудительным поведением (и причину, по которой некоторые люди хотят его отключить):

  1. Это позволяет пользователю выбирать отключенные значения в счетчике. Путем длительного нажатия, перетаскивания и отпускания вы можете выбрать значения, которые невозможно выбрать даже при обычном взаимодействии (щелчок для открытия + щелчок для выбора)
  2. Как следствие №1, он также может очень легко привести к провалу теста эспрессо. Действительно, в Espresso продолжительность щелчка довольно нестабильна, и одно нажатие может быстро превратиться в длительное нажатие и выбор-взаимодействие.
  3. Наконец, самая большая проблема здесь в том, что нет атрибута method / XML для отключения поведения «перетаскивание для открытия» ...

Давайте исправим!

Я открыл связанный с этим тикет в системе отслеживания проблем AOSP: # 228953. Не стесняйтесь следить за ним или комментировать, если я что-то пропустил.

person David Ferrand    schedule 28.11.2016

Итак, я придумал относительно простой способ сделать это, хотя он не очень элегантен. По сути, я создал прозрачное наложение поверх Spinner и установил для него OnClickListener, который просто запускает щелчок Spinner.

XML:

    <Spinner 
        android:id="@+id/spinner"
        android:layout_width="match_parent" 
        android:layout_height="40dip" />

    <View android:id="@+id/spinner_overlay"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:layout_alignLeft="@id/spinner" 
        android:layout_alignRight="@id/spinner"
        android:layout_alignTop="@id/spinner" 
        android:layout_alignBottom="@id/spinner"  />

Java:

        View spinnerOverlay = findViewById(R.id.spinner_overlay);
        spinnerOverlay.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                spinner.performClick();
            }

        });
person user496854    schedule 14.01.2015

Вы уже пробовали android: longClickable = "false" в xml?

или попробуйте что-то вроде этого:

spinner.setOnTouchListener(new View.OnTouchListener() {
        private static final int MAX_CLICK_DISTANCE = 15;
        private static final int MAX_CLICK_DURATION = 1000;
        private long pressStartTime;
        private float pressedX;
        private float pressedY;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    pressStartTime = System.currentTimeMillis();
                    pressedX = event.getX();
                    pressedY = event.getY();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                long pressDuration = System.currentTimeMillis() - pressStartTime;
                if (pressDuration < MAX_CLICK_DURATION && distance(pressedX, pressedY, event.getX(), event.getY()) < MAX_CLICK_DISTANCE) {
                     //when long clicked.
                }
                break;
            }
        }
        return false;
}
person Jordi Sipkens    schedule 13.01.2015
comment
Если вы переопределите OnTouchListener счетчика, он вообще перестанет работать - person user496854; 13.01.2015
comment
Не у меня, я использую эту функцию на слайдере изображений. Скользящие элементы управления от super по-прежнему работают, только когда я нажимаю менее 1 секунды и диапазона x, он запускает onClick. Если он не соответствует этому диапазону, он просто будет использовать родительскую функцию. Попробуйте нажать Продолжительность ›MAX_CLICK_DURATION. Это ничего не даст, если вы нажмете дольше 1 секунды (LongClick). - person Jordi Sipkens; 14.01.2015
comment
это не имеет ничего общего с продолжительностью - вы переопределяете OnTouchListener и не обрабатываете какие-либо события, которые обычно присутствовали бы там. - person user496854; 14.01.2015

Немного поздно, но, может быть, кому-то пригодится:

Установка OnLongClickListener, которая возвращает true в onLongClick, предотвращает (непреднамеренное) открытие Spinner, потому что это работает так, как если бы обратный вызов потреблял длинный щелчок, как указано в документация.

spinner.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View view) {
        return true;
    }
});

Единственным недостатком является то, что спиннер все равно будет иметь анимацию onTouch при долгом нажатии.

person c7n    schedule 21.02.2018