欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现日历控件示例代码

程序员文章站 2023-12-05 20:45:10
做的是一个酒店的项目,可以选择入住和离开的日期。声明为了省事在网上找的资料,自己修改的逻辑,希望对需要的朋友有帮助。喜欢的给个好评。谢谢啦!祝生活愉快! 先上图...

做的是一个酒店的项目,可以选择入住和离开的日期。声明为了省事在网上找的资料,自己修改的逻辑,希望对需要的朋友有帮助。喜欢的给个好评。谢谢啦!祝生活愉快!

先上图

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;
  }
}

在界面显示选择的日期

Android实现日历控件示例代码 

接下来就是为了显示选择的日期进行逻辑判断,包括字符串的转换以及日期格式的转换,日期的计算等。

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

Android实现日历控件示例代码 

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>

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