AppCompatSpinner's entries not opening TimePic

2019-02-21 16:32发布

问题:

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.

回答1:

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>


回答2:

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.