Android实现日历控件示例代码
做的是一个酒店的项目,可以选择入住和离开的日期。声明为了省事在网上找的资料,自己修改的逻辑,希望对需要的朋友有帮助。喜欢的给个好评。谢谢啦!祝生活愉快!
先上图
第一步,搭建布局xml
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/days_detail" android:gravity="center" android:padding="16dp" android:text="选择住店离店日期" android:textColor="@color/white" android:textSize="18sp" /> <ImageView android:id="@+id/back_to_up" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:src="@drawable/backto" /> </FrameLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <View android:layout_width="match_parent" android:layout_height="30dp" android:background="@color/days_detail" /> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:layout_marginTop="20dp" android:padding="10dp" app:cardCornerRadius="10dp" app:cardElevation="16dp"> <LinearLayout android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" /> </android.support.v7.widget.CardView> </FrameLayout> </LinearLayout> </ScrollView>
第二部在编写逻辑
LinearLayout ll; MyCalendar c1; Date date; String nowday; long nd = 1000 * 24L * 60L * 60L;//一天的毫秒数 SimpleDateFormat simpleDateFormat, sd1, sd2; SharedPreferences sp; SharedPreferences.Editor editor; private String inday, outday//日期 sp_inday, sp_outday;//周几 Activity extends BaseActivity implements MyCalendar.OnDaySelectListener {
继承BaseActivity实现点击日历的监听回调
private void init() { List<String> listDate = getDateList(); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); for (int i = 0; i < listDate.size(); i++) { c1 = new MyCalendar(this); c1.setLayoutParams(params); Date date = null; try { date = simpleDateFormat.parse(listDate.get(i)); } catch (ParseException e) { e.printStackTrace(); } if (!"".equals(sp_inday)) { c1.setInDay(sp_inday); } if (!"".equals(sp_outday)) { c1.setOutDay(sp_outday); } c1.setTheDay(date); c1.setOnDaySelectListener(this); ll.addView(c1); } } @Override public void onDaySelectListener(View view, String date) { //若日历日期小于当前日期,或日历日期-当前日期超过三个月,则不能点击 try { if (simpleDateFormat.parse(date).getTime() < simpleDateFormat.parse(nowday).getTime()) { return; } long dayxc = (simpleDateFormat.parse(date).getTime() - simpleDateFormat.parse(nowday).getTime()) / nd; if (dayxc > 90) { return; } } catch (ParseException e) { e.printStackTrace(); } //若以前已经选择了日期,则在进入日历后会显示以选择的日期,该部分作用则是重新点击日历时,清空以前选择的数据(包括背景图案) if (!"".equals(sp_inday)) { c1.viewIn.setBackgroundColor(Color.WHITE); ((TextView) c1.viewIn.findViewById(R.id.tv_calendar_day)).setTextColor(Color.BLACK); ((TextView) c1.viewIn.findViewById(R.id.tv_calendar)).setText(""); } if (!"".equals(sp_outday)) { c1.viewOut.setBackgroundColor(Color.WHITE); ((TextView) c1.viewOut.findViewById(R.id.tv_calendar_day)).setTextColor(Color.BLACK); ((TextView) c1.viewOut.findViewById(R.id.tv_calendar)).setText(""); } String dateDay = date.split("-")[2]; if (Integer.parseInt(dateDay) < 10) { dateDay = date.split("-")[2].replace("0", ""); } TextView textDayView = (TextView) view.findViewById(R.id.tv_calendar_day); TextView textView = (TextView) view.findViewById(R.id.tv_calendar); view.setBackgroundColor(Color.parseColor("#33B5E5")); textDayView.setTextColor(Color.WHITE); if (null == inday || inday.equals("")) { textDayView.setText(dateDay); textView.setText("入住"); inday = date; } else { if (inday.equals(date)) { view.setBackgroundColor(Color.WHITE); textDayView.setText(dateDay); textDayView.setTextColor(Color.BLACK); textView.setText(""); inday = ""; } else { try { if (simpleDateFormat.parse(date).getTime() < simpleDateFormat.parse(inday).getTime()) { view.setBackgroundColor(Color.WHITE); textDayView.setTextColor(Color.BLACK); Toast.makeText(CalendarActivity.this, "离开日期不能小于入住日期", Toast.LENGTH_SHORT).show(); return; } } catch (ParseException e) { e.printStackTrace(); } textDayView.setText(dateDay); textView.setText("离开"); outday = date; editor.putString("dateIn", inday); editor.putString("dateOut", outday); editor.commit(); finish(); } } } //根据当前日期,向后数三个月(若当前day不是1号,为满足至少90天,则需要向后数4个月) @SuppressLint("SimpleDateFormat") public List<String> getDateList() { List<String> list = new ArrayList<String>(); Date date = new Date(); int nowMon = date.getMonth() + 1; String yyyy = sd1.format(date); String dd = sd2.format(date); if (nowMon == 9) { list.add(simpleDateFormat.format(date)); list.add(yyyy + "-10-" + dd); list.add(yyyy + "-11-" + dd); if (!dd.equals("01")) { list.add(yyyy + "-12-" + dd); } } else if (nowMon == 10) { list.add(yyyy + "-10-" + dd); list.add(yyyy + "-11-" + dd); list.add(yyyy + "-12-" + dd); if (!dd.equals("01")) { list.add((Integer.parseInt(yyyy) + 1) + "-01-" + dd); } } else if (nowMon == 11) { list.add(yyyy + "-11-" + dd); list.add(yyyy + "-12-" + dd); list.add((Integer.parseInt(yyyy) + 1) + "-01-" + dd); if (!dd.equals("01")) { list.add((Integer.parseInt(yyyy) + 1) + "-02-" + dd); } } else if (nowMon == 12) { list.add(yyyy + "-12-" + dd); list.add((Integer.parseInt(yyyy) + 1) + "-01-" + dd); list.add((Integer.parseInt(yyyy) + 1) + "-02-" + dd); if (!dd.equals("01")) { list.add((Integer.parseInt(yyyy) + 1) + "-03-" + dd); } } else { list.add(yyyy + "-" + getMon(nowMon) + "-" + dd); list.add(yyyy + "-" + getMon((nowMon + 1)) + "-" + dd); list.add(yyyy + "-" + getMon((nowMon + 2)) + "-" + dd); if (!dd.equals("01")) { list.add(yyyy + "-" + getMon((nowMon + 3)) + "-" + dd); } } return list; } public String getMon(int mon) { String month = ""; if (mon < 10) { month = "0" + mon; } else { month = "" + mon; } return month; }
第三部 编写监听,自定义的控件
public class MyCalendar extends LinearLayout { private static Context context; private Date theInDay; private String inday = "", outday = ""; public static View viewIn; public static View viewOut; public static String positionIn; public static String positionOut; public static final int WEEKDAYS = 7; public static String[] WEEK = { "周日", "周一", "周二", "周三", "周四", "周五", "周六" }; static long nd = 1000 * 24L * 60L * 60L;//一天的毫秒数 private List<String> gvList;//存放天 private OnDaySelectListener callBack;//回调函数 private static String nowday = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMM");//日期格式化 private static SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd");//日期格式化 /** * 构造函数 * * @param context */ public MyCalendar(Context context) { super(context); MyCalendar.context = context; } /** * 日期变量转成对应的星期字符串 * * @param date * @return */ public static String DateToWeek(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); int dayIndex = calendar.get(Calendar.DAY_OF_WEEK); if (dayIndex < 1 || dayIndex > WEEKDAYS) { return null; } return WEEK[dayIndex - 1]; } /** * 获得天数差 * * @param begin * @param end * @return */ public static long getDayDiff(Date begin, Date end) { long day = 1; if (end.getTime() < begin.getTime()) { day = -1; } else if (end.getTime() == begin.getTime()) { day = 1; } else { day += (end.getTime() - begin.getTime()) / (24 * 60 * 60 * 1000); } return day; } /** * 将yyyy-MM-dd类型转换成MM.dd * * @param time * @return * @throws ParseException */ public static String format1(String time) throws ParseException { SimpleDateFormat from = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); SimpleDateFormat to = new SimpleDateFormat("MM.dd", Locale.CHINA); return to.format(from.parse(time)); } /** * 获得指定日期的后一天 * * @param specifiedDay * @return */ public static String getSpecifiedDayAfter(String specifiedDay) { Calendar c = Calendar.getInstance(); Date date = null; try { date = new SimpleDateFormat("yy-MM-dd").parse(specifiedDay); } catch (ParseException e) { e.printStackTrace(); } c.setTime(date); int day = c.get(Calendar.DATE); c.set(Calendar.DATE, day + 1); String dayAfter = new SimpleDateFormat("yyyy-MM-dd") .format(c.getTime()); return dayAfter; } /** * 构造函数 * * @param context */ public MyCalendar(Context context, AttributeSet attrs) { super(context, attrs); MyCalendar.context = context; } public void setInDay(String inday) { this.inday = inday; } public void setOutDay(String outday) { this.outday = outday; } public void setTheDay(Date dateIn) { this.theInDay = dateIn; init(); } /** * 初始化日期以及view等控件 */ private void init() { gvList = new ArrayList<String>();//存放天 final Calendar cal = Calendar.getInstance();//获取日历实例 cal.setTime(theInDay);//cal设置为当天的 cal.set(Calendar.DATE, 1);//cal设置当前day为当前月第一天 int tempSum = countNeedHowMuchEmpety(cal);//获取当前月第一天为星期几 int dayNumInMonth = getDayNumInMonth(cal);//获取当前月有多少天 setGvListData(tempSum, dayNumInMonth, cal.get(Calendar.YEAR) + "-" + getMonth((cal.get(Calendar.MONTH) + 1))); View view = LayoutInflater.from(context).inflate(R.layout.comm_calendar, this, true);//获取布局,开始初始化 TextView tv_year = (TextView) view.findViewById(R.id.tv_year); if (cal.get(Calendar.YEAR) > new Date().getYear()) { tv_year.setVisibility(View.VISIBLE); tv_year.setText(cal.get(Calendar.YEAR) + "年"); } TextView tv_month = (TextView) view.findViewById(R.id.tv_month); tv_month.setText(String.valueOf(theInDay.getMonth() + 1)); MyGridView gv = (MyGridView) view.findViewById(R.id.gv_calendar); calendarGridViewAdapter gridViewAdapter = new calendarGridViewAdapter(gvList, inday, outday); gv.setAdapter(gridViewAdapter); gv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View arg1, int position, long arg3) { String choiceDay = (String) adapterView.getAdapter().getItem(position); String[] date = choiceDay.split(","); String day = date[1]; if (!" ".equals(day)) { if (Integer.parseInt(day) < 10) { day = "0" + date[1]; } choiceDay = date[0] + "-" + day; if (callBack != null) {//调用回调函数回调数据 callBack.onDaySelectListener(arg1, choiceDay); } } } }); } /** * 为gridview中添加需要展示的数据 * * @param tempSum * @param dayNumInMonth */ private void setGvListData(int tempSum, int dayNumInMonth, String YM) { gvList.clear(); for (int i = 0; i < tempSum; i++) { gvList.add(" , "); } for (int j = 1; j <= dayNumInMonth; j++) { gvList.add(YM + "," + String.valueOf(j)); } } private String getMonth(int month) { String mon = ""; if (month < 10) { mon = "0" + month; } else { mon = "" + month; } return mon; } /** * 获取当前月的总共天数 * * @param cal * @return cal.getActualMaximum(Calendar.DATE) */ private int getDayNumInMonth(Calendar cal) { return cal.getActualMaximum(Calendar.DATE); } /** * 获取当前月第一天在第一个礼拜的第几天,得出第一天是星期几 * * @param cal * @return firstDayInWeek */ private int countNeedHowMuchEmpety(Calendar cal) { int firstDayInWeek = cal.get(Calendar.DAY_OF_WEEK) - 1; Log.e("MyCalendar", String.valueOf(firstDayInWeek)); return firstDayInWeek; } /** * gridview中adapter的viewholder * * @author wx */ static class GrideViewHolder { TextView tvDay, tv; } /** * gridview的adapter * * @author Administrator */ static class calendarGridViewAdapter extends BaseAdapter { List<String> gvList;//存放天 String inday, outday; public calendarGridViewAdapter(List<String> gvList, String inday, String outday) { super(); this.gvList = gvList; this.inday = inday; this.outday = outday; } @Override public int getCount() { return gvList.size(); } @Override public String getItem(int position) { return gvList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { GrideViewHolder holder; if (convertView == null) { holder = new GrideViewHolder(); convertView = inflate(context, R.layout.common_calendar_gridview_item, null); holder.tv = (TextView) convertView.findViewById(R.id.tv_calendar); holder.tvDay = (TextView) convertView.findViewById(R.id.tv_calendar_day); convertView.setTag(holder); } else { holder = (GrideViewHolder) convertView.getTag(); } String[] date = getItem(position).split(","); holder.tvDay.setText(date[1]); if ((position + 1) % 7 == 0 || (position) % 7 == 0) { holder.tvDay.setTextColor(Color.parseColor("#339900")); } if (!date[1].equals(" ")) { String day = date[1]; if (Integer.parseInt(date[1]) < 10) { day = "0" + date[1]; } if ((date[0] + "-" + day).equals(nowday)) { holder.tvDay.setTextColor(Color.parseColor("#FF6600")); holder.tvDay.setTextSize(15); holder.tvDay.setText("今天"); } if (!"".equals(inday) && (date[0] + "-" + day).equals(inday)) { convertView.setBackgroundColor(Color.parseColor("#33B5E5")); holder.tvDay.setTextColor(Color.WHITE); holder.tvDay.setText(date[1]); holder.tv.setText("入住"); viewIn = convertView; positionIn = date[1]; } if (!"".equals(outday) && (date[0] + "-" + day).equals(outday)) { convertView.setBackgroundColor(Color.parseColor("#33B5E5")); holder.tvDay.setTextColor(Color.WHITE); holder.tvDay.setText(date[1]); holder.tv.setText("离开"); viewOut = convertView; positionOut = date[1]; } try { //若日历日期<当前日期,则不能选择 if (dateFormat2.parse(date[0] + "-" + day).getTime() < dateFormat2.parse(nowday).getTime()) { holder.tvDay.setTextColor(Color.parseColor("#999999")); } //若日历日期-当前日期>90天,则不能选择 long dayxc = (dateFormat2.parse(date[0] + "-" + day).getTime() - dateFormat2.parse(nowday).getTime()) / nd; if (dayxc > 90) { holder.tvDay.setTextColor(Color.parseColor("#999999")); } } catch (ParseException e) { e.printStackTrace(); } } return convertView; } } /** * 自定义监听接口 * * @author Administrator */ public interface OnDaySelectListener { void onDaySelectListener(View view, String date); } /** * 自定义监听接口设置对象 * * @param o */ public void setOnDaySelectListener(OnDaySelectListener o) { callBack = o; } }
在界面显示选择的日期
接下来就是为了显示选择的日期进行逻辑判断,包括字符串的转换以及日期格式的转换,日期的计算等。
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); if ("".equals(home_into_date.getText().toString()) && "".equals(home_out_date.getText().toString())) { inday = simpleDateFormat.format(new Date()); try { //转换时间格式 String changeDate = MyCalendar.format1(inday); Date dateIn = simpleDateFormat.parse(inday); //将日期转换成周 String weekIn = MyCalendar.DateToWeek(dateIn); home_into_date.setText("" + changeDate + weekIn); String nextDay = MyCalendar.format1(MyCalendar.getSpecifiedDayAfter(inday)); Date dateOut = simpleDateFormat.parse(MyCalendar.getSpecifiedDayAfter(inday)); String weekOut = MyCalendar.DateToWeek(dateOut); home_out_date.setText("" + nextDay + weekOut); long days = MyCalendar.getDayDiff(dateIn, dateOut); home_total_days.setText("共" + (days - 1) + "晚"); } catch (ParseException e) { e.printStackTrace(); } } else { //这里使用sp传的值 inday = pro.getString("dateIn", ""); outday = pro.getString("dateOut", ""); try { String changeDate = MyCalendar.format1(inday); Date dateIn = simpleDateFormat.parse(inday); //将日期转换成周 String weekIn = MyCalendar.DateToWeek(dateIn); home_into_date.setText("" + changeDate + weekIn); String outDay = MyCalendar.format1(outday); Date dateOut = simpleDateFormat.parse(outday); String weekOut = MyCalendar.DateToWeek(dateOut); home_out_date.setText("" + outDay + weekOut); long days = MyCalendar.getDayDiff(dateIn, dateOut); home_total_days.setText("共" + (days - 1) + "晚"); } catch (ParseException e) { e.printStackTrace(); }
其中有几个布局,给图自己写吧
comm_calendar
common_calendar_gridview_item
<LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:orientation="vertical"> <TextView android:id="@+id/tv_calendar_day" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:textSize="15sp" /> <TextView android:id="@+id/tv_calendar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:textColor="#FFFFFF" android:textSize="15sp" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:background="#E4E4E4" /> </LinearLayout>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
赞 (0)