Android实现日历控件示例代码
程序员文章站
2023-12-15 13:56:28
做的是一个酒店的项目,可以选择入住和离开的日期。声明为了省事在网上找的资料,自己修改的逻辑,希望对需要的朋友有帮助。喜欢的给个好评。谢谢啦!祝生活愉快!
先上图...
做的是一个酒店的项目,可以选择入住和离开的日期。声明为了省事在网上找的资料,自己修改的逻辑,希望对需要的朋友有帮助。喜欢的给个好评。谢谢啦!祝生活愉快!
先上图
第一步,搭建布局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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。