Select multiple dates in Android DatePickerDialog
I have a requirement to select multiple dates from an Android DatePickerDialog. Below is my snippet. However, I can only choose one date. I've seen other libraries like https://github.com/square/android-times-square . But I'm more interested in native Android code.
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val currentDate = Calendar.getInstance()
val year = currentDate.get(Calendar.YEAR)
val month = currentDate.get(Calendar.MONTH)
val day = currentDate.get(Calendar.DAY_OF_MONTH)
val maxDate = Calendar.getInstance()
maxDate.add(Calendar.MONTH, 3)
val datePickerDialog = DatePickerDialog(activity, onDateSet, year, month, day)
datePickerDialog.datePicker.minDate = currentDate.timeInMillis
datePickerDialog.datePicker.maxDate = maxDate.timeInMillis
return datePickerDialog
}
source to share
Android does not support this feature until date. However, you can create your own calendar. I have the same requirement and I did it. Note that I did not allow the user to select a date. But users can choose their own dates. I created a snippet that only changes the months and so it changes the adapter like when the month changes.
public class CalendarFragment extends DialogFragment {
private final String TAG = CalendarFragment.class.getSimpleName();
private static CalendarFragment instance;
private View view;
private ImageView ivDecrementMonth, ivIncrementMonth;
private TextView btnOk, btnCancel;
public TextView tvMonthYear;
private int counter = 0;
private int year = 2017;
private static CalendarActivity INSTANCE;
private Calendar calendarMinimumDate, calendarMaximumDate;
private GridView gridCalendarView;
private ArrayList<EventDateSelectionBean> listEventDates;
private String from;
public static final String KEY_EVENT_DATES = "key event dates";
public static final String KEY_FROM = "key from";
public static final String FROM_ANNOUNCEMENT_ACTIVITY = "from announcement activity";
public static final String FROM_BOOKING_DIALOG = "from booking dialog";
private List<String> listMonths;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
WindowManager.LayoutParams wlmp = dialog.getWindow().getAttributes();
wlmp.gravity = Gravity.CENTER | Gravity.FILL_HORIZONTAL;
wlmp.dimAmount = 0.0F;
dialog.getWindow().setAttributes(wlmp);
dialog.getWindow().setWindowAnimations(R.style.DialogTheme);
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
return dialog;
}
//End of onCreateDialog()
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (view == null) {
instance = this;
view = inflater.inflate(R.layout.activity_calendar, container);
findViewsId();
setData();
setClickListeners();
}
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
return view;
}
//End of onCreateView()
private void findViewsId() {
ivDecrementMonth = (ImageView) view.findViewById(R.id.ivDecrementMonth);
ivIncrementMonth = (ImageView) view.findViewById(R.id.ivIncrementMonth);
gridCalendarView = (GridView) view.findViewById(R.id.calendar);
tvMonthYear = (TextView) view.findViewById(R.id.tvMonthYear);
btnOk = (TextView) view.findViewById(R.id.btnOk);
btnCancel = (TextView) view.findViewById(R.id.btnCancel);
}
//End of findViewsId()
private void setData() {
listMonths = Arrays.asList(getResources().getStringArray(R.array.months));
Bundle bundle = getArguments();
calendarMinimumDate = Calendar.getInstance();
calendarMinimumDate.setTimeInMillis(System.currentTimeMillis());
calendarMaximumDate = Calendar.getInstance();
calendarMaximumDate.setTimeInMillis(System.currentTimeMillis());
btnOk.setText(getString(R.string.ok));
btnCancel.setText(getString(R.string.cancel));
listEventDates = bundle.getParcelableArrayList(KEY_EVENT_DATES);
from = bundle.getString(KEY_FROM);
//setMinMaxDateCalendar();
counter = calendarMinimumDate.get(Calendar.MONTH);
year = calendarMinimumDate.get(Calendar.YEAR);
tvMonthYear.setText(listMonths.get(counter) + " " + year);
MyCalendarAdapter adapter = new MyCalendarAdapter(GoToTourActivity.getInstance(),
listEventDates, counter, year);
gridCalendarView.setAdapter(adapter);
}
//End of setData()
private void setClickListeners() {
btnOk.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (from.equals(FROM_ANNOUNCEMENT_ACTIVITY)) {
GoToTourActivity.getInstance().setDate(listEventDates);
} else if (from.equals(FROM_BOOKING_DIALOG)) {
BookDialogs.getInstance().setDate(listEventDates);
}
dismiss();
}
});
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
}
});
ivDecrementMonth.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (counter == 0) {
counter = listMonths.size() - 1;
year = year - 1;
} else {
counter--;
}
tvMonthYear.setText(listMonths.get(counter) + " " + year);
updateCalendar();
}
});
ivIncrementMonth.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (counter == (listMonths.size() - 1)) {
counter = 0;
year = year + 1;
} else {
counter++;
}
tvMonthYear.setText(listMonths.get(counter) + " " + year);
updateCalendar();
}
});
}
//End of setClickListeners()
private void updateCalendar() {
MyCalendarAdapter adapter = new MyCalendarAdapter(GoToTourActivity.getInstance(),
listEventDates, counter, year);
gridCalendarView.setAdapter(adapter);
}
//End of updateCalendar()
}
// Here is the layout of the Fragment Calendar
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.1"
android:background="#FFF"
android:gravity="center"
android:orientation="horizontal"
android:weightSum="1">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.2"
android:background="#FFF"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/llPrev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/margin">
<ImageButton
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="2dp"
android:padding="1dp"
android:src="@drawable/slide_right" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.6"
android:gravity="center">
<TextView
android:id="@+id/tvMonthYear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="DECEMBER 2017"
android:textAllCaps="false"
android:textColor="#000"
android:textSize="22dp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.2"
android:background="#FFF"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/llNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/margin">
<ImageButton
android:id="@+id/forw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:padding="1dp"
android:rotation="180"
android:src="@drawable/slide_right" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/llcalender"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.9"
android:background="#FFF">
<GridView
android:id="@+id/calgrid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="7">
</GridView>
</LinearLayout>
And the most important part is the Gridview adapter. Go through the code and try to figure out what's not bothering you. However, if you have problems. Please comment.
public MyCalendarAdapter(Context context, ArrayList<EventDateSelectionBean> listEvents, int month, int year) {
super();
this._context = context;
dateDefaultTextColor = context.getResources().getColor(R.color.calendar_date_default_text_color);
dateInEventTextColor = context.getResources().getColor(R.color.calendar_date_in_event_text_color);
dateInEventSelectedTextColor = context.getResources().getColor(R.color.calendar_date_in_event_selected_text_color);
this.list = new ArrayList<>();
Calendar calendar = Calendar.getInstance();
setCurrentDayOfMonth(calendar.get(Calendar.DAY_OF_MONTH));
setCurrentWeekDay(calendar.get(Calendar.DAY_OF_WEEK));
this.listEvents = listEvents;
currentMonth = month;
currentYear = year;
// Print Month
printMonth(month, year);
eventCalendar = Calendar.getInstance();
eventCalendar.setTimeInMillis(System.currentTimeMillis());
currentDayCalendar = Calendar.getInstance();
currentDayCalendar.setTimeInMillis(System.currentTimeMillis());
currentDayCalendar.set(Calendar.MONTH, currentMonth);
currentDayCalendar.set(Calendar.YEAR, currentYear);
}
private String getMonthAsString(int i) {
return months[i];
}
private int getNumberOfDaysOfMonth(int i) {
if (currentYear % 4 == 0 && i == 1) {
return daysOfMonth[i] + 1;
} else {
return daysOfMonth[i];
}
}
public String getItem(int position) {
return list.get(position);
}
@Override
public int getCount() {
return list.size();
}
private void printMonth(int mm, int yyyy) {
int trailingSpaces = 0;
int daysInPrevMonth = 0;
int prevMonth = 0;
int prevYear = 0;
int nextMonth = 0;
int nextYear = 0;
int currentMonth = mm/* - 1*/;
daysInMonth = getNumberOfDaysOfMonth(currentMonth);
// Gregorian Calendar : MINUS 1, set to FIRST OF MONTH
GregorianCalendar cal = new GregorianCalendar(yyyy, currentMonth, 1);
if (currentMonth == 11) {
prevMonth = currentMonth - 1;
daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
nextMonth = 0;
prevYear = yyyy;
nextYear = yyyy + 1;
} else if (currentMonth == 0) {
prevMonth = 11;
prevYear = yyyy - 1;
nextYear = yyyy;
daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
nextMonth = 1;
} else {
prevMonth = currentMonth - 1;
nextMonth = currentMonth + 1;
nextYear = yyyy;
prevYear = yyyy;
daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
}
int currentWeekDay = cal.get(Calendar.DAY_OF_WEEK) - 1;
trailingSpaces = currentWeekDay;
// Trailing Month days
for (int i = 0; i < trailingSpaces; i++) {
list.add(String.valueOf((daysInPrevMonth - trailingSpaces + DAY_OFFSET) + i) + "-GREY" + "-" + getMonthAsString(prevMonth) + "-" + prevYear);
}
// Current Month Days
for (int i = 1; i <= daysInMonth; i++) {
if (i == getCurrentDayOfMonth())
list.add(String.valueOf(i) + "-BLUE" + "-" + getMonthAsString(currentMonth) + "-" + yyyy);
else
list.add(String.valueOf(i) + "-WHITE" + "-" + getMonthAsString(currentMonth) + "-" + yyyy);
}
// Leading Month days
for (int i = 0; i < list.size() % 7; i++) {
list.add(String.valueOf(i + 1) + "-GREY" + "-" + getMonthAsString(nextMonth) + "-" + nextYear);
}
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Blue - Current Day
//White - Current Month
//Grey - Next Month
final ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.calendar_day_gridcell, parent, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// ACCOUNT FOR SPACING
String[] day_color = list.get(position).split("-");
String theday = day_color[0];
// Set the Day GridCell
holder.btnDate.setText(theday);
if (day_color[1].equals("WHITE") || day_color[1].equals("BLUE")) { //For Current Month
holder.btnDate.setTextColor(dateDefaultTextColor);
holder.btnDate.setBackgroundResource(R.drawable.date_default_bg);
currentDayCalendar.set(Calendar.DAY_OF_MONTH, Integer.valueOf(theday));
for (int i = 0; i < listEvents.size(); i++) {
EventDateSelectionBean eventDate = listEvents.get(i);
setDataInEventCalendar(eventDate.getDate());
if(Commons.checkDateEquality(currentDayCalendar, eventCalendar)) {
final EventDateSelectionBean finalEventDate = eventDate;
if(finalEventDate.isSelected()) {
holder.btnDate.setBackgroundResource(R.drawable.date_selected_bg);
holder.btnDate.setTextColor(dateInEventSelectedTextColor);
} else {
holder.btnDate.setBackgroundResource(R.drawable.date_unselected);
holder.btnDate.setTextColor(dateInEventTextColor);
}
holder.btnDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(finalEventDate.isSelected()) {
finalEventDate.setSelected(false);
holder.btnDate.setBackgroundResource(R.drawable.date_unselected);
holder.btnDate.setTextColor(dateInEventTextColor);
} else {
finalEventDate.setSelected(true);
holder.btnDate.setBackgroundResource(R.drawable.date_selected_bg);
holder.btnDate.setTextColor(dateInEventSelectedTextColor);
}
}
});
break;
}
}
} else { //For Previous and next month dates
holder.btnDate.setAlpha(0.4f);
holder.btnDate.setBackgroundResource(R.drawable.date_default_bg);
//holder.btnDate.setVisibility(View.INVISIBLE);
holder.llBtnParent.setVisibility(View.INVISIBLE);
}
if (position == list.size() - 1) {
//Set Default data
}
return convertView;
}
//End of getView()
public class ViewHolder {
Button btnDate;
LinearLayout llBtnParent;
public ViewHolder(View view) {
btnDate = (Button) view.findViewById(R.id.calendar_day_gridcell);
llBtnParent = (LinearLayout) view.findViewById(R.id.llBtnParent);
}
}
public int getCurrentDayOfMonth() {
return currentDayOfMonth;
}
private void setCurrentDayOfMonth(int currentDayOfMonth) {
this.currentDayOfMonth = currentDayOfMonth;
}
public void setCurrentWeekDay(int currentWeekDay) {
this.currentWeekDay = currentWeekDay;
}
private void setDataInEventCalendar(String date) {
String splittedDate[] = date.split("-");
eventCalendar.set(Calendar.YEAR, Integer.valueOf(splittedDate[0]));
eventCalendar.set(Calendar.MONTH, (Integer.valueOf(splittedDate[1]) - 1));
eventCalendar.set(Calendar.DAY_OF_MONTH, Integer.valueOf(splittedDate[2]));
}
//End of setDataInEventCalendar()
}
Adapter diagram
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_margin="1dp"
android:background="@android:color/transparent"
android:id="@+id/llBtnParent">
<LinearLayout
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_margin="1dp"
android:background="@drawable/day_calendar"
android:padding="1dp"
android:gravity="center">
<com.yaashvi.placeandpeople.customviews.AttendanceButton
android:id="@+id/calendar_day_gridcell"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="40dp"
android:layout_height="40dp"
android:text="1"
android:gravity="left"
android:paddingLeft="2dp"
android:textSize="12sp"/>
</LinearLayout>
The result will be like this.
source to share