8

I have the following as AppCompatSpinner's entries:

<string-array name="startTimeList">
    <item>Now</item>
    <item>Pick a time..</item>
</string-array>

Upon selecting Pick a time.., a TimePickerDialog is opened and the user is allowed to choose a time. Here's how:

startTimeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
//                startTimeString = adapterView.getItemAtPosition(i).toString();
                DateFormat currentDateFormat = new SimpleDateFormat("HH:mm:ss");
                userAvailableTimeInSF = currentDateFormat.format(new Date());

                final TextView startTimeSpinnerTV = (TextView) adapterView.getSelectedView();
                startTimeSpinnerTV.setText(userAvailableTimeInSF);

                switch (i) {
                    case 0:

                        userAvailableTimeInSF = currentDateFormat.format(new Date());
                        startTimeSpinnerTV.setText("Now");
                        break;

                    default:

                        final Calendar c = Calendar.getInstance();
                        mHour = c.get(Calendar.HOUR_OF_DAY);
                        mMinute = c.get(Calendar.MINUTE);

                        TimePickerDialog timePickerDialog = new TimePickerDialog(PostSportRequest.this,
                                new TimePickerDialog.OnTimeSetListener() {

                                    @Override
                                    public void onTimeSet(TimePicker view, int hourOfDay,
                                                          int minute) {

                                        Calendar date = Calendar.getInstance();
                                        date.set(Calendar.HOUR_OF_DAY, hourOfDay);
                                        date.set(Calendar.MINUTE, minute);
                                        date.set(Calendar.AM_PM, date.get(Calendar.AM_PM));

                                        showTime(hourOfDay, minute);

                                        userAvailableTimeInSF = new SimpleDateFormat("HH:mm:ss").format(date.getTime());
                                        startTimeSpinnerTV.setText(userAvailableTimeAMPM);

                                        Toast.makeText(getBaseContext(), "userAvailableTimeInSF: " + userAvailableTimeInSF, Toast.LENGTH_SHORT).show();

                                    }
                                }, mHour, mMinute, false);
                        timePickerDialog.show();
                        break;
                }

            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });

Upon selecting Pick a time.. the first time, TimePickerDialog is successfully opened and the chosen time is shown but when I choose it again or click on it again, nothing happens!

I don't know why!

Please let me know how can I get the TimePickerDialog opened and chose the time no matter how many times I select/click it.

Hammad Nasir
  • 2,681
  • 6
  • 44
  • 120
  • @SuryaPrakashKushawah bro, I have explained as clearly as I can in the question. See this line: "Upon selecting Pick a time.. the first time, TimePickerDialog is successfully opened and the chosen time is shown but when I choose it again or click on it again, nothing happens!" – Hammad Nasir Dec 21 '16 at 08:29
  • What is `i` ? and are you getting Toast message on second selection ? – ρяσѕρєя K Dec 21 '16 at 08:52
  • @ρяσѕρєяK `int i` is a parameter in `onItemSelected()` and yes, I get the `Toast` message first time but then if without selecting `case 0` first I select `case 1` again, nothing happens! As described in the answer below by @MarcinJedynak His approach didn't worked for me! – Hammad Nasir Dec 21 '16 at 08:56
  • @HammadNasir: Ok then change `case 1:` to `default:` and check getting Dialog every time excluding 0 – ρяσѕρєя K Dec 21 '16 at 08:58
  • @ρяσѕρєяK it didn't helped! Please see the edited question and also have a look at Marcin's answer below. He has a good reason about why is this happening. – Hammad Nasir Dec 21 '16 at 09:06
  • @HammadNasir: Then add "Select time..." as first default item and hide it on opening of Spinner – ρяσѕρєя K Dec 21 '16 at 09:09
  • I know its late, but you can check this answer: http://stackoverflow.com/a/11323043/2798289 – Govind Dec 21 '16 at 14:29

2 Answers2

6

Follow these steps:

Create a custom spinner class

    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.Spinner;

    public class SpinnerOnSameSelection extends Spinner {
        OnItemSelectedListener listener;
        private AdapterView<?> lastParent;
        private View lastView;
        private long lastId;

        public SpinnerOnSameSelection(Context context, AttributeSet attrs) {
            super(context, attrs);
            // TODO Auto-generated constructor stub
            initlistner();
        }

        @Override
        public void setSelection(int position) {
            if (position == getSelectedItemPosition() && listener != null) {
                listener.onItemSelected(lastParent, lastView, position, lastId);
            } else {
                super.setSelection(position);
            }

        }

        private void initlistner() {
            // TODO Auto-generated method stub
            super.setOnItemSelectedListener(new OnItemSelectedListener() {

                @Override
                public void onItemSelected(AdapterView<?> parent, View view,
                                           int position, long id) {
                    // TODO Auto-generated method stub
                    lastParent = parent;
                    lastView = view;
                    lastId = id;
                    if (listener != null) {
                        listener.onItemSelected(parent, view, position, id);
                    }
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {
                    // TODO Auto-generated method stub
                    if (listener != null) {
                        listener.onNothingSelected(parent);
                    }
                }
            });

        }

        public void setOnItemSelectedEvenIfUnchangedListener(
                OnItemSelectedListener listener) {
            this.listener = listener;
        }

}

Create onItemSelectedListener in your activity

private AdapterView.OnItemSelectedListener listener;

 listener = new AdapterView.OnItemSelectedListener() {

            @Override
            public void onItemSelected(AdapterView<?> adapterView, View arg1,
                                       int i, long arg3) {

                //startTimeString = adapterView.getItemAtPosition(i).toString();
                DateFormat currentDateFormat = new SimpleDateFormat("HH:mm:ss");
                userAvailableTimeInSF = currentDateFormat.format(new Date());

                final TextView startTimeSpinnerTV = (TextView) adapterView.getSelectedView();
                startTimeSpinnerTV.setText(userAvailableTimeInSF);

                switch (i) {
                    case 0:

                        // userAvailableTimeInSF = currentDateFormat.format(new Date());
                        startTimeSpinnerTV.setText("Now");
                        break;

                    case 1:

                        final Calendar c = Calendar.getInstance();
                        mHour = c.get(Calendar.HOUR_OF_DAY);
                        mMinute = c.get(Calendar.MINUTE);

                        TimePickerDialog timePickerDialog = new TimePickerDialog(MainActivity.this,
                                new TimePickerDialog.OnTimeSetListener() {

                                    @Override
                                    public void onTimeSet(TimePicker view, int hourOfDay,
                                                          int minute) {

                                        Calendar date = Calendar.getInstance();
                                        date.set(Calendar.HOUR_OF_DAY, hourOfDay);
                                        date.set(Calendar.MINUTE, minute);
                                        date.set(Calendar.AM_PM, date.get(Calendar.AM_PM));

                                        //showTime(hourOfDay, minute);

                                       /* userAvailableTimeInSF = new SimpleDateFormat("HH:mm:ss").format(date.getTime());
                                        startTimeSpinnerTV.setText(userAvailableTimeAMPM);*/

                                        Toast.makeText(getBaseContext(), "userAvailableTimeInSF: " + userAvailableTimeInSF, Toast.LENGTH_SHORT).show();

                                    }
                                }, mHour, mMinute, false);
                        timePickerDialog.show();
                        break;
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
                // TODO Auto-generated method stub

            }
        };
}

Add the listener object to custom spinner method

SpinnerOnSameSelection startTimeSpinner;

in onCreate(): startTimeSpinner = (SpinnerOnSameSelection) findViewById(R.id.idOfItemInXml);

startTimeSpinner.setOnItemSelectedEvenIfUnchangedListener(listener);

In Your xml File

<your_package_name.SpinnerOnSameSelection
    android:id="@+id/startTimeSpinner"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:layout_alignParentBottom="true"
    android:entries="@array/mList">
</your_package_name.SpinnerOnSameSelection>
Hammad Nasir
  • 2,681
  • 6
  • 44
  • 120
Ronak Gadhia
  • 466
  • 4
  • 11
3

Spinner (or actually AdapterView, its superclass), fires OnItemSelectedListener only when the selection changes.

When your user selects "Pick a time..." Spinner assumes it is a selected option, and won't call the listener anymore if it is selected again. You can however notice, that if "Pick a time..." is selected, then "Now" and then "Pick a time...", the dialog appears.

I would recommend against using Spinner in your case (and doing some weird shit with the selected view). You can simply accomplish the same with TextView that displays the selected time and two buttons - one to show the dialog and one to reset the time to now.

Marcin Jedynak
  • 3,079
  • 2
  • 16
  • 19
  • I need to use the `Spinner`. Please let me know how to achieve it using it only. – Hammad Nasir Nov 22 '16 at 18:14
  • 1
    Maybe add an additional option with your selected time. When the user picks the time, just change the text of your additional option and programmatically select it (`setSelection(int)`). That way "Pick a time..." will be always treated as newly selected. – Marcin Jedynak Nov 22 '16 at 18:25
  • User can select any time he wants, how many other options can I add? There can be a lot of possibilities! – Hammad Nasir Nov 23 '16 at 02:31