广告
返回顶部
首页 > 资讯 > 移动开发 >android自定义view之实现日历界面实例
  • 534
分享到

android自定义view之实现日历界面实例

view界面Android 2022-06-06 04:06:02 534人浏览 泡泡鱼
摘要

现在网上有很多自定义view实现日历的demo,今天讲一讲如何自己实现这个自定义view。 看一下最终效果图: 在这个自定义view中,我使用了各种奇技淫巧的方法来实现这个日

现在网上有很多自定义view实现日历的demo,今天讲一讲如何自己实现这个自定义view。

看一下最终效果图:

在这个自定义view中,我使用了各种奇技淫巧的方法来实现这个日历,真是费尽心思。废话少说,开始进坑。

界面分析

头部是一个textview,显示年份和月份,然后下边一行是星期几,这两行可以固定住,不随月份切换而进出屏幕。

再下边就是我们自定义view 的主角,每个月的天数。目前规定是星期日为每星期第一天。上个月的天数填充满第一行,下个月的前几天填充完最后一行,颜色设置为灰色,本月日期中的周一至周五设置为红色,周六周日设置为青色,特殊日期设置为绿色,并且在右上角填充特殊标识符,用四分之三的圆弧包裹(上个月和下个月的日期没有)。

此处还有个小细节,每月的总行数会不断改变,但是view的总高度并未改变,所以视觉效果会不一样。

构造方法


 public MyCalendar(Context context) {
    super(context);
  }
  public MyCalendar(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
  }

主要是实现上面两个构造方法,第一个是用来在java代码中使用的,第二个是用来在xml布局文件中使用的。

暴露的接口

目前接口共有下面几个,setDate(CustomDate customDate),setWeekendHighLight(boolean b),setSpecialDay(int[] ints)

其中第一个是必须要设置的,否则是不会显示任何东西,第二个设置的是否周末高亮,第三个设置的是特殊显示的日期,第四个是设置是否可以点击前一个月或者后一个月的日期,默认为不设置,后期可以根据自己需求增加其他接口。


  
  public void setDate(CustomDate customDate) {
    Log.d(TAG, customDate.toString());
    this.date = customDate;
    firstDayOfWeek = date.getFirstDayOfWeek();
    Log.d(TAG, (date.getMonth() + 1) + "月1号是星期" + firstDayOfWeek);
    lastDayOfWeek = date.getLastDayOfWeek();
    lineCount = calculateLineNum() + 1;
    lastMonthTotalDays = date.getLastMonthDays();
  }
  
  public void setWeekendHighLight(boolean b) {
    this.weekendHighlight = b;
  }
  public void setSpecialDay(int[] ints) {
    this.specialDays = ints;
  }
  
  public void setCanClickNextOrPreMonth(boolean b) {
    this.canClickNextOrPreMonth = b;
  }

在这里说明一下计算显示行数的方法,首先要注意我们获取的星期数与实际的星期几会有一个增加一天的问题,也就是当前是星期4,那么你获取的int将会是5.


 
  private int calculateLineNum() {
    monthDaySum = date.getTotalDayOfMonth();
    return (firstDayOfWeek - 1 + monthDaySum) / 7;
  }

我们将第一天是星期几减去一后加上这个月总共多少天,就可以获得最后一天是在什么位置,然后除以七取商的整数部分,然后在进一法即可获得应该显示多少行。

onSizechanged方法

onSizechanged方法中已经可以获得显示的尺寸了,此时我们需要做一些工作:


 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    this.viewWidth = w;
    this.viewHeight = h;
    Log.d(TAG, "onSizeChanged" + w + h);
    cutGrid();
    init();
    setCellDay();
  }

首先是将宽和高引入进来,方便后边使用。

cutGrid()方法是将区域分割为行X列的格式。

init()方法初始化了一些画笔。

setCellDay()方法将每月的天对应过到坐标上。

首先看一下cutGrid()方法:


 
  private void cutGrid() {
    cellWidth = (float) viewWidth / ROW_COUNT;
    cellHeight = (float) viewHeight / lineCount;
    this.radius = Math.min(cellWidth / 2, cellHeight / 2);
    for (int i = 0; i < lineCount; i++) {
      for (int j = 0; j < ROW_COUNT; j++) {
        points.add(new PointF(cellWidth * j + cellWidth / 2, cellHeight * i + cellHeight / 2));
      }
    }
  }

cellWidth是每天的宽度,其中ROW_COUNT是一个常量7,表示每周7天;cellHeight是每行的高度,linecount是一个变量,需要我们根据日期计算,后边会说到;radius是我们绘制区域的半径,这个值是我们取宽度和高度中较小的值的一半。然后我们将每个方格中心坐标点利用双重循环放入一个List<Point> points中。

整个view被分割为如上的形状。

下面来看一下init()方法:


private void init() {
    circlePaint = new Paint();
    circlePaint.setStyle(Paint.Style.STROKE);
    circlePaint.setAntiAlias(true);
    circlePaint.setColor(Color.BLUE);
    textPaint = new Paint();
    textPaint.setAntiAlias(true);
    textPaint.setColor(Color.BLACK);
    textPaint.setTextSize(radius / 2);
    selectPaint = new Paint();
    selectPaint.setColor(Color.YELLOW);
    selectPaint.setAlpha(10);
    selectPaint.setAntiAlias(true);
    selectPaint.setStyle(Paint.Style.FILL);
    selectTextPaint = new Paint();
    selectTextPaint.setColor(Color.WHITE);
    selectTextPaint.setAntiAlias(true);
    selectTextPaint.setTextSize(radius / 2);
    selectTextPaint.setStyle(Paint.Style.FILL);
  }

基本都是画笔工具

然后是setAllDays()方法:


 
  private void setCellDay() {
    cellDays = new CellDay[lineCount * ROW_COUNT];
    for (int i = 0, length = cellDays.length; i < length; i++) {
      cellDays[i] = new CellDay();
      cellDays[i].setPointX(points.get(i).x);
      cellDays[i].setPointY(points.get(i).y);
      if (firstDayOfWeek > 1 && i < firstDayOfWeek - 1) {
        cellDays[i].setDayState(DayState.LASTMONTH);
        cellDays[i].setDate(String.valueOf(lastMonthTotalDays - firstDayOfWeek + i + 2));
        cellDays[i].setCustomDate(new CustomDate(
            date.getYear(), date.getMonth() - 1, lastMonthTotalDays - firstDayOfWeek + i + 2));
      }
      if (i >= firstDayOfWeek - 1 && i < monthDaySum + firstDayOfWeek - 1) {
        cellDays[i].setDayState(CURRENTMONTH);
        cellDays[i].setDate(String.valueOf(i + 2 - firstDayOfWeek));
        cellDays[i].setCustomDate(new CustomDate(
            date.getYear(), date.getMonth(), i - firstDayOfWeek + 2));
        //设置周末高亮
        if (weekendHighlight) {
          if (i % 7 == 0 || i % 7 == 6) {
            cellDays[i].setDayState(WEEKEND);
          }
        }
      }
      if (i >= monthDaySum + firstDayOfWeek - 1) {
        cellDays[i].setDayState(NEXTMONTH);
        cellDays[i].setDate(String.valueOf(i - monthDaySum - firstDayOfWeek + 2));
        cellDays[i].setCustomDate(new CustomDate(
            date.getYear(), date.getMonth() + 1, i - monthDaySum - firstDayOfWeek + 2));
      }
      for (int j = 0, s = specialDays.length; j < s; j++) {
        if (specialDays[j] + firstDayOfWeek - 2 == i) {
          cellDays[i].setDayState(SPECIALDAY);
        }
      }
    }
  }

在这里我们用到了一个自定的类-CellDay。

CellDay有以下几个字段


    private String date;
    private DayState dayState;
    private CustomDate customDate;
    private float pointX;
    private float pointY;
    private boolean isSelected;

1、String date表示当前的日期。

2、dayState是一个美剧类型,定义了天的状态值。

LASTMONTH:上个月的日期 CURRENTMONTH:本月的日期 NEXTMONTH: 下个月的日期 CURRENTDAY: 今天的日期 WEEKEND:周末的日期 SPECIALDAY:用户自定义的可以设置状态的日期

其中可以设置多种状态,用法和SPECIALDAY基本一样。

cusomedate是我们自己定义的一个工具类,包含项目中需要用到的一系列方法。 pointX是横坐标。 pointY是纵坐标。 isSelceted表示有没有被选中。

CustomDate工具


public class CustomDate {
  private Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
  private int year;
  private int month;
  private int day;
  private int dayOfWeek;
  public CustomDate() {
  }
  
  public CustomDate getCurrentDate() {
    this.year = calendar.get(Calendar.YEAR);
    this.month = calendar.get(Calendar.MONTH);
    this.day = calendar.get(Calendar.DAY_OF_MONTH);
    this.dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
    return new CustomDate(year, month, day);
  }
  public CustomDate(int year, int month, int day) {
    this.year = year;
    this.month = month;
    this.day = day;
    calendar.set(year, month, day);
    dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
  }
  
  public int getLastMonthDays() {
    return this.getDaysOfMonth(this.year, this.month - 1);
  }
  
  public int getFirstDayOfWeek() {
    calendar.set(this.year, this.month, 1);
    return calendar.get(Calendar.DAY_OF_WEEK);
  }
  
  public int getLastDayOfWeek() {
    calendar.set(this.year, this.month, getTotalDayOfMonth());
    return calendar.get(Calendar.DAY_OF_WEEK);
  }
  
  public int getTotalDayOfMonth() {
    return this.getDaysOfMonth(year, month);
  }
  public int getTotalWeekOfMonth() {
    return calendar.getMaximum(Calendar.WEEK_OF_MONTH);
  }
  public int getYear() {
    return year;
  }
  public void setYear(int year) {
    this.year = year;
  }
  public int getMonth() {
    return month;
  }
  public void setMonth(int month) {
    this.month = month;
  }
  public int getDay() {
    return day;
  }
  public void setDay(int day) {
    this.day = day;
  }
  public int getDayOfWeek() {
    return dayOfWeek;
  }
  public void setDayOfWeek(int dayOfWeek) {
    this.dayOfWeek = dayOfWeek;
  }
  @Override
  public String toString() {
    return "CustomDate{" +
        "year=" + year +
        ", month=" + (getMonth() + 1) +
        ", day=" + day +
        ", dayOfWeek=" + dayOfWeek +
        '}';
  }
  
  private int getDaysOfMonth(int year, int month) {
    if (month > 11) {
      month = 0;
      year += 1;
    } else if (month < 0) {
      month = 11;
      year -= 1;
    }
    int[] arr = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int daysOfMonth = 0;
    if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
      arr[1] = 29;
    }
    daysOfMonth = arr[month];
    return daysOfMonth;
  }
}

注释中对每个方法的说明已经非常清晰了。


int getLastMonthDays()

获取上个月的天数是用来计算上个月最后一天是星期几,然后以此推导出上个月在本月中显示的天数和对应的星期。


getFirstDayOfWeek()

获取本月第一天是星期几,然后排序本月的天数与对应的星期。


int getTotalDayOfMonth()

获取本月总共多少天。配合第一天是星期几用来计算总共分为几行,也就是确定linenumber。

您可能感兴趣的文章:Android自定义控件实现可多选课程日历CalendarViewAndroid CalendarView,DatePicker,TimePicker,以及NumberPicker的使用Android 一个日历控件的实现代码Android实现自定义日历Android自定义日历控件实例详解Android实现日历控件示例代码Android自定义日历Calender代码实现Android 仿日历翻页、仿htc时钟翻页、数字翻页切换效果Android可签到日历控件的实现方法Android使用GridView实现日历的简单功能Android开发之日历CalendarView用法示例


--结束END--

本文标题: android自定义view之实现日历界面实例

本文链接: https://www.lsjlt.com/news/22080.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • android自定义view之实现日历界面实例
    现在网上有很多自定义view实现日历的demo,今天讲一讲如何自己实现这个自定义view。 看一下最终效果图: 在这个自定义view中,我使用了各种奇技淫巧的方法来实现这个日...
    99+
    2022-06-06
    view 界面 Android
  • Android自定义view实现日历打卡签到
    本文实例为大家分享了Android自定义view实现日历打卡签到的具体代码,供大家参考,具体内容如下 1.说明 自己写一个view实现每天签到的功能,设置背景图片 源码下载 2.效果...
    99+
    2022-11-12
  • Android实现自定义日历
    自定义日历控件,支持旧历、节气、日期标注、点击操作 (参考网络上的日历控件改写) 注:将下面的四张资源图片拷贝到所建包的下一个image目录中,如Calendar.java 所...
    99+
    2022-06-06
    自定义 Android
  • Android如何自定义view实现日历打卡签到
    这篇文章主要介绍Android如何自定义view实现日历打卡签到,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Android是什么Android是一种基于Linux内核的自由及开放源代码的操作系统,主要使用于移动设备...
    99+
    2023-06-14
  • Android自定义实现日历控件
    本文实例为大家分享了Android自定义实现日历控件的具体代码,供大家参考,具体内容如下 1. Calendar类 2. 布局 创建calendar_layout.xml <...
    99+
    2022-11-12
  • Android自定义日历控件实例详解
    为什么要自定义控件 有时,原生控件不能满足我们对于外观和功能的需求,这时候可以自定义控件来定制外观或功能;有时,原生控件可以通过复杂的编码实现想要的功能,这时候可以自定义控件来...
    99+
    2022-06-06
    Android
  • Android Studio简单实现自定义日历
    本文实例为大家分享了Android Studio自定义日历的具体代码,供大家参考,具体内容如下 效果图: 目录树 1.DayBean.java用来存储每天的信息 package ...
    99+
    2022-11-13
  • Android自定义日历Calender代码实现
    产品要做签到功能,签到功能要基于一个日历来进行,所以就根据 要求自定义了一个日历 自定义控件相信做android都知道: (1)首先创建一个类,继承一个容器类或者是一个控...
    99+
    2022-06-06
    Android
  • Android 自定义View之倒计时实例代码
    Android 自定义View之倒计时实例代码 需求: 大多数app在注册的时候,都有一个获取验证码的按钮,点击后,访问接口,最终用户会收到短信验证码。为了不多次写这个获取验...
    99+
    2022-06-06
    倒计时 view 自定义view Android
  • Android如何自定义实现日历控件
    这篇文章主要介绍Android如何自定义实现日历控件,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体内容如下1. Calendar类2. 布局创建calendar_layout.xml<LinearLayou...
    99+
    2023-06-25
  • Android自定义view之3D正方体效果实例
    目录前言一、小提二、将传感器改成事件分发机制三、使用四、源码总结前言 在之前写了一篇关于3D效果的文章,借助传感器展示,有小伙伴问可不可以改成手势滑动操作(事件分发),所以出一篇文...
    99+
    2022-11-12
  • Android自定义View实现水面上涨效果
    实现效果如下: 实现思路: 1、如何实现圆中水面上涨效果:利用Paint的setXfermode属性为PorterDuff.Mode.SRC_IN画出进度所在的矩形与圆的交...
    99+
    2022-06-06
    view Android
  • Android ListView自定义Adapter实现仿QQ界面
    PS:listview中有一些简单使用的适配器,如:SimpleAdapter:构造方法SimpleAdapter(Context context,List<Map<String,?>> data,reStr...
    99+
    2023-05-30
    listview adapter
  • Android自定义view实现雪花特效实例代码
    目录一、前言二、创意名三、效果展示四、实现步骤五、编码实现总结一、前言 这个冬天,老家一直没有下雨, 正好圣诞节,就想着制作一个下雪的特效。 圣诞祝福:平安夜,舞翩阡。雪花飘,飞满天...
    99+
    2022-12-28
    android实现雪花特效 android雪花特效 android自定义view
  • Android自定义View实现等级滑动条的实例
     Android自定义View实现等级滑动条的实例 实现效果图: 思路: 首先绘制直线,然后等分直线绘制点; 绘制点的时候把X值存到集合中。 然后绘制背...
    99+
    2022-06-06
    view Android
  • Android自定义View实现验证码
    本文章是基于鸿洋的Android 自定义View (一) 的一些扩展,以及对Android自定义View构造函数详解里面内容的一些转载。 首先我们定义一个declare-sty...
    99+
    2022-06-06
    view 验证码 Android
  • java简单实现自定义日历
    本文实例为大家分享了java自定义日历的具体代码,供大家参考,具体内容如下 效果图: 源码: package com.example; import java.text.Simp...
    99+
    2022-11-13
  • Android 自定义View 密码框实例代码
    暴露您view中所有影响可见外观的属性或者行为。 •通过XML添加和设置样式 •通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 ...
    99+
    2022-06-06
    view 自定义view Android
  • Android自定义相机界面的实现代码
    我们先实现拍照按钮的圆形效果哈,Android开发中,当然可以找美工人员设计图片,然后直接拿进来,不过我们可以自己写代码实现这个效果哈,最常用的的是用layout-list实现...
    99+
    2022-06-06
    界面 相机 Android
  • Android自定义手机界面状态栏实例代码
    前言 我们知道IOS上的应用,状态栏的颜色总能与应用标题栏颜色保持一致,用户体验很不错,那安卓是否可以呢?若是在安卓4.4之前,答案是否定的,但在4.4之后,谷歌允许开发者自定...
    99+
    2022-06-06
    界面 状态栏 手机 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作