Android Spinner Закрыть - PullRequest
       56

Android Spinner Закрыть

9 голосов
/ 02 сентября 2011

У меня есть действие со счетчиком, и мне было интересно, можно ли программно закрыть счетчик, если пользователь открыл его.

Вся история в том, что в фоновом режиме я запускаю процесс в отдельном потоке. Когда процесс завершен, я вызываю обработчик для основного действия и, в зависимости от результата, выполняю некоторые задачи. Тогда я хочу закрыть счетчик, если пользователь открыл его.

Спиннер находится в макете main.xml:

<Spinner android:id="@+id/birthPlaceSpinner" android:layout_weight="1" 
android:layout_height="wrap_content" android:prompt="@string/select"
android:layout_width="fill_parent" />

и это обработчик:

private class BirthplaceChangedHandler extends Handler {

    @Override
    public void handleMessage(Message msg) {
        String placeFilterStr = birthPlaceFilterText.getText().toString();
        if ("".equals(placeFilterStr) || placeFilterStr == null || validNewAddresses.isEmpty()) {
            birthPlaceSpinner.setEnabled(false);
            hideGeoLocationInformation();
        } else {
            birthPlaceSpinner.setEnabled(true);
        }
        adapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.multiline_spinner_dropdown_item, validNewAddressesStr)
        birthPlaceSpinner.setAdapter(adapter);
    }
}

Ура!

Ответы [ 8 ]

17 голосов
/ 31 марта 2013

Это работает для меня:

class SomeAdapter extends BaseAdapter implements SpinnerAdapter {
    //......   
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        if (view == null) {
            //......
        }
        view.setOnClickListener(new ItemOnClickListener(parent));
        return view;
    }
    //.....
}

и прослушиватель щелчков:

class ItemOnClickListener implements View.OnClickListener {
    private View _parent;

    public ItemOnClickListener(ViewGroup parent) {
        _parent = parent;
    }

    @Override
    public void onClick(View view) {
        //.......
        // close the dropdown
        View root = _parent.getRootView();
        root.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
        root.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
    }
}
8 голосов
/ 24 октября 2017
  public static void hideSpinnerDropDown(Spinner spinner) {
    try {
        Method method = Spinner.class.getDeclaredMethod("onDetachedFromWindow");
        method.setAccessible(true);
        method.invoke(spinner);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
8 голосов
/ 06 августа 2013

Ну, это немного сложнее, чем я думал.

Я добавляю пошаговые подробности здесь.Попытайтесь следовать этому.Я смог достичь этого на уровне API 10.

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

Первым шагом является создание пользовательского Spinner путем расширения класса Spinner.Допустим, я создал класс с именем CustomSpinner в пакете com.bts.sampleapp

Мой класс CustomSpinner выглядит следующим образом:

package com.bts.sampleapp;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.Spinner;

    public class CustomSpinner extends Spinner{
        Context context=null;

        public CustomSpinner(Context context) {
            super(context);
            this.context=context;
        }

        public CustomSpinner(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

        public CustomSpinner(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        @Override
        public void onDetachedFromWindow() {
            super.onDetachedFromWindow();
        }
    }

Теперь в вашем XML-файле замените элемент Spinner на этот пользовательский счетчик,

        <com.bts.sampleapp.CustomSpinner
        android:id="@+id/spin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

Следующим шагом будет инициализация и установка адаптера для этого счетчика в классе Activity,

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    CustomSpinner spin=null;
    spin=(CustomSpinner)findViewById(R.id.spin);
    spin.setAdapter(spinnerAdapter); //you can set your adapter here.
}
* 1023.* Последний шаг - закрыть диалоговое окно, когда пользователь нажимает кнопку HomeButton или когда действие переходит в фоновый режим.Чтобы сделать это, мы переопределяем onPause () следующим образом:
@Override
    protected void onPause() {
        Log.i("Life Cycle", "onPause");
        spin.onDetachedFromWindow();
        super.onPause();
    }

Теперь внутри onPause () вызываем метод spin.onDetachedFromWindow();, который выполняет за вас закрытие диалогового окна с подсказкой.

Теперь, как говорится, вызов spin.onDetachedFromWindow(); из любой точки вашей Деятельности должен помочь вам программно закрыть счетчик.Так что если это то, что вы хотите, то удалите onpause().

8 голосов
/ 02 сентября 2011

Я не вижу способа сделать это - на Spinner нет способа его закрыть. «Открытая» часть Spinner - это AlertDialog на Android 1.x и 2.x, и я не совсем уверен, как она реализована в Honeycomb при использовании голографической темы.

Единственный обходной путь - клонировать исходный код для Spinner и добавить код самостоятельно, чтобы закрыть диалоговое окно. Но, опять же, он не будет работать на Honeycomb или выше, пока вы не сможете увидеть и клонировать этот код.

Кроме того, я бы подумал, что вам нужен плохой UX. Если пользователь открыл Spinner, он, скорее всего, активно изучает содержимое Spinner и делает выбор. Выдергивание из-под их пальца, в лучшем случае, смущает их. Пожалуйста, рассмотрите альтернативный подход.

Кроме того, не используйте getApplicationContext(), если вы не знаете , почему вы используете getApplicationContext(). Вам не нужно или даже не нужно getApplicationContext() при создании ArrayAdapter.

3 голосов
/ 02 сентября 2011

Я думаю, вам следует отказаться от использования Spinner и вместо этого использовать ImageView с Frame Animation (т.е. <animation-list>), чтобы создать свой собственный счетчик. Вы просто устанавливаете фон ImageView для рисования вашей анимации кадра.

Тогда вы можете легко сделать что-то , подобное этому , чтобы запустить и остановить его.

1 голос
/ 09 июня 2014

Вы хотели бы закрыть свои счетчики в любом месте.Нажатие клавиши для НАЗАД является хорошим решением, но здесь вы закрываете все представления одновременно.

Как насчет setPressed (false)?
Ссылка: Закрытие выпадающих кругов, когда два среди всех впри групповом просмотре одновременно щелкают

В противном случае: попробуйте сделать Spinner focusable и focusableInTouchMode и использовать на нем clearFocus().Попробуйте сфокусироваться на представлении под ним, используя метод requestFocus().

Проверьте, не закрывается ли раскрывающийся список

1 голос
/ 02 октября 2012

Как насчет клонирования нажатия клавиши «назад»?

Хорошо, я только что попробовал

[current activity].dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_BACK));

, и ничего не получалось, что я мог видеть - затем нажал физическую клавишу возврата ивыпадение ушло.Также попытался сделать ACTION_UP сразу после нажатия вниз - эффекта тоже нет.

0 голосов
/ 22 апреля 2015

Используйте clearFocus() для программного закрытия счетчика

spinner.clearFocus();
...