Reputation: 382
I'm learning the basics of android programming and having some trouble with a NumberPicker.
I am close to what I want to have, the dialog opens and the hour and minute number pickers appear, but they do not have numbers above and below to scroll through. I also can't edit the numbers with the keyboard that pops up. I tried adding an onValueChange listener, but it didn't generate any events when I used the keyboard.
Can anyone offer advice on how to fix this? I've noticed so far that there are a lot of things I try to do with the widgets in certain activities or fragments that aren't supported in that specific class.
Below are snippets of the relevant code and images:
I have a class ClockActivity with two buttons:
...
public class ClockActivity extends ActionBarActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clock);
// Define gui objects
...
mWorkForTime = (Button)findViewById(R.id.work_for_time);
mBreakForTime = (Button)findViewById(R.id.break_for_time);
// Add listeners for the work for/break for buttons
mWorkForTime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Bring up the picker fragment
DialogFragment newFragment = TimePickerFragment.newInstance(R.string.work_title);
newFragment.show(getSupportFragmentManager(), "WorkTimePicker");
}
});
mBreakForTime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Bring up the picker fragment
DialogFragment newFragment = TimePickerFragment.newInstance(R.string.break_title);
newFragment.show(getSupportFragmentManager(), "BreakTimePicker");
}
});
...
The TimePickerFragment class extends the DialogFragment:
public class TimePickerFragment extends DialogFragment {
// Setup the time pickers
private NumberPicker mHourPicker;
private NumberPicker mMinutePicker;
public static TimePickerFragment newInstance(int title) {
TimePickerFragment fragment = new TimePickerFragment();
Bundle args = new Bundle();
args.putInt("title", title);
fragment.setArguments(args);
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
super.onCreateDialog(savedInstanceState);
int title = getArguments().getInt("title");
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = (View)inflater.inflate(R.layout.activity_time_picker, null);
// Initialize the pickers
mHourPicker = (NumberPicker)view.findViewById(R.id.hours_picker);
mMinutePicker = (NumberPicker)view.findViewById(R.id.minutes_picker);
mHourPicker.setMinValue(0);
mMinutePicker.setMinValue(0);
mHourPicker.setMaxValue(24);
mMinutePicker.setMaxValue(59);
Dialog alertDialog = new AlertDialog.Builder(getActivity())
.setTitle(title)
.setView(inflater.inflate(R.layout.activity_time_picker, null))
.setNegativeButton(R.string.negate,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
((ClockActivity) getActivity()).doNegativeTimeDialogClick();
}
})
.setPositiveButton(R.string.confirm,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
((ClockActivity) getActivity()).doPositiveTimeDialogClick();
}
})
.create();
return alertDialog;
}
}
Following is the XML for the DialogFragment view that is in
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/hours"
android:textSize="24sp"
android:textStyle="bold"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/minutes"
android:textSize="24sp"
android:textStyle="bold"/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<NumberPicker
android:id="@+id/hours_picker"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<NumberPicker
android:id="@+id/minutes_picker"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
Here is an image of the current operation:
https://i.sstatic.net/FqSoA.png
Here is what I'm looking to have:
http://www.i-programmer.info/images/stories/Core/Android/Pickers/ten.gif
Here is some output I see on the console when I try to edit the NumberPicker with the soft keyboard:
01-02 16:10:46.559 18438-18438/com.example.android.worktimer W/IInputConnectionWrapper﹕ beginBatchEdit on inactive InputConnection
01-02 16:10:46.569 18438-18438/com.example.android.worktimer W/IInputConnectionWrapper﹕ endBatchEdit on inactive InputConnection
Upvotes: 5
Views: 3461
Reputation: 1692
I've had the same problem trying to get the NumberPicker to work using a DialogFragment. None of the suggestion provided above worked for me. I will add, the problem isn't unique to using NumberPicker as I had the same problem using Spinner. My code looked pretty much like Burke9077, so I won't repeat it.
There's a number of issues that you'll run into, such as the findViewById does not work in the onCreateDialog. I thinks it's because the view isn't yet instantiated. I tried working around this problem by initializing the NumberPicker in the onCreateView. At least in that method I could get the onFindViewById to work, but it still didn't work setting min and max values for the NumberPicker. The short of it, I just couldn't get NumberPicker to work in a DialogFragment. Everything I was trying, just keep the code more obscured and too hard to understand. A coding principle of mine is stop making code work when its getting to hard to understand.
The solution for me was to altogether scrapped the notion of using a DialogFrament. I instead opted to build the dialog on the fly. Here's more or less what that looks like:
public Dialog show() {
AppCompatActivity activity = CoreAndroid.getActivity();
Context context = CoreAndroid.getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
// Get the layout inflater
LayoutInflater inflater = LayoutInflater.from(CoreAndroid.getContext());
ViewGroup viewGroup = activity.findViewById(android.R.id.content);
View dialogView = inflater.inflate(R.layout.log_filter_dialog, viewGroup, false);
builder.setView(dialogView);
builder.setPositiveButton(R.string.apply, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// sign in the user ...
}
})
.setNegativeButton(R.string.exit, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
dialog = builder.create();
initDialog(dialogView) // this method is where the NumberPicker and other
// controls in the dialog get initialized
dialog.show();
return dialog;
}
It's just a method in a class that creates the dialog and shows it. Once the builder.create method is called you can find the views in the dialog layout that you want to initialize by using dialogView.findViewId. It's so much simpler and easier to understand then trying to use DialogFragment. I got hooked on trying to use DialogFragment because other people provided it as a coding template. There may be a reason to use DialogFragment but for what I needed to do, it was too cumbersome and I wasn't able to get it to to do some simple things like initializing a control.
Upvotes: 2
Reputation: 1963
You have to provide the picker with array of what you are trying to select.
String[] myStringArray = new String[]{"a","b","c"};
mMinutePicker.setMinValue(0);
mMinutePicker.setMaxValue(myStringArray.length - 1);
mMinutePicker.setDisplayedValues(myStringArray);
And Change
Dialog alertDialog = new AlertDialog.Builder(getActivity()) .setTitle(title) .setView(inflater.inflate(R.layout.activity_time_picker, null))
to
Dialog alertDialog = new AlertDialog.Builder(getActivity()).setTitle(title).setView(view)
You are inflating the view again.
Upvotes: 3