Установка счетчика на ClickListener () в Android - PullRequest
32 голосов
/ 14 октября 2010

Я пытаюсь заставить onClickListener запускаться на Spinner, но получаю следующую ошибку:

Java.lang.RuntimeException is «Не вызывать setOnClickListener для AdapterView. Вывероятно, вместо этого нужно установить setOnItemClickListener: "

Я уверен, что хочу вызвать onClickListener, а НЕ onItemClickListener.Я нашел вопрос, заданный кем-то еще о переполнении стека, Есть ли способ использовать setOnClickListener с Android Spinner?

В ответе указано:

Вы должны будете установить прослушиватель Click в базовом представлении (обычно TextView с id: android.R.id.text1) счетчика.Для этого:

Создание собственного Spinner. В конструкторе (с атрибутами) создайте Spinner, предоставив макет android.R.layout.simple_spinner_item. Выполните findViewById (android.R.id.text1), чтобы получитьTextView Теперь установите onClickListener для TextView

Я попробовал ответ, отмеченный там, но, похоже, он не работает.Я получаю нулевой указатель на TextView после того, как я выполняю findViewById ().

Вот что я делаю:

Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.layoutspinner,dataArray);

spinner.setAdapter(adapter);

TextView SpinnerText = (TextView)findViewById(R.id.spinnerText);
if (SpinnerText == null) {
    System.out.println("Not found");
}
else {
    SpinnerText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View arg0) {
            //Do something
        }
    });
}

Файл layoutspinner.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
                  android:id="@+id/spinnerText"
                  android:singleLine ="true"
                  android:layout_width="fill_parent"
                  android:layout_height="wrap_content"
                  android:textSize="6pt"
                  android:gravity="right"/>

Что я делаю не так?

Я новичок в Stack Overflow, я не нашел способа опубликовать дополнительный вопрос в другой ветке (или оставить комментарий, так как у меня мало повторений), поэтому яначал новый вопрос.

По рекомендации я попробовал это:

int a = spinnerMes.getCount();
int b = spinnerMes.getChildCount();
System.out.println("Count = " + a);
System.out.println("ChildCount = " + b);
for (int i = 0; i < b; i++) {
    View v = spinnerMes.getChildAt(i);
    if (v == null) {
        System.out.println("View not found");
    }
    else {
        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Click code
            }
        });
    }
}

Но LogCat не показывает многообещающие результаты.

10-14 16:09:08.127: INFO/System.out(3116): Count = 7
10-14 16:09:08.127: INFO/System.out(3116): ChildCount = 0

Я проверил это на уровнях API 7 и 8 с одинаковыми результатами.

Ответы [ 7 ]

56 голосов
/ 15 декабря 2011

Вот рабочее решение:

Вместо установки OnClickListener счетчика, мы устанавливаем OnTouchListener и OnKeyListener.

spinner.setOnTouchListener(Spinner_OnTouch);
spinner.setOnKeyListener(Spinner_OnKey);

и слушатели:

private View.OnTouchListener Spinner_OnTouch = new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            doWhatYouWantHere();
        }
        return true;
    }
};
private static View.OnKeyListener Spinner_OnKey = new View.OnKeyListener() {
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
            doWhatYouWantHere();
            return true;
        } else {
            return false;
        }
    }
};
27 голосов
/ 04 октября 2013

Всякий раз, когда вам нужно выполнить какое-либо действие по щелчку Spinner в Android, используйте следующий метод.

mspUserState.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            doWhatIsRequired();
        }
        return false;
    }
});

Единственное, что нужно иметь в виду, это всегда возвращать False при использовании вышеуказанного метода.Если вы вернете True , выпадающие элементы счетчика не будут отображаться при нажатии на Spinner.

13 голосов
/ 02 апреля 2014

Лично я использую это:

    final Spinner spinner = (Spinner) (view.findViewById(R.id.userList));
    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {                

            userSelectedIndex = position;
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });  
5 голосов
/ 25 сентября 2012

Прежде всего, спиннер не поддерживает события щелчка предмета.Вызов этого метода вызовет исключение.

Вы можете использовать setOnItemSelectedListener:

Spinner s1;
s1 = (Spinner)findViewById(R.id.s1);
int selectionCurrent = s1.getSelectedItemPosition();

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            if (selectionCurrent != position){
                // Your code here
            }
            selectionCurrent= position;
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parentView) {
        // Your code here
    }
});
4 голосов
/ 14 октября 2010

Следующее работает так, как вы хотите, но оно не идеально.

public class Tester extends Activity {

    String[] vals = { "here", "are", "some", "values" };
    Spinner spinner;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        spinner = (Spinner) findViewById(R.id.spin);
        ArrayAdapter<String> ad = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, vals);
        spinner.setAdapter(ad);
        Log.i("", "" + spinner.getChildCount());
        Timer t = new Timer();
        t.schedule(new TimerTask() {

            @Override
            public void run() {
                int a = spinner.getCount();
                int b = spinner.getChildCount();
                System.out.println("Count =" + a);
                System.out.println("ChildCount =" + b);
                for (int i = 0; i < b; i++) {
                    View v = spinner.getChildAt(i);
                    if (v == null) {
                        System.out.println("View not found");
                    } else {
                        v.setOnClickListener(new View.OnClickListener() {

                            @Override
                            public void onClick(View v) {
                                        Log.i("","click");
                                        }
                        });
                    }
                }
            }
        }, 500);
    }
}

Дайте мне точно знать, как вам нужен спиннер, и мы сможем найти лучшее решение.

2 голосов
/ 16 февраля 2015

Я предлагаю разделить все события для Spinner на два типа:

  1. Пользовательские события (вы имели в виду событие "click").

  2. События программы.

Я также предлагаю, чтобы когда вы хотите перехватить пользовательское событие, вы просто хотели избавиться от «программных событий». Так что все довольно просто:

private void setSelectionWithoutDispatch(Spinner spinner, int position) {
    AdapterView.OnItemSelectedListener onItemSelectedListener = spinner.getOnItemSelectedListener();
    spinner.setOnItemSelectedListener(null);
    spinner.setSelection(position, false);
    spinner.setOnItemSelectedListener(onItemSelectedListener);
}

Есть ключевой момент: вам нужно setSelection (position, false). «false» в параметре анимации вызовет событие немедленно. Поведение по умолчанию - отправка события в очередь событий.

0 голосов
/ 30 октября 2018

Класс Spinner реализует DialogInterface.OnClickListener, тем самым эффективно угоняя стандарт View.OnClickListener.

Если вы не используете подчиненный класс Spinner или не собираетесь, выберите другой ответ.

В противном случае просто добавьте следующий код в свой пользовательский Spinner:

@Override
/** Override triggered on 'tap' of closed Spinner */
public boolean performClick() {
    // [ Do anything you like here ]
    return super.performClick();
}

Пример. Отображение предварительно предоставленной подсказки через Snackbar при каждом открытии Spinner:

private String sbMsg=null;      // Message seen by user when Spinner is opened.
public void setSnackbarMessage(String msg) { sbMsg=msg; }
@Override
/** Override triggered on 'tap' of closed Spinner */
public boolean performClick() {
    if (sbMsg!=null && !sbMsg.isEmpty()) { /* issue Snackbar */ }
    return super.performClick();
}

Trapping 'click' of closed Spinner

Пользовательский Spinner - потрясающая отправная точка для программной стандартизации внешнего вида Spinner во всем вашем проекте.

Если интересно, посмотрите здесь

...