Как установить OnValueChangedListener из NumberPicker внутри BaseAdapter

Я пытаюсь создать BaseAdapter, каждый элемент которого имеет NumberPicker и кнопку. Параметры действия кнопки зависят от значения, выбранного в NumberPicker. Я думал, что одним из решений было создание setOnClickListener (кнопки) внутри onValueChange NumberPicker, проблема в том, что onValueChange никогда не срабатывает, когда я меняю номер.

Я оставляю вам код, чтобы было понятнее:

public class Adapter extends BaseAdapter{
...

  public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        if (v == null)
        {
            LayoutInflater vi = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.row, null);
        }
        button = (Button) v.findViewById(R.id.button);
        numPick = (NumberPicker) v.findViewById(R.id.numPick);
        numPick.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                val = newVal;
                button.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View arg0) {
                        actionToPerform(val);
                    }
                });
            }
        });

Как я могу решить эту проблему? Спасибо!


person Albert    schedule 13.06.2014    source источник


Ответы (1)


Поскольку адаптер будет повторно использовать макет, вам нужно будет установить прослушиватель при создании макета. Переместите прослушиватель кнопок. В противном случае он будет устанавливаться при каждом изменении значения. Вот исправленный код:

// Put the array as a member of your activity or fragment's class
// Remember to save it between life cycle event
// Initialize it to same size as your adapter data
int[] numValues;

public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null)
    {
        LayoutInflater vi = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.row, null);

        final Button button = (Button) v.findViewById(R.id.button);
        final NumberPicker numPick = (NumberPicker) v.findViewById(R.id.numPick);

        button.setOnClickListener(new View.OnClickListener() {
                public void onClick(View arg0) {
                    // Get the position value from the tag field
                    int pos = (int)button.tag;
                    actionToPerform(numValues[pos]);
                }
            });

        numPick.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
        public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
              // Save the value in the number picker
              numPick.tag = newVal;
          }
        });
    }

    // Save the position in the button's tag field
    button.tag = position;
    // Restore picker value
    final NumberPicker numPick1 = (NumberPicker) v.findViewById(R.id.numPick);
    numPicker1.setValue(numValues[position]);

}

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

person hfann    schedule 13.06.2014
comment
Прежде всего, спасибо за ваш ответ. Я не понимаю несколько вещей. Прежде всего, что такое тег? Могу ли я использовать позицию из getView вместо button.tag (я не знаю, как извлечь позицию из этого последнего). Если theNumberPicker является конечной переменной, я не могу получить доступ за пределами случая if. Спасибо еще раз! - person Albert; 14.06.2014
comment
Поле тега — это поле объекта View, которое не используется Android. Вы можете использовать его для хранения чего угодно. Переменная position в getView() содержит информацию о позиции, запрошенную элементом управления для отображения материала. Когда пользователь взаимодействует с элементом управления в строке, getView() не вызывается. Поэтому я сохраняю позицию в поле тега. Это гарантирует, что элемент управления в каждой отображаемой строке знает свою позицию. Извините, я должен определить другую переменную вне блока if. Я обновил код. - person hfann; 14.06.2014
comment
Теперь, когда я задал этот вопрос, у меня похожая проблема. Что делать, если мне приходится менять текст каждый раз, когда я меняю значение в средстве выбора чисел? Я не могу обновить текст, так как у меня нет слушателя (например, кнопки). Вы знаете, как это сделать? Спасибо! - person Albert; 15.06.2014
comment
В методе onValueChange() прослушивателя выбора номера вы можете вызвать метод notifyDataSetChanged(), чтобы принудительно перерисовать элемент управления. Затем отобразите текущее значение numValues[position] в TextView. Поместите вызов setText() сразу после установки значения NumberPicker после блока if. - person hfann; 15.06.2014