Как сбросить данные NumberPicker
Я использую два NumberPicker для отображения провинции (mProvincePicker
) и город (mCityPicker
) данные в моем приложении. Когда пользователь изменяет данные провинции, данные города должны быть изменены соответствующим образом. Я сбросил mCityPicker
данные в NumberPicker.onValueChange(NumberPicker picker, int oldVal, int newVal)
, Но это не работает хорошо и java.lang.ArrayIndexOutOfBoundsException
вылетает приложение
Вот мой код:
public class AreaPickerDialog extends Dialog implements OnValueChangeListener, OnClickListener {
static final String TAG = "AreaPickerDialog";
private NumberPicker mProvincePicker;
private NumberPicker mCityPicker;
private Button mCancelBtn;
private Button mOKBtn;
private AreaUtil mAreaUtil;
private List<Area> mProvinces;
private int mAreaId;
private int mProvinceId;
private Handler mHandler;
public AreaPickerDialog(Context context, Handler handler, int areaId) {
super(context);
mAreaUtil = AreaUtil.getInstance();
mProvinces = mAreaUtil.getProvinceList();
mAreaId = areaId;
mProvinceId = mAreaUtil.getProvinceIdByAreaId(areaId);
mHandler = handler;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_area_picker);
mProvincePicker = (NumberPicker) findViewById(R.id.np_province);
mCityPicker = (NumberPicker) findViewById(R.id.np_city);
mCancelBtn = (Button) findViewById(R.id.btn_cancel);
mOKBtn = (Button) findViewById(R.id.btn_ok);
initProvinceData();
mProvincePicker.setOnValueChangedListener(this);
mCityPicker.setOnValueChangedListener(this);
mCancelBtn.setOnClickListener(this);
mOKBtn.setOnClickListener(this);
}
private void initProvinceData() {
if (mProvinces != null && mProvinces.size() > 0) {
String[] provinceNames = new String[mProvinces.size()];
for (int i = 0; i < provinceNames.length; i++) {
provinceNames[i] = mProvinces.get(i).getProvincename();
}
mProvincePicker.setDisplayedValues(provinceNames );
mProvincePicker.setMinValue(1);
mProvincePicker.setMaxValue(mProvinces.size());
}
mProvincePicker.setValue(mProvinceId);
initCityData(mProvincePicker.getValue());
}
private void initCityData(int provinceId) {
List<Arealist> cities = mAreaUtil.getCityListOfProvince(provinceId);
if (cities != null && cities.size() > 0) {
try {
int min = Integer.parseInt(cities.get(0).getAreaid());
int max = Integer.parseInt(cities.get(cities.size() -1).getAreaid());
String[] cityNames = new String[cities.size()];
for (int i = 0; i < cityNames.length; i++) {
cityNames[i] = cities.get(i).getName();
}
mCityPicker.setValue(0);
mCityPicker.setDisplayedValues(cityNames);
mCityPicker.setMinValue(min);
mCityPicker.setMaxValue(max);
} catch (NumberFormatException e) {
ILog.e(TAG, e.getMessage(), e);
}
}
}
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
if (mProvincePicker.equals(picker)) {
initCityData(mProvincePicker.getValue());
} else if (mCityPicker.equals(picker)) {
mAreaId = mCityPicker.getValue();
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_cancel:
dismiss();
break;
case R.id.btn_ok:
Message msg = mHandler.obtainMessage(MineActivity.MSG_UPDATE_AREA);
msg.arg1 = mAreaId;
msg.sendToTarget();
dismiss();
break;
default:
break;
}
}
}
И трассировка ошибок logcat:
12-30 23:09:26.560: E/InputEventReceiver(5620): Exception dispatching input event.
12-30 23:09:26.560: W/dalvikvm(5620): threadid=1: thread exiting with uncaught exception (group=0x41ddf438)
12-30 23:09:26.580: E/AndroidRuntime(5620): FATAL EXCEPTION: main
12-30 23:09:26.580: E/AndroidRuntime(5620): java.lang.ArrayIndexOutOfBoundsException: length=14; index=15
12-30 23:09:26.580: E/AndroidRuntime(5620): at net.simonvt.numberpicker.NumberPicker.updateInputTextView(NumberPicker.java:1840)
12-30 23:09:26.580: E/AndroidRuntime(5620): at net.simonvt.numberpicker.NumberPicker.setDisplayedValues(NumberPicker.java:1423)
12-30 23:09:26.580: E/AndroidRuntime(5620): at com.meishai.app.dialog.AreaPickerDialog.initCityData(AreaPickerDialog.java:88)
12-30 23:09:26.580: E/AndroidRuntime(5620): at com.meishai.app.dialog.AreaPickerDialog.onValueChange(AreaPickerDialog.java:100)
12-30 23:09:26.580: E/AndroidRuntime(5620): at net.simonvt.numberpicker.NumberPicker.notifyChange(NumberPicker.java:1855)
12-30 23:09:26.580: E/AndroidRuntime(5620): at net.simonvt.numberpicker.NumberPicker.setValueInternal(NumberPicker.java:1641)
12-30 23:09:26.580: E/AndroidRuntime(5620): at net.simonvt.numberpicker.NumberPicker.scrollBy(NumberPicker.java:1106)
12-30 23:09:26.580: E/AndroidRuntime(5620): at net.simonvt.numberpicker.NumberPicker.onTouchEvent(NumberPicker.java:886)
12-30 23:09:26.580: E/AndroidRuntime(5620): at android.view.View.dispatchTouchEvent(View.java:7127)
12-30 23:09:26.580: E/AndroidRuntime(5620): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2170)
12-30 23:09:26.580: E/AndroidRuntime(5620): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1905)
12-30 23:09:26.580: E/AndroidRuntime(5620): at net.simonvt.numberpicker.NumberPicker.dispatchTouchEvent(NumberPicker.java:944)
....
Я сбрасываю minValue,maxValue and DisplayedValues
сбросить NumberPicker
данные и не работают, так что это правильный путь?
4 ответа
Хорошо, я смотрю на исходный код NumberPicker.java, обнаружив, что он будет пересчитывать данные и обновлять пользовательский интерфейс в setMinValue(int minValue)
а также setMaxValue(int minValue)
, Когда установлено новое minValue, оно будет вычисляться с использованием нового minValue и старого maxValue, после чего произошла ошибка.
Итак, я модифицирую немного NumberPicker
: установить значение только в setMinValue(int minValue)
а также setMaxValue(int maxValue)
и обновить пользовательский интерфейс в setDisplayedValues(String[] displayedValues)
, Когда данные NumberPicker
изменилось, просто сбросьте значения minValue, maxVaule и отображаемые значения. Обратите внимание, что setDisplayedValues(String[] displayedValues)
ДОЛЖЕН быть вызван в конце концов.
Вот что я модифицировал:
NumberPicker.java
:
public void setMinValue(int minValue) {
if (mMinValue == minValue) {
return;
}
if (minValue < 0) {
throw new IllegalArgumentException("minValue must be >= 0");
}
mMinValue = minValue;
if (mMinValue > mValue) {
mValue = mMinValue;
}
//boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length;
//setWrapSelectorWheel(wrapSelectorWheel);
//initializeSelectorWheelIndices();
//updateInputTextView();
//tryComputeMaxWidth();
invalidate();
}
public void setMaxValue(int maxValue) {
if (mMaxValue == maxValue) {
return;
}
if (maxValue < 0) {
throw new IllegalArgumentException("maxValue must be >= 0");
}
mMaxValue = maxValue;
if (mMaxValue < mValue) {
mValue = mMaxValue;
}
//boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length;
//setWrapSelectorWheel(wrapSelectorWheel);
//initializeSelectorWheelIndices();
//updateInputTextView();
//tryComputeMaxWidth();
invalidate();
}
public void setDisplayedValues(String[] displayedValues) {
if (mDisplayedValues == displayedValues) {
return;
}
mDisplayedValues = displayedValues;
if (mDisplayedValues != null) {
// Allow text entry rather than strictly numeric entry.
mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
} else {
mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
}
boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length;
setWrapSelectorWheel(wrapSelectorWheel);
updateInputTextView();
initializeSelectorWheelIndices();
tryComputeMaxWidth();
}
AreaPickerDialog.java
:
private void initCityData(int provinceId) {
List<Arealist> cities = mAreaUtil.getCityListOfProvince(provinceId);
if (cities != null && cities.size() > 0) {
try {
int min = Integer.parseInt(cities.get(0).getAreaid());
int max = Integer.parseInt(cities.get(cities.size() -1).getAreaid());
String[] cityNames = new String[cities.size()];
for (int i = 0; i < cityNames.length; i++) {
cityNames[i] = cities.get(i).getName();
}
mCityPicker.setMinValue(min);
mCityPicker.setMaxValue(max);
mCityPicker.setDisplayedValues(cityNames);
} catch (NumberFormatException e) {
ILog.e(TAG, e.getMessage(), e);
}
}
}
Это уродливое, но рабочее решение.
Проверить на звонок setDisplayedValues(null)
до setMaxValue
в onClick.
Ссылка: /questions/40519192/vyibor-nomera-s-dinamicheskim-spiskom/40519198#40519198
У меня та же проблема, и я исправил ее без изменений NumberPicker.java
, Вот код для вашей справки.
private void initCityData(int provinceId) {
List<Arealist> cities = mAreaUtil.getCityListOfProvince(provinceId);
if (cities != null && cities.size() > 0) {
try {
int min = Integer.parseInt(cities.get(0).getAreaid());
int max = Integer.parseInt(cities.get(cities.size() -1).getAreaid());
String[] cityNames = new String[cities.size()];
for (int i = 0; i < cityNames.length; i++) {
cityNames[i] = cities.get(i).getName();
}
int maxV = mCityPicker.getMaxValue();
if (max> maxV){
mCityPicker.setMinValue(min);
mCityPicker.setValue(0);
mCityPicker.setDisplayedValues(cityNames);
mCityPicker.setMaxValue(max);
}else{
mCityPicker.setMinValue(min);
mCityPicker.setValue(0);
mCityPicker.setMaxValue(max);
mCityPicker.setDisplayedValues(cityNames);
}
} catch (NumberFormatException e) {
ILog.e(TAG, e.getMessage(), e);
}
}
}
Просто установите для displayValues значение null перед сбросом средства выбора номера, как показано ниже:
pickerWard.displayedValues = null
pickerWard.maxValue = values.size - 1
pickerWard.displayedValues = values
Ищем код используемого NumberPicker:
private boolean updateInputTextView() {
/*
* If we don't have displayed values then use the current number else
* find the correct value in the displayed values for the current
* number.
*/
String text = (mDisplayedValues == null) ? formatNumber(mValue)
: mDisplayedValues[mValue - mMinValue];
вы можете увидеть, что он использует mMinValue, прежде чем вызывать setMinValue.
Попробуйте установить minValue и maxValue, прежде чем устанавливать отображаемые значения.