setMinValue на NumberPicker не выбирает правильное минимальное значение

Я хочу создать NumberPicker с массивом отображаемых значений. Значения не должны изменяться при отображении NumberPicker, но минимальное и максимальное значения динамически изменяются в зависимости от действий пользователя.

Вот код:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <NumberPicker
        android:id="@+id/picker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>
</RelativeLayout>

В основной деятельности

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final String[] values = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};

        NumberPicker picker = (NumberPicker) findViewById(R.id.picker);
        picker.setDisplayedValues(values);
        picker.setMaxValue(7);
        picker.setMinValue(3);

        picker.setWrapSelectorWheel(false);
    }
}

Когда я устанавливаю максимум без установки минимума, я заканчиваю отображаемыми значениями между «0» и «7» (включительно). Если я установлю minValue на 0, у меня будет такое же поведение. Но если я установлю minValue на 3, я закончу отображаемыми значениями между «0» и «4». Когда он должен быть между "3" и "7".

Я не понимаю, почему. Я что-то не так сделал или проблема с компонентом?


person Eselfar    schedule 23.02.2017    source источник


Ответы (3)


Если вы посмотрите на реализацию setMinValue или setMaxValue, вы увидите комментарий, в котором говорится:

 * <strong>Note:</strong> The length of the displayed values array
 * set via {@link #setDisplayedValues(String[])} must be equal to the
 * range of selectable numbers which is equal to
 * {@link #getMaxValue()} - {@link #getMinValue()} + 1.

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

//do this once in onCreate and save the values list somewhere where you have access
final List<String> values = new ArrayList<>();
for (int i = 0; i < 10; ++i) {
    values.add(String.valueOf(i));
}
NumberPicker picker = (NumberPicker) findViewById(R.id.picker);
picker.setWrapSelectorWheel(false);


//do this every time you want to change the displayed values and set minValue and maxValue accordingly
//also make sure that you stay within the bounds of value
int minValue = 3;
int maxValue = 7;

final List<String> subValues = values.subList(minValue, maxValue + 1);
String[] subValuesArray = new String[subValues.size()];
subValuesArray = subValues.toArray(subValuesArray);
picker.setDisplayedValues(subValuesArray);
picker.setMinValue(0);
picker.setMaxValue(subValues.size() - 1);
person Bmuig    schedule 23.02.2017
comment
Не могли бы вы уточнить это? Почему это не решает проблему ОП? Разве вы также не предлагали, чтобы отображаемое значение изменялось всякий раз, когда изменяется минимальное / максимальное значение (может быть, я неправильно это понял)? - person Bmuig; 23.02.2017
comment
Мои извинения, я неправильно понял ваше предложение. Он работает так, как ожидалось. Простите за это! - person Eugen Martynov; 23.02.2017


для краткости на ответ @Bmuig просто вспомогательная функция:

private void configurePicker(NumberPicker picker, ArrayList<String> values, int minValue, int maxValue, int currentValue) {
    picker.setDisplayedValues(values) //to avoid out of bounds
    picker.setMinValue(minValue);
    picker.setMaxValue(maxValue);
    picker.setValue(currentValue);
    picker.setDisplayedValues((String[]) values.subList(minValue, maxValue + 1).toArray());
}
person Joe Maher    schedule 07.07.2017