3

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();
Sun
  • 6,768
  • 25
  • 76
  • 131
  • You can refer last answer from this post [Android spinner with date picker][1] [1]: http://stackoverflow.com/questions/9406920/android-spinner-with-date-picker-like-google-calendar-app – AndyN Feb 03 '14 at 12:08

2 Answers2

5

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());
}
erakitin
  • 11,437
  • 5
  • 44
  • 49
  • thank you so much :) I have accepted your answer and ticked as useful too, and will award you bounty after 5 hours.. this is the most easiest way of doing this ... Salute you, and one more thing - like i have selected 6 Jul 2015 in first spinner and now i want to show date from 7 Jul 2015 (again with next 30 days) in second spinner (just like hotel check in and check out) functionality .. I have posted activity code check above and please let me know where i have to make changes - place code in your new EDITED section – Sun Jul 01 '15 at 05:23
  • i don't have words to express my feeling and your talent bro :) in short you are the master, and i am eagerly waiting to reward you but i have to wait 1 more hour... – Sun Jul 01 '15 at 09:33
  • brother have a look at this issue please: http://stackoverflow.com/questions/28871921/add-weekly-event-to-calendar – Sun Jul 01 '15 at 10:48
  • @Sun l didn't work with Google Calendar. Sorry, can't help you with that issue. – erakitin Jul 01 '15 at 11:34
  • Issue in our Date Spinner, not getting selected item value in String format, check EDITED: 2 section for my updated code – Sun Jul 03 '15 at 06:43
  • hello friend, how can i show time in Spinner with 15 minutes from now only future time – Sun Oct 09 '15 at 05:54
  • Just change `mCalendar.add(Calendar.DAY_OF_YEAR, position - mLastRequestedDay);` to `mCalendar.add(Calendar.MINUTE, (position - mLastRequestedDay) * 15);` and pattern for SimpleDateFormat from "d MMM yyyy" to "hh:mm". – erakitin Oct 09 '15 at 08:43
  • i will give a try and revert you soon.. for now thank you so much – Sun Oct 09 '15 at 09:28
0

Spinner works with an Adapter. If you want to show in your spinner the date from today up to the end of the month you can do. Let's create a model class, with one can use to feed the Adapter,

  public class MyDateInterval {
    public String mDateString;
    public Date mDate;

    public MyDateInterval(String dateString, Date date) {
        mDateString = dateString;
        mDate = date;
    }

    @Override
    public String toString() {
        return mDateString;
    }
}

Now we define an ArrayList<MyDateInterval>, that we will fill up with the date you want to show:

ArrayList<MyDateInterval> items = new ArrayList<>();

Retrieve the end date on the format of your example:

SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy");
Calendar c = Calendar.getInstance();
c.set(Calendar.MONTH, 6);
c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
// for the sake of the example 31 Jul 2015
Date endDate = c.getTime();
Log.e(getClass().getSimpleName(), dateFormat.format(endDate));

Now we calculated the interval from today up to the end date

Calendar todayCalendar = Calendar.getInstance();
while(endDate.after(todayCalendar.getTime())) {
    items.add(new MyDateInterval(dateFormat.format(todayCalendar.getTime()), todayCalendar.getTime());
    todayCalendar.add(Calendar.DAY_OF_MONTH, 1);
 }

Now we all the pieces. You have to create the Adapter for the Spinner.

ArrayAdapter<MyDateInterval> dataAdapter = new ArrayAdapter<>(this,
                            android.R.layout.simple_spinner_item, items);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(dataAdapter);

and that should be all.

Blackbelt
  • 156,034
  • 29
  • 297
  • 305