javaandroiddateandroid-spinnercustom-datetimepicker

How to create Spinner to show current and next 30 dates


How can I create a date Spinner, which shows current date in EditText as default and future dates in Spinner (like, for next 30 days)

I used date picker in many apps, so I am familiar with date picker dialog but don't have any idea about date spinner.

Note
Please don't tell me How to style EditText as Spinner

EDITED: 1 AS RECOMMENDED BY @erakitin

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_date);

    Spinner spinnerDateIn = (Spinner) findViewById(R.id.spinnerDateIn);
    Spinner spinnerDateOut = (Spinner) findViewById(R.id.spinnerDateOut);       

    spinnerDateIn.setAdapter(new CalendarSpinnerAdapter(SpinnerDateActivity.this, 30));         

}

EDITED: 2 AS RECOMMENDED BY @erakitin in new update

CalendarSpinnerAdapter mSpinnerDateInAdapter = new CalendarSpinnerAdapter(SpinnerDateActivity.this, 30);
        spinnerDate.setAdapter(mSpinnerDateInAdapter);

        spinnerDate.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                spinnerDate.setSelection(position);
            }

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

            }
        });

Now, trying to get value of selected Item in String but getting: java.util.GregorianCalendar, where i am doing mistake ?

strDate = spinnerDate.getSelectedItem().toString();

Solution

  • There are a simple example of adapter for Spinner below.

    public class CalendarSpinnerAdapter extends BaseAdapter {
    
        private SimpleDateFormat mDateFormat = new SimpleDateFormat("d MMM yyyy");
    
        private LayoutInflater mInflater;
        private Calendar mCalendar;
        private int mDayCount;
        private int mLastRequestedDay = 0;
    
        public CalendarSpinnerAdapter(Context context, int dayCount) {
            mInflater = LayoutInflater.from(context);
            mDayCount = dayCount;
            mCalendar = Calendar.getInstance();
        }
    
        @Override
        public int getCount() {
            return mDayCount;
        }
    
        @Override
        public Calendar getItem(int position) {
            mCalendar.add(Calendar.DAY_OF_YEAR, position - mLastRequestedDay);
            mLastRequestedDay = position;
            return mCalendar;
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = mInflater.inflate(android.R.layout.simple_spinner_dropdown_item, parent, false);
            }
    
            Calendar item = getItem(position);
            ((TextView) convertView).setText(mDateFormat.format(item.getTimeInMillis()));
    
            return convertView;
        }
    
        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            return getView(position, convertView, parent);
        }
    }
    

    How to use it for display current date and next 29 days:

    mDateSpinner.setAdapter(new CalendarSpinnerAdapter(getActivity(), 30));
    

    UPD:

    We should add a parameter to adapter's constructor for setting the starting date:

    public CalendarSpinnerAdapter(Context context, Calendar startDate, int dayCount) {
        mInflater = LayoutInflater.from(context);
        mDayCount = dayCount;
        mCalendar = Calendar.getInstance();
        mCalendar.setTimeInMillis(startDate.getTimeInMillis());
    }
    

    Then add listener for spinnerDateIn where we can initialize the second spinner:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_date);
    
        Spinner spinnerDateIn = (Spinner) findViewById(R.id.spinnerDateIn);
        final Spinner spinnerDateOut = (Spinner) findViewById(R.id.spinnerDateOut);
    
        mSpinnerDateInAdapter = new CalendarSpinnerAdapter(SpinnerDateActivity.this, Calendar.getInstance(), 30);
        spinnerDateIn.setAdapter(mSpinnerDateInAdapter);
    
        spinnerDateIn.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                Calendar dateIn = Calendar.getInstance();
                dateIn.setTimeInMillis(mSpinnerDateInAdapter.getItem(position).getTimeInMillis());
                dateIn.add(Calendar.DAY_OF_YEAR, 1); // add one day
                mSpinnerDateOutAdapter = new CalendarSpinnerAdapter(SpinnerDateActivity.this, dateIn, 30);
                spinnerDateOut.setAdapter(mSpinnerDateOutAdapter);
            }
    
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
    
            }
        });
    }
    

    I didn't try this code but it should work.

    UPD2:

    spinnerDate.setSelection(position) returns Calendar class instance. If you want to get selected date as String you should format it. Try to use following method:

    private String getSelectedDateAsString(Spinner dateSpinner) {
        Calendar selectedDate = (Calendar) dateSpinner.getSelectedItem();
        return new SimpleDateFormat("d MMM yyyy").format(selectedDate.getTimeInMillis());
    }