问题
In activity_main.xml
:
<NumberPicker
android:id="@+id/numberPicker1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView2"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp" />
In MainActivity.java
inside the oncreate
:
NumberPicker numberPicker1 = (NumberPicker) findViewById(R.id.numberPicker1);
numberPicker1.setMinValue(1);
numberPicker1.setMaxValue(20);
When I edit the value with the keyboard, the value that I get programmatically doesn't change, but if I press +
then -
it works.
How can I make it work without having to press +
and -
?
EDIT :
I created a new Project with the code of Melih Altıntaş and it displayed a whole new numberpicker!! (The one where you slide with your finger and can't enter text). Then I compared with my real project and I saw android:theme="@android:style/Theme.NoTitleBar"
. I added it in the new project and then the numberpicker became the one I was used to.
回答1:
The NumberPicker
wasn't designed for that interaction. When you change the value with the keyboard you're making changes directly to a widget from the NumberPicker
and the widget itself doesn't see this change so this is why you end up with the last stored value. To get around this you'll need some hacky code, which isn't really recommended, because you'll need to access the underlying EditText
(assuming that the phone maker didn't changed this in the first place):
private EditText findInput(ViewGroup np) {
int count = np.getChildCount();
for (int i = 0; i < count; i++) {
final View child = np.getChildAt(i);
if (child instanceof ViewGroup) {
findInput((ViewGroup) child);
} else if (child instanceof EditText) {
return (EditText) child;
}
}
return null;
}
and then you'll use this code to set a TextWatcher
on the found EditText
to see when it's manually modified(and let the NumberPicker
know about this change):
EditText input = findInput(np);
TextWatcher tw = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {}
@Override
public void afterTextChanged(Editable s) {
if (s.toString().length() != 0) {
Integer value = Integer.parseInt(s.toString());
if (value >= np.getMinValue()) {
np.setValue(value);
}
}
}
};
input.addTextChangedListener(tw);
Another option would be to make your own implementation of the NumberPicker
widget and insert the functionality you target.
回答2:
If anyone wants a simple workaround, just add the below code before saving the value.
numberPicker.clearFocus();
回答3:
You have to press the Done
button for the value to programmatically change.
回答4:
NumberPicker np = (NumberPicker) findViewById(R.id.numberPicker1);
String[] nums = new String[20];
for(int i=0; i<nums.length; i++)
nums[i] = Integer.toString(i);
np.setMinValue(1);
np.setMaxValue(20);
np.setWrapSelectorWheel(false);
np.setDisplayedValues(nums);
np.setValue(1);
回答5:
I see that you already have an answer, however this may be useful to others. You can extend android.widget.NumberPicker and make your own where you can configure the EditText. As you type on the soft keyboard, the value of your NumberPicker is immediately set to the value you're typing.
public class MyNumberPicker extends android.widget.NumberPicker {
private EditText eText;
public MyNumberPicker(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void addView(View child) {
super.addView(child);
initEditText(child);
}
@Override
public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) {
super.addView(child, index, params);
initEditText(child);
}
@Override
public void addView(View child, android.view.ViewGroup.LayoutParams params) {
super.addView(child, params);
initEditText(child);
}
public void initEditText(View view){
if(view instanceof EditText){
EditText eText = (EditText) view;
eText.addTextChangedListener(new TextWatcher(){
@Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
try{
int num = Integer.parseInt(s.toString());
setValue(num); //this line changes the value of your numberpicker
}catch(NumberFormatException E){
//do your catching here
}
}});
}
}
}
In your XML-file you put the following:
<com.mypackage.MyNumberPicker
android:id="@+id/numberPicker1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
回答6:
the reason why it doesn't work it's because if you look at the implementation of setValue in NumberPicker, it calls another method setValueInternal(int, boolean) which takes 2 parameters the new value and of course the bugger boolean which is representing whether it should notify the UI of any change or not. And guess what, in setValue the boolean goes always with false. Godammit. But there is one more trick I see that the validateInputTextView actually does it correctly, and it invokes when the edit text has no focus. maybe at the right time clearing the focus will do what is supposed to do.
来源:https://stackoverflow.com/questions/18944997/numberpicker-doesnt-work-with-keyboard