How to create Spinner to show current and next 30 dates

4k Views Asked by At

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();
2

There are 2 best solutions below

8
erakitin On BEST ANSWER

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());
}
0
Blackbelt On

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.