当前位置: 移动技术网 > IT编程>移动开发>Android > Android使用GridView实现日历的方法

Android使用GridView实现日历的方法

2019年07月24日  | 移动技术网IT编程  | 我要评论

女烈图,医香19楼,问卷调查模板

在开发中可能会遇到某些情况下需要用到日历的功能,并且还要在日历上加标签什么的,最重要的就是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;

    }

  }

调用部分的代码由于是从项目中直接复制出来的..代码的前后没有什么关联性,主要是说明功能的..请根据自己的项目进行调整..

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网