Burke9077
Burke9077

Reputation: 382

NumberPicker not working inside DialogFragment

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

Answers (2)

Tom Rutchik
Tom Rutchik

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

Farooq Arshed
Farooq Arshed

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

Related Questions