Android spinner близко


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

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

Прядильщик находится в основном.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 8

8 ответов:

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

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

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

Также не используйте getApplicationContext(), Если вы не знаете , Почему вы используете getApplicationContext(). Вы не нуждаетесь и даже не хотите getApplicationContext() при создании ArrayAdapter.

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

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));
    }
}

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

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

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

Первым шагом является создание пользовательского прядильщика путем расширения класса прядильщика. Допустим, я создал класс CustomSpinner в упаковке кОм.БТС.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 на этот пользовательский spinner,

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

Следующим шагом является инициализация и установка адаптера для этого spinner в вашем классе 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.
}
Последний шаг-закрыть диалоговое окно, когда пользователь нажимает кнопку HomeButton или когда действие переходит в фоновый режим. Для этого мы переопределяем onPause () вот так,
@Override
    protected void onPause() {
        Log.i("Life Cycle", "onPause");
        spin.onDetachedFromWindow();
        super.onPause();
    }

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

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

  public static void hideSpinnerDropDown(Spinner spinner) {
    try {
        Method method = Spinner.class.getDeclaredMethod("onDetachedFromWindow");
        method.setAccessible(true);
        method.invoke(spinner);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

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

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

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

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

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

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

Вы хотели бы закрыть свои блесны отовсюду. Инъекция ключа для обратного нажатия-это хорошее решение, но здесь вы закрываете все виды сразу.

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

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

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

Используйте clearFocus(), чтобы закрыть программу spinner программно

spinner.clearFocus();