【Android论文栏目提醒】:网学会员鉴于大家对Android论文十分关注,论文会员在此为大家搜集整理了“论文 实现基于Android 的日历系统 - 其它论文”一文,供大家参考学习
、实现基于
Android 的日历系统 摘要:
Android 作为目前较为流行的智能手机操作系统已成为大多数人的首选。
在美国乃至世界的很多地方的出货量已经超越 Iphone, 成为世界上最大智能手机操作系统。
因此, 世界各地的程序员都跃跃欲试地想
学习 Android 的开发, 并希望从中捞得属于自己的第一桶金。
在此给出一个基于
Android 的日历系统的完整实现过程。
关键词:
Android; 日历; 绘画; 农历; 记录; 提醒 1 引言 要实现的日历除了常规的日历功能外, 还可以显示与当前日期相关的信息, 如当前日期的农历日期、天干地支、节日等信息。
下面先看看日历的绚丽界面, 如图1、图 2 所示。
主要功能 2 绘画基础 由于实现的日历
系统要涉及到大量的
Android 绘图技术,因此, 要简单介绍
Android 的绘图技术。
绘制图形通常在
Android.view.View 或其子类的 onDraw 方法中进行。
该方法的定义如下: protected void onDrawCanvas canvas 其中 Canvas 对象提供了大量用于绘图的方法, 这些方法主要包括绘制像素点、直线、圆形、弧、文本, 这些都是组成复杂图形的基本元素。
如果要画更复杂的图形, 可以采用组合这些图形基本元素的方式来完成。
例如, 可以采用画 3 条直线的方式来画三角形。
下面来看一下绘制图形基本元素的方法。
2.1 绘制像素点 public native void drawPointfloat x float y Paint paint// 画一个像素点 public native void drawPointsfloat pts int offset int countPaintpaint // 画多个像素点 public void drawPointsfloat pts Paint paint// 画多个像素点 参数的含义如下: (1) x: 像素点的横坐标。
(2) y: 像素点的纵坐标。
(3) paint: 描述像素点属性的 Paint 对象。
可设置像素点的大小、颜色等属性。
绘制其他图形元素的 Paint 对象与绘制像素点的 Paint 对象的含义相同。
在绘制具体的图形元素时可根据实际的情况设置 Paint 对象。
(4) pts: drawPoints 方法可一次性画多个像素点。
pts 参数表示多个像素点的坐标。
该数组元素必须是偶数个, 两个一组为一个像素点的坐标。
(5) offset: drawPoints 方法可以取 pts 数组中的一部分连续元素作为像素点的坐标, 因此, 需要通过 offset 参数来指定取得数组中连续元素的第一个元素的位置, 也就是元素偏移量, 从 0 开始。
例如, 要从第 3 个元素开始取数组元素, 那么 offset 参数值就是 2。
(6) count: 要获得的数组元素个数, count 必须为偶数(两个数组元素为一个像素点的坐标)。
要注意的是, offset 可以从任意一个元素开始取值, 例如,offset 可以为1, 然后 count 为 4。
2.2 绘制直线 public void drawL ine float startX float startY float stopXfloatstopYPaint paint// 画一条直线 public native void drawLinesfloat pts int offset int countPaintpaint // 画多条直线 public void drawLinesfloat pts Paint paint// 画多条直线 参数的含义如下: (1) startX: 直线开始端点的横坐标。
(2) startY: 直线开始端点的纵坐标。
(3) stopX: 直线结束端点的横坐标。
(4) stopY: 直线结束端点的纵坐标。
(5) pts: 绘制多条直线时的端点坐标集合。
4 个数组元素(两个为开始端点的坐标, 两个为结束端点的坐标) 为 1 组,表示一条直线。
例如, 画两条直 前线, pts 数组就应该有 8 个元素。
4 个数组元素为第 1 条直线两个端点的坐标,后 4 个数组元素为第 2 条直线的两个端点的坐标。
(6) offset: pts 数组中元素的偏移量。
(7) count: 取得 pts 数组中元素的个数。
该参数值需为 4 的整数倍。
2.3 绘制圆形 public void drawCircle float cx float cy float radius Paint paint 参数的含义如下: (1) cx: 圆心的横坐标。
(2) cy: 圆心的纵坐标。
(3) radius: 圆的半径。
2.4 绘制弧 public void drawArc RectF oval float startAngle float sweepAngleboolean useCenter Paint paint 参数的含义如下: (1) oval: 弧的外切矩形的坐标。
需要设置该矩形的左上角和右下角的坐标,也就是 oval.left、oval.top、oval.right 和 oval.bottom。
(2) startAngle: 弧的起始角度。
(3) sweepAngle: 弧的结束角度。
如果 sweepAngle - startAngle 的值大于等于 360, drawArc 画的就是一个圆或椭圆(如果 oval 指定的坐标画出来的是长方形, drawArc 画的就是椭圆)。
(4) useCenter: 如果该参数值为 true, 在画弧时弧的两个端点会连接圆心。
如果该参数值为 false, 则只会画弧。
效果如图 3 所示。
前两个弧未设置填充状态, 后两个弧设置了填充状态。
2.5 绘制文本 // 绘制 text 指定的文本 public native void drawText String text float x float y Paint paint // 绘制 text 指定的文本。
文本中的每一个字符的起始坐标由 //pos 数组中的值决定。
public void drawPosTextString text float pos Paint paint // 绘制 text 指定的文本。
text 中的每一个字符的起始坐标由 //pos 数组中的值决定。
并且可以选择 text 中的某一段 // 连续的字符绘制 public void drawPosTextchar text int index int count float posPaint paint 参数的含义如下: 1 text: drawText 方法中的 text 参数表示要绘制的文本。
drawPostText 方法中的 text 虽然也表示要绘制的文本, 但每一个字符的坐标需要单独指定。
如果未指定某个字符的坐标, 系统会抛出异常。
2 x: 绘制文本的起始点的横坐标。
3 y: 绘制文本的起始点的纵坐标。
4 index: 选定的字符集合在 text 数组中的索引。
5 count: 选定的字符集中字符个数。
3 绘制日历的框架 从图 1 可以看出, 日历的上部是 3 行文字, 显示了当前日期的相关信息。
下面来看看如何布局显示这些文字的组件。
在日历主界面的上半部需要放置 4 个组件, 1 个 ImageView 组件和 3 个TextView 组件。
其中 ImageView 组件用于显示左上角的图像。
3 个 TextView 组件用于显示当前日期的信息。
由于目前还没有当前日期的信息。
因此, 这 3 个TextView 组件暂时设置了固定的信息。
下面开始在 main.xml 文件中设置这 4 个组件。
在修改 main.xml 文件的内容之前, 先复制一个 calendar.png 文件, 作为日历的 logo (修改AndroidManifest.xml 文件中的应用
程序图标)。
建立一个 Calendar 工程, 并编写 main.
xml 文件。
ltxml versionquot1.0quot encodingquotutf-8quotgt ltLinearLay out xmlns:
android http://schemas.
android.com/apk/res/
android android:orientation quotverticalquot
android:layout_width quotfill_parentquotandroid:layout_heightquotfill_parentquotandroid:backgroundquotcolor/calendar_backgroundquot gtlt --
android:background quotdrawable/backgroundquot --gt ltRelativeLayout
android:id quot id/calHeaderquotandroid:layout_widthquotfill_parentquotandroid:layout_heightquot70dpquotgt ltImageView
android:id quot id/ivLogoquot
android: srcquotdrawable/calendar_bakquot
android:layout_widthquotdimen/logo_sizequot
android: layout_heightquotdimen/logo_sizequot
android:layout_marginquotdimen/marginquot /gt ltLinearLayoutandroid:layout_widthquotfill_parentquotandroid:layout_height quotwrap_contentquotandroid:layout_toRightOfquotid/ivLogoquotandroid:layout_marginTop quotdimen/marginquotandroid:orientationquotverticalquot gt ltTextView
android:id quot id/tvMsg1quot
android: layout_widthquotfill_parentquot
android:layout_height quotwrap_contentquot
android:textColorquotcolor/text_colorquot /gt ltTextView
android:id quot id/tvMsg2quot
android:layout_widthquotfill_parentquot
android:layout_height quotwrap_contentquot
android:textColorquotcolor/text_colorquot /gt ltTextView
android:id quot id/tvMsg3quot
android: layout_widthquotfill_parentquot
android:layout_height quotwrap_contentquot
android:textColorquotcolor/text_colorquot /gt lt/LinearLayoutgt lt/RelativeLayoutgt lt/LinearLayoutgt 下面在 Main 类的 Oncreate 方法中编写代码装载 main.xml: public void onCreateBundle savedInstanceState super.onCreatesavedInstanceState LinearLayout mainLayout LinearLayout getLayoutInflater. inflateR.layout.main null setContentViewmainLayout // 需要向 mainLayout 中加入日历网络 在绘制日历之前, 要先介绍一下日历绘制的方法。
虽然从底层技术来看, 绘制日历是在 onDraw 方法中完成的。
但在本系统中将要绘制的部分分成了很多块。
而这些要绘制的块都需要放在一个叫 CalendarView 的类中, 代码如下: public class CalendarView extends View private Activity activity Override protected void onDrawCanvas canvas public CalendarViewActivity activity superactivity this.activity activity 在编写完 CalendarView 类后, 需要在 Main 类中定义该类的变量, 并在onCreate 方法中创建类的对象实例, 代码如下: private CalendarView calendarView calendarView new CalendarViewthis mainLayout.addViewcalendarView 在前面已经介绍过, 在本系统中会将要绘制的日历分成若干块, 而每一块都需要有同样的接口, 以便统一绘制它们。
因此, 这些块都要实现一个CalendarElement 接口。
这些要绘制的块包括日历边框、
网络、日历头等, 而在CalendarElement 接口中有一个 draw 方法。
在绘制日历元素时只需调用 draw 方法即可。
在后面的实现中会看到更多实现 CalendarElement 接口的类, 下面先来编写CalendarElement 接口。
package project.calendar.interfaces import
android.graphics.Canvas public interface CalendarElement public void drawCanvas canvas package project.calendar.interfaces import
android.graphics.Canvas public interface CalendarElement public void drawCanvas canvas 现在需要一个总的类来绘制上述的这些块。
这个功能由 Calendar 类来完成。
Calendar 是一个总的日历元素类, 在该类的 draw 方法中绘制了所有的日历元素。
Calendar 是第一个实现 CalendarElement 接口的类, 代码如下: public class Calendar extends CalendarParent // elements 用于保存多功能日历中所有的日历元素 private ArrayList ltCalendarElement gt elements new ArrayListltCalendarElementgt public CalendarActivity activity View view superactivity view Override public void drawCanvas canvas // 在 draw 方法中通过扫描 elements 变量来获得所 //有日历元素的对象,并调用 draw 方法绘制这些日历元素 for CalendarElement ce : elements ce.drawcanvas 在 CalendarView 类中需要调用 Calendar 类来绘制日历, 因此, 需要在CalendarView 类中创建 Calendar 类的对象实例, 并调用 draw 进行绘制, 代码如下: public Calendar ce Override protected void onDrawCanvas canvas ce.drawcanvas public CalendarViewActivity activity ce new Calendaractivity this 下面编写第一个绘制元素类: Border。
Border 类用于绘制日历的边框, 该类是日历元素类, 需要实现 CalendarElement 接口, 不过该类只要继承刚实现的CalendarParent 类即可。
public class Border extends CalendarParent public BorderActivity activity View view superactivity view // 注意,一定要 4 个字节的颜色值,包括一个透明色 paint.setColor0xFFFFFFFF Override public void drawCanvas canvas float left borderMargin float top borderMargin float right view.getMeasuredWidth - left float bottom view.getMeasuredHeight - top canvas.drawLineleft top right top paint canvas.drawLineright top right bottom paint canvas.drawLineright bottom left bottom paint canvas.drawLineleft bottom left top paint Log.dquotdrawquotString.valueOfright Grid 类用于绘制日历的网格, 该类是日历元素类, 需要继承 CalendarParent类。
public class Grid extends CalendarParent private float top left Override public void drawCanvas canvas left borderMargin top borderMargin weekNameSize weekNameMargin 2 4 float calendarWidth view.getMeasuredWidth - left 2 float calendarHeight view.getMeasuredHeight - top - borderMargin float cellWidth calendarWidth / 7 float cellHeight calendarHeight / 6 paint.setColor0xFFFFFFFF canvas.drawLineleft top left view.getMeasuredWidth - borderMargin 2 top paint paint.setColor0xFF666666 // 画横线 for int i 1 i lt 6 i canvas.drawLine left top cellHeight i left calendar- Widthtop cellHeight i paint// 画竖线for int i 1 i lt 7 icanvas.drawLineleft cellWidth i top left cellWidth iview.getMeasuredHeight - borderMargin paintpublic GridActivity activity View viewsuperactivity view// TODO Auto-generated constructor stubWeek 类用于显示日历网格上方的星期文本:public class Week extends CalendarParentprivate String weekNames new String quot日quot quot一quot quot二quot quot三quot quot四quot quot五quot quot六quot private int weekNameColorpublic WeekActivity activity View viewsuperactivity viewweekNameColor Color.WHITEpaint.setTextSizeweekNameSizeOverridepublic void drawCanvas canvasfloat left borderMarginfloat top borderMarginfloat everyWeekWidth view.getMeasuredWidth - borderMargin 2 / 7 paint.setFakeBoldTexttrue for int i 0 i lt weekNames.length i if i 0 i weekNames.length - 1 paint.setColorsundaySaturdayColor else paint.setColorweekNameColor left borderMargin everyWeekWidth i everyWeekWidth - paint.measureText weekNames i / 2 canvas.drawTextweekNamesi left top paint.getTextSize weekNameMargin paint 4 核心技术 前面介绍了绘制日历的基本方法, 现在将逐步接触到日历系统的核心技术。
首先来看一下日历中如何表示日期。
在 Grid 类中的 days 数组保存了 42 个数字。
这42 个数字就是日历主界面中的 67 个方格中的数字。
这些数字分为两部分, 中间的部分就是当前月中的天数。
这些天数最小是 28 天,最大是 31 天。
在这组数字的前后可以包含了上月的部分月末天数和下月部分月初天数。
当单击或触摸上月或下月的天数时, 日历会跳到上月或下月。
这里内容在后面将详细介绍。
只介绍如何将这些数字绘制到这 42 个方格中。
为了区别这两类数字。
将在上月和下月的相应天数中加星号(), 代码如下: private String days new String42 public int currentYear currentMonth public int currentDay -1 currentDay1 -1 currentDayIndex -1 private java.util.Calendar calendar java.util.Calendar. getInstance 在 Grid 类的构造方法中初始化变量的代码如下: currentYear calendar.getcalendar.YEAR currentMonth calendar.getcalendar.MONTH 下面来编写一个 getMonthDays 方法, 该方法用来获得指定月份的天数。
这个方法也是绘制指定月份的日历的基础, 代码如下: private int getMonthDaysint year int month month switch month case 1: case 3: case 5: case 7: case 8: case 10: case 12: return 31 case 4: case 6: case 9: case 11: return 30 case 2: if year 4 0 ampamp year 100 0 year 400 0 return 29 else return 28 return 0 下面到了关键时刻, 需要基础出当前月的天数, 以及上一月和下一月落在本月初和本月末的天数。
并将其放在 days 数组中。
代码如下: private void calculateDays // 将当前日历设为指定月份的第一天 calendar.setcurrentYear currentMonth 1 // 获得指定月份的第 1 天是当前周的第几天 int week calendar.getcalendar.DAY_OF_WEEK int monthDays 0 int prevMonthDays 0 // 获得当前月有多少天 monthDays getMonthDayscurrentYear currentMonth // 如果当前月是一年中的第一个月,则获得上一年最后一月 //(也就是 12 月)的天数 if currentMonth 0 prevMonthDays getMonthDayscurrentYear - 1 11 // 否则,获得指定月上一月的天数 else prevMonthDays getMonthDays currentYear current- Month - 1 for int i week day prevMonthDays i gt 1 i-- day-- daysi - 2 quotquot String.valueOfday // 设置指定月(在这里是当前月)的天数 for int day 1 i week - 1 day lt monthDays day i daysi String.valueOfday if day currentDay // 获得当前日在 days 数组中的索引 currentDayIndex i // 设置下一月显示在本月日历后面的天数 for int i week monthDays - 1 day 1 i lt days.length i day daysi quotquot String.valueOfday 下面的代码是本例中最核心的部分, 在 onDraw 方法中绘制日历的主界面, 代码如下: // 填充 days 数组 calculateDays java.util.Calendar calendar java.util.Calendar.getInstance int day calendar.getcalendar.DATE int myYear calendar.getcalendar.YEAR Int myMonth calendar.getcalendar.MONTH calendar.setmyYear myMonth1 int week calendar.getcalendar.DAY_OF_WEEK boolean flag false 在 ondraw 方法中添加绘制日历的代码(2): for int i 0 i lt days.length i today falseint row i / 7int col i 7String text String.valueOfdaysi// 如果日历是周日、周六,并且是上一月和下一月的周六和周//日if i 7 0 i - 6 7 0 ampamp text.startsWithquotquotpaint.setColor0xFF990000else if i 7 0 i - 6 7 0paint.setColorsundaySaturdayColorelse if text.startsWithquotquot // 非周六周日,但为上一月的日期paint.setColor0xFF999999elsepaint.setColor0xFFFFFFFF // 普通日历// 去掉上月一下月日.