Android使用GridView实现日历的方法
程序员文章站
2023-12-18 12:50:10
在开发中可能会遇到某些情况下需要用到日历的功能,并且还要在日历上加标签什么的,最重要的就是android自带的日历由于各个系统版本不同导致日历的样式也不同,这样就会导致使用...
在开发中可能会遇到某些情况下需要用到日历的功能,并且还要在日历上加标签什么的,最重要的就是android自带的日历由于各个系统版本不同导致日历的样式也不同,这样就会导致使用起来比较麻烦..而且在日历中加标签也不好实现...所以很多时候日历都是自己去实现的...由于自定义日历会比较麻烦...这里就教大家使用gridview来实现,主要是我们比较熟悉这个控件...到时候也可以根据自己的情况进行封装为自定义view
下面就先看看效果图.由于是从项目中抽取出来的,某些地方定制性比较强, 可以根据需求自行修改
效果图
图中的红点就是标签,蓝色背景就是选中的意思.
下面开始撸代码:
先上核心的gridview的适配器:
calendaradapter.java
/** * 日历gridview中的每一个item显示的textview */ public class calendaradapter extends baseadapter { private static string tag = "calendaradapter"; private boolean isleapyear = false; //是否为闰年 private int daysofmonth = 0; //某月的天数 private int dayofweek = 0; //具体某一天是星期几 private int lastdaysofmonth = 0; //上一个月的总天数 private context context; private string[] daynumber = new string[42]; //一个gridview中的日期存入此数组中 private specialcalendar sc = null; private int currentyear = 0; private int currentmonth = 0; /** * 当前选中的日期位置 */ private int currentflag = -1; /** * 当前选中天的字符串 例:20170830 */ private string currentdaystr; private simpledateformat sdf = new simpledateformat("yyyy-m-d"); private set<integer> schdatetagflag = new arrayset<>(); //存储当月所有的日程日期(标签) private string showyear = ""; //用于在头部显示的年份 private string showmonth = ""; //用于在头部显示的月份 private string animalsyear = ""; private string leapmonth = ""; //闰哪一个月 private set<string> mset = null; /** * 距离当前月的差(上一个月-1,当前月0,下一个月+1) */ private int jumpmonth = 0; public calendaradapter(context context, int year, int month, string currentdaystr) { this.context = context; sc = new specialcalendar(); currentyear = year; currentmonth = month; //得到跳转到的月份 this.currentdaystr = currentdaystr; getcalendar(currentyear, currentmonth); } @override public int getcount() { return daynumber.length; } @override public object getitem(int position) { return position; } @override public long getitemid(int position) { return position; } @override public view getview(int position, view convertview, viewgroup parent) { viewholder myviewholder = null; if (convertview == null || convertview.gettag() == null) { convertview = layoutinflater.from(context).inflate(r.layout.item_select_time, null); myviewholder = new viewholder(convertview); convertview.settag(myviewholder); } else { myviewholder = (viewholder) convertview.gettag(); } myviewholder.midtvitemselecttimeday.settext(daynumber[position]); myviewholder.midtvitemselecttimeday.settextcolor(color.gray);//不是当前月为灰 if (position < daysofmonth + dayofweek && position >= dayofweek) { // 当前月信息显示 myviewholder.midtvitemselecttimeday.settextcolor(color.black);// 当月字体设黑 myviewholder.midtvitemselecttimeday.settag(true);// 当月字体设黑 }else { myviewholder.midtvitemselecttimeday.settag(false);// 当月字体设黑 } if (currentflag != -1 && currentflag == position) { //设置当天的背景 myviewholder.midtvitemselecttimeday.setbackgroundresource(r.color.mainmenu); myviewholder.midtvitemselecttimeday.settextcolor(color.white); } else { myviewholder.midtvitemselecttimeday.setbackgroundcolor(0); } //显示小圆点 if (schdatetagflag != null && schdatetagflag.size() > 0) { if (schdatetagflag.contains(position)) { if (myviewholder.midimgitemselecttimelogo.getvisibility()!=view.visible) { myviewholder.midimgitemselecttimelogo.setvisibility(view.visible); } } else { if (myviewholder.midimgitemselecttimelogo.getvisibility()!=view.gone) { myviewholder.midimgitemselecttimelogo.setvisibility(view.gone); } } } else { if (myviewholder.midimgitemselecttimelogo.getvisibility()!=view.gone) { myviewholder.midimgitemselecttimelogo.setvisibility(view.gone); } } return convertview; } /** * 下一个月 */ public void addmonth() { jumpmonth++; } /** * 上一个月 */ public void lessmonth() { jumpmonth--; } /** * 更新日历数据 */ public void updatamonth() { int stepyear; int stepmonth = currentmonth + jumpmonth; if (stepmonth > 0) { //下一个月 if (stepmonth % 12 == 0) { stepyear = currentyear + stepmonth / 12 - 1; stepmonth = 12; } else { stepyear = currentyear + stepmonth / 12; stepmonth = stepmonth % 12; } } else { //上一个月 stepyear = currentyear - 1 + stepmonth / 12; stepmonth = stepmonth % 12 + 12; } getcalendar(stepyear, stepmonth); } /** * 得到某年的某月的天数且这月的第一天是星期几 * * @param year * @param month */ private void getcalendar(int year, int month) { isleapyear = sc.isleapyear(year); //是否为闰年 daysofmonth = sc.getdaysofmonth(isleapyear, month); //某月的总天数 dayofweek = sc.getweekdayofmonth(year, month); //某月第一天为星期几 lastdaysofmonth = sc.getdaysofmonth(isleapyear, month - 1); //上一个月的总天数 getweek(year, month); } /** * 将一个月中的每一天的值添加入数组daynuber中 * * @param year * @param month */ private void getweek(int year, int month) { schdatetagflag.clear(); currentflag = -1; int j = 1; //得到当前月的所有日程日期(这些日期需要标记) for (int i = 0; i < daynumber.length; i++) { if (i < dayofweek) { //前一个月 int temp = lastdaysofmonth - dayofweek + 1; daynumber[i] = (temp + i) + ""; } else if (i < daysofmonth + dayofweek) {//本月 int day = i - dayofweek + 1; //得到的日期 daynumber[i] = i - dayofweek + 1 + ""; //对于当前月才去标记当前日期 string yearstr = string.valueof(year); string monthstr =getstr(string.valueof(month),2); string daystr =getstr(string.valueof(day),2); string timeall = yearstr + monthstr + daystr; if (timeall.equals(currentdaystr)) {//判断选中的位置 currentflag = i; } if (mset != null && mset.size() > 0) { for (string s : mset) {//迭代器遍历判断是否需要带标签 if (timeall.equals(s)) { schdatetagflag.add(i); } } } setshowyear(yearstr); setshowmonth(string.valueof(month)); } else { //下一个月 daynumber[i] = j + ""; j++; } } } /** * 获取当前时间 样式:20170830 * @param position * @return */ public string getitemtime(int position) { string month = getstr(getshowmonth(), 2); string day = getstr(getdatebyclickitem(position), 2); return getshowyear() + month + day; } /** * 保留n位整数,不足前面补0 * * @param file string * @param bit 位数 * @return */ public static string getstr(string file,int bit) { while (file.length() < bit) file = "0" + file; return file; } /** * 点击每一个item时返回item中的日期 * * @param position * @return */ public string getdatebyclickitem(int position) { return daynumber[position]; } /** * 在点击gridview时,得到这个月中第一天的位置 * * @return */ public int getstartpositon() { return dayofweek + 7; } /** * 在点击gridview时,得到这个月中最后一天的位置 * * @return */ public int getendposition() { return (dayofweek + daysofmonth + 7) - 1; } public string getshowyear() { return showyear; } public void setshowyear(string showyear) { this.showyear = showyear; } public string getshowmonth() { return showmonth; } public void setshowmonth(string showmonth) { this.showmonth = showmonth; } public string getanimalsyear() { return animalsyear; } public void setanimalsyear(string animalsyear) { this.animalsyear = animalsyear; } public string getleapmonth() { return leapmonth; } public void setleapmonth(string leapmonth) { this.leapmonth = leapmonth; } public set<string> getset() { return mset; } public void setset(set<string> set) { mset = set; } static class viewholder { @bindview(r.id.id_img_item_select_time_logo) imageview midimgitemselecttimelogo; @bindview(r.id.id_tv_item_select_time_day) textview midtvitemselecttimeday; viewholder(view view) { butterknife.bind(this, view); } } }
日历工具类:
/** * 日历工具类 */ public class specialcalendar { private int daysofmonth = 0; //某月的天数 private int dayofweek = 0; //具体某一天是星期几 /** * 判断是否为闰年 * @param year * @return */ public boolean isleapyear(int year) { if (year % 100 == 0 && year % 400 == 0) { return true; } else if (year % 100 != 0 && year % 4 == 0) { return true; } return false; } /** * 得到某月有多少天数 * @param isleapyear * @param month * @return */ public int getdaysofmonth(boolean isleapyear, int month) { switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: daysofmonth = 31; break; case 4: case 6: case 9: case 11: daysofmonth = 30; break; case 2: if (isleapyear) { daysofmonth = 29; } else { daysofmonth = 28; } } return daysofmonth; } /** * 指定某年中的某月的第一天是星期几 * @param year * @param month * @return */ public int getweekdayofmonth(int year, int month){ calendar cal = calendar.getinstance(); cal.set(year, month-1, 1); dayofweek = cal.get(calendar.day_of_week)-1; return dayofweek; } }
布局文件:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <include layout="@layout/layout_public_finish_menu" /> <linearlayout android:layout_width="match_parent" android:layout_height="40dp" android:background="@color/bg_home_gone_menu" android:gravity="center" android:orientation="horizontal" > <imageview android:id="@+id/id_img_select_time_less" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:padding="5dp" android:src="@mipmap/ic_sd_time_less" android:background="@drawable/selector_public_btn_bg" /> <textview android:id="@+id/id_tv_select_time_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="4" android:gravity="center" android:text="年月" android:textcolor="@color/white" android:textsize="@dimen/default_big" /> <imageview android:id="@+id/id_img_select_time_add" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:padding="5dp" android:src="@mipmap/ic_sd_time_add" android:background="@drawable/selector_public_btn_bg" /> </linearlayout> <gridview android:id="@+id/id_gv_select_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/bg_rectangle_null_black_1" android:clickable="true" android:gravity="center" android:layout_gravity="center" android:clipchildren="true" android:listselector="@null" android:numcolumns="7" android:padding="1dp" android:layout_margin="5dp" android:stretchmode="columnwidth" /> </linearlayout>
item布局
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg_rectangle_null_black_1"> <textview android:id="@+id/id_tv_item_select_time_day" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="天" android:textsize="@dimen/default_big" android:layout_margin="1dp" android:textstyle="bold" /> <imageview android:id="@+id/id_img_item_select_time_logo" android:layout_width="5dp" android:layout_height="5dp" android:layout_margin="3dp" android:src="@drawable/shap_doorbell_oval_red" android:visibility="gone" /> </relativelayout>
布局只供参考...可以根据需求进行修改
下面就看看简单的调用
//传入当前的年,月..已经选中的时间(20170830) madapter = new calendaradapter(mcontext, year_c, month_c, currentdaystr); midgvselectitem.setadapter(madapter); /** * gridview item的点击事件 */ private class mygvlistener implements adapterview.onitemclicklistener { @override public void onitemclick(adapterview<?> parent, view view, int position, long id) { textview mtv = (textview) view.findviewbyid(r.id.id_tv_item_select_time_day); boolean isonclick = (boolean) mtv.gettag(); if (isonclick) { string time = madapter.getitemtime(position); intent mintent = getintent(); mintent.putextra("filedate", time); setresult(appstart.sdva_sdta, mintent); finish(); log.i(tag,"当前选择的时间:" + time); } } } /** * 点击事件逻辑处理 */ private class mylistener implements view.onclicklistener { @override public void onclick(view v) { switch (v.getid()) { //上一个月 case r.id.id_img_select_time_less: madapter.lessmonth(); mhandler.sendemptymessage(updata_time); addtexttotoptextview(midtvselecttimeshow); break; //下一个月 case r.id.id_img_select_time_add: madapter.addmonth(); mhandler.sendemptymessage(updata_time); addtexttotoptextview(midtvselecttimeshow); break; } } } private set<string> dayeventcount = new hashset<>(); //设置需要显示标签的实际 madapter.setset(dayeventcount); //更新 @override protected void uihandlermessage(message msg) { switch (msg.what) { case updata_time: madapter.updatamonth(); madapter.notifydatasetchanged(); break; } }
调用部分的代码由于是从项目中直接复制出来的..代码的前后没有什么关联性,主要是说明功能的..请根据自己的项目进行调整..
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Android UI控件Switch的使用方法
-
Android使用GridView实现日历的方法
-
Android使用CrashHandler来获取应用的crash信息的方法
-
Android编程使用ListView实现数据列表显示的方法
-
Android编程实现号码归属地查询的方法
-
Android编程实现自动检测版本及自动升级的方法
-
Android编程使用内容提供者方式(ContentProvider)进行存储的方法
-
Android编程使用HTTP协议与TCP协议实现上传文件的方法
-
PHP使用Mysqli类库实现完美分页效果的方法
-
Android编程简单实现ImageView点击时背景图修改的方法