




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、实用第一智慧密集2011.05实现基于Android的日历系统摘要:Android作为目前较为流行的智能手机操作系统已成为大多数人的首选。在美国乃至世界的很多地方的出货量已经超越Iphone,成为世界上最大智能手机操作系统。因此,世界各地的程序员都跃跃欲试地想学习Android的开发,并希望从中捞得属于自己的第一桶金。在此给出一个基于Android的日历系统的完整实现过程。关键词:Android;日历;绘画;农历;记录;提醒1引言要实现的日历除了常规的日历功能外,还可以显示与当前日期相关的信息,如当前日期的农历日期、天干地支、节日等信息。下面先看看日历的绚丽界面,电/03如图1、图2所示。17
2、:1十二R*月JRIIi一*”凄.场十月甘ft十一,窜眼?闻月IH率单也.图1日历的主界面图2日历的主要功能主要功能2绘画基础由于实现的日历系统要涉及到大量的Android绘图技术,因此,要简单介绍Android的绘图技术。绘制图形通常在Android.view.View或其子类的onDraw方法中进行。该方法的定义如下:protectedvoidonDraw(Canvascanvas);其中Canvas对象提供了大量用于绘图的方法,这些方法主要包括绘制像素点、直线、圆形、弧、文本,这些都是组成复杂图形的基本元素。如果要画更复杂的图形,可以采用组合这些图形基本元素的方式来完成。例如,可以采用画
3、3条直线的方式来画三角形。下面来看一下绘制图形基本元素的方法。2.1 绘制像素点publicnativevoiddrawPoint(floatx,floaty,Paintpaint);/画一个像素点publicnativevoiddrawPoints(floatpts,intoffset,intcount,Paintpaint);/画多个像素点publicvoiddrawPoints(floatpts,Paintpaint);/画多个像素点参数的含义如下:(1) x:像素点的横坐标。(2) y:像素点的纵坐标。(3) paint:描述像素点属性的Paint对象。可设置像素点的大小、颜色等属性。
4、绘制其他图形元素的Paint对象与绘制像素点的Paint对象的含义相同。在绘制具体的图形元素时可根据实际的情况设置Paint对象。(4) pts:drawPoints方法可一次性画多个像素点。pts参数表示多个像素点的坐标。该数组元素必须是偶数个,两个一组为一个像素点的坐标。(5) offset:drawPoints方法可以取pts数组中的一部分连续元素作为像素点的坐标,因此,需要通过offset参数来指定取得数组中连续元素的第一个元素的位置,也就是元素偏移量,从0开始。例如,要从第3个元素开始取数组元素,那么offset参数值就是2。(6) count:要获得的数组元素个数,count必须为
5、偶数(两个数组元素为一个像素点的坐标)。要注意的是,offset可以从任意一个元素开始取值,例如,offset可以为1,然后count为4。2.2 绘制直线publicvoiddrawLine(floatstartX,floatstartY,floatstopX,floatstopY,Paintpaint);/画一条直线publicnativevoiddrawLines(float口pts,intoffset,intcount,Paintpaint);/画多条直线publicvoiddrawLines(floatpts,Paintpaint);/画多条直线参数的含义如下:(1) startX:
6、直线开始端点的横坐标。(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 绘制圆形publicvoiddrawCircle(floatcx
7、,floatcy,floatradius,Paintpaint);参数的含义如下:(1) cx:圆心的横坐标。(2) cy:圆心的纵坐标。(3) radius:圆的半径。D.uceCmter-trueuEeCenter-falseuwCenlEi二true不城灵芾址更埔充it蹙图3填充和设首useCenter参数的效果2.4 绘制弧publicvoiddrawArc(RectFoval,floatstartAngle,floatsweepAngle,booleanuseCenter,Paintpaint);参数的含义如下:(1) oval:弧的外切矩形的坐标。需要设置该矩形的左上角和右下角的坐
8、标,也就是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指定的文本publicnati
9、vevoiddrawText(Stringtext,floatx,floaty,Paintpaint);/绘制text指定的文本。文本中的每一个字符的起始坐标由/pos数组中的值决定。publicvoiddrawPosText(Stringtext,floatpos,Paintpaint);/绘制text指定的文本。text中的每一个字符的起始坐标由/pos数组中的值决定。并且可以选择text中的某一段/连续的字符绘制publicvoiddrawPosText(chartext,intindex,intcount,floatpos,Paintpaint);参数的含义如下:(1) text:dr
10、awText方法中的text参数表示要绘制的文本。drawPostText方法中的text虽然也表示要绘制的文本,但每一个字符的坐标需要单独指定。如果未指定某个字符的坐标,系统会抛出异常。(2) x:绘制文本的起始点的横坐标。(3) y:绘制文本的起始点的纵坐标。(4) index:选定的字符集合在text数组中的索引。count:选定的字符集中字符个数。3绘制日历的框架从图1可以看出,日历的上部是3行文字,显示了当前日期的相关信息。下面来看看如何布局显示这些文字的组件。在日历主界面的上半部需要放置4个组件,1个ImageView组件和3个TextView组件。其中ImageView组件用于显
11、示左上角的图像。3个TextView组件用于显示当前日期的信息。由于目前还没有当前日期的信息。因此,这3个TextView组件暂时设置了固定的信息。下面开始在main.xml文件中设置这4个组件。在修改main.xml文件的内容之前,先复制一个calendar.png文件,作为日历的logo(修改AndroidManifest.xml文件中的应用程序图标)。建立一个Calendar工程,并编写main.xml文件。<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android
12、="<RelativeLayoutandroid:id="+id/calHeader"android:layout_width="fill_parent"android:layout_height="70dp"><ImageViewandroid:id="+id/ivLogo"android:src="drawable/calendar_bak"android:layout_width="dimen/logo_size"android:layout
13、_height="dimen/logo_size"android:layout_margin="dimen/margin"/><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_toRightOf="id/ivLogo"android:layout_marginTop="dimen/margin"android:orien
14、tation="vertical"><TextViewandroid:id="+id/tvMsg1"android:layout_width="fill_parent"android:layout_height="wrap_content"android:textC010r="color/text_color”/><TextViewandroid:id="+id/tvMsg2"android:layout_width="fill_parent"
15、;android:layout_height="wrap_content"android:textC010r="color/text_color”/><TextViewandroid:id="+id/tvMsg3"android:layout_width="fill_parent"android:layout_height="wrap_content"android:textC010r="color/text_color”/></LinearLayout></
16、RelativeLayout></LinearLayout>下面在Main类的Oncreate方法中编写代码装载main.xml:publicvoidonCreate(BundlesavedInstanceState)(super.onCreate(savedlnstanceState);LinearLayoutmainLayout=(LinearLayout)getLayoutInflater().inflate(R.layout.main,null);setContentView(mainLayout);/需要向mainLayout中加入日历网络)在绘制日历之前,要先介绍
17、一下日历绘制的方法。虽然从底层技术来看,绘制日历是在onDraw方法中完成的。但在本系统中将要绘制的部分分成了很多块。而这些要绘制的块都需要放在一个叫CalendarView的类中,代码如下:publicclassCalendarViewextendsViewprivateActivityactivity;OverrideprotectedvoidonDraw(Canvascanvas)publicCalendarView(Activityactivity)super(activity);this.activity=activity;)在编写完CalendarView类后,需要在Main类中定
18、义该类的变量,并在onCreate方法中创建类的对象实例,代码如下:privateCalendarViewcalendarView;calendarView=newCalendarView(this);mainLayout.addView(calendarView);在前面已经介绍过,在本系统中会将要绘制的日历分成若干块,而每一块都需要有同样的接口,以便统一绘制它们。因此,这些块都要实现一个CalendarElement接口。这些要绘制的块包括日历边框、网络、日历头等,而在CalendarElement接口中有一个draw方法。在绘制日历元素时只需调用draw方法即可。在后面的实现中会看到更多
19、实现CalendarElement接口的类,下面先来编写CalendarElement接口。erfaces;importandroid.graphics.Canvas;publicinterfaceCalendarElementpublicvoiddraw(Canvascanvas);)erfaces;importandroid.graphics.Canvas;publicinterfaceCalendarElementpublicvoiddraw(Canvascanvas);)现在需要
20、一个总的类来绘制上述的这些块。这个功能由Calendar类来完成。Calendar是一个总的日历元素类,在该类的draw方法中绘制了所有的日历元素。Calendar是第一个实现CalendarElement接口的类,代码如下:publicclassCalendarextendsCalendarParent(/elements用于保存多功能日历中所有的日历元素privateArrayList<CalendarElement>elements=newArrayList<CalendarElement>();publicCalendar(Activityactivity,Vi
21、ewview)(super(activity,view);Overridepublicvoiddraw(Canvascanvas)(/在draw方法中通过扫描elements变量来获得所/有日历元素的对象,并调用draw方法绘制这些日历元素for(CalendarElementce:elements)ce.draw(canvas);在CalendarView类中需要调用Calendar类来绘制日历,因此,需要在CalendarView类中创建Calendar类的对象实例,并调用draw进行绘制,代码如下:publicCalendarce;OverrideprotectedvoidonDraw(
22、Canvascanvas)(ce.draw(canvas);publicCalendarView(Activityactivity)(ce=newCalendar(activity,this);下面编写第一个绘制元素类:Border。Border类用于绘制日历的边框,该类是日历元素类,需要实现CalendarElement接口,不过该类只要继承刚实现的CalendarParent类即可。publicclassBorderextendsCalendarParent(publicBorder(Activityactivity,Viewview)(super(activity,view);/注意,一
23、定要4个字节的颜色值,包括一个透明色paint.setColor(0xFFFFFFFF);)Overridepublicvoiddraw(Canvascanvas)(floatleft=borderMargin;floattop=borderMargin;floatright=view.getMeasuredWidth()-left;floatbottom=view.getMeasuredHeight()-top;canvas.drawLine(left,top,right,top,paint);canvas.drawLine(right,top,right,bottom,paint);can
24、vas.drawLine(right,bottom,left,bottom,paint);canvas.drawLine(left,bottom,left,top,paint);Log.d("draw",String.valueOf(right);)Grid类用于绘制日历的网格,该类是日历元素类,需要继承CalendarParent类。publicclassGridextendsCalendarParent(privatefloattop,left;Overridepublicvoiddraw(Canvascanvas)(left=borderMargin;top=bord
25、erMargin+weekNameSize+weekNameMargin*2+4;floatcalendarWidth=view.getMeasuredWidth()-left*2;floatcalendarHeight=view.getMeasuredHeight()-top-borderMargin;floatcellWidth=calendarWidth/7;floatcellHeight=calendarHeight/6;paint.setColor(0xFFFFFFFF);canvas.drawLine(left,top,left+view.getMeasuredWidth()-bo
26、rderMargin*2,top,paint);paint.setColor(0xFF666666);/画横线for(inti=1;i<6;i+)(canvas.drawLine(left,top+(cellHeight)*i,left+calendarWidth,top+(cellHeight)*i,paint);)/画竖线for(inti=1;i<7;i+)(canvas.drawLine(left+cellWidth*i,top,left+cellWidth*i,view.getMeasuredHeight()-borderMargin,paint);publicGrid(A
27、ctivityactivity,Viewview)(super(activity,view);/TODOAuto-generatedconstructorstubWeek类用于显示日历网格上方的星期文本:publicclassWeekextendsCalendarParent(privateStringweekNames=newString"日","一","二","三","四","五","六"privateintweekNameColor;publicWe
28、ek(Activityactivity,Viewview)super(activity,view);weekNameC010r=Color.WHITE;paint.setTextSize(weekNameSize);Overridepublicvoiddraw(Canvascanvas)floatleft=borderMargin;floattop=borderMargin;floateveryWeekWidth=(view.getMeasuredWidth()-borderMargin*2)/7;paint.setFakeBoldText(true);for(inti=0;i<week
29、Names.length;i+)if(i=0|i=weekNames.length-1)paint.setColor(sundaySaturdayColor);elsepaint.setColor(weekNameColor);left=borderMargin+everyWeekWidth*i+(everyWeekWidth-paint.measureText(weekNamesi)/2;canvas.drawText(weekNamesi,left,top+paint.getTextSize()+weekNameMargin,paint);4核心技术前面介绍了绘制日历的基本方法,现在将逐步
30、接触到日历系统的核心技术。首先来看一下日历中如何表示日期。在Grid类中的days数组保存了42个数字。这42个数字就是日历主界面中的6*7个方格中的数字。这些数字分为两部分,中间的部分就是当前月中的天数。这些天数最小是28天,最大是31天。在这组数字的前后可以包含了上月的部分月末天数和下月部分月初天数。当单击或触摸上月或下月的天数时,日历会跳到上月或下月。这里内容在后面将详细介绍。只介绍如何将这些数字绘制到这42个方格中。为了区别这两类数字。将在上月和下月的相应天数中加星号(*),代码如下:privateStringdays=newString42;publicintcurrentYear,
31、currentMonth;publicintcurrentDay=-1,currentDay1=-1,currentDayIndex=-1;privatejava.util.Calendarcalendar=java.util.Calendar.getInstance();在Grid类的构造方法中初始化变量的代码如下:currentYear=calendar.get(calendar.YEAR);currentMonth=calendar.get(calendar.MONTH);下面来编写一个getMonthDays方法,该方法用来获得指定月份的天数。这个方法也是绘制指定月份的日历的基础,代码
32、如下:privateintgetMonthDays(intyear,intmonth)month+;switch(month)case1:case3:case5:case 7:case 8:case10:case12:return31;case4:case6:case9:case11:(return30;)case2:(if(year%4=0)&&(year%100!=0)|(year%400=0)return29;elsereturn28;)return0;下面到了关键时刻,需要基础出当前月的天数,以及上一月和下一月落在本月初和本月末的天数。并将其放在days数组中。代码如下
33、:privatevoidcalculateDays()(/将当前日历设为指定月份的第一天calendar.set(currentYear,currentMonth,1);/获得指定月份的第1天是当前周的第几天intweek=calendar.get(calendar.DAY_OF_WEEK);intmonthDays=0;intprevMonthDays=0;/获得当前月有多少天monthDays=getMonthDays(currentYear,currentMonth);/如果当前月是一年中的第一个月,则获得上一年最后一月/(也就是12月)的天数if(currentMonth=0)prev
34、MonthDays=getMonthDays(currentYear-1,11);/否则,获得指定月上一月的天数elseprevMonthDays=getMonthDays(currentYear,currentMonth-1);for(inti=week,day=prevMonthDays;i>1;i-,day-)(daysi-2="*"+String.valueOf(day);/设置指定月(在这里是当前月)的天数for(intday=1,i=week-1;day<=monthDays;day+,i+)(daysi=String.valueOf(day);if
35、(day=currentDay)(/获得当前日在days数组中的索引currentDaylndex=i;)/设置下一月显示在本月日历后面的天数for(inti=week+monthDays-1,day=1;i<days.length;i+,day+)(daysi="*"+String.valueOf(day);下面的代码是本例中最核心的部分,在onDraw方法中绘制日历的主界面,代码如下:/填充days数组calculateDays();java.util.Calendarcalendar=java.util.Calendar.getInstance();intday
36、=calendar.get(calendar.DATE);intmyYear=calendar.get(calendar.YEAR),IntmyMonth=calendar.get(calendar.MONTH);calendar.set(myYear,myMonth,1);intweek=calendar.get(calendar.DAY_OF_WEEK);booleanflag=false;在ondraw方法中添加绘制日历的代码(2):for(inti=0;i<days.length;i+)(today=false;introw=i/7;intcol=i%7;Stringtext=S
37、tring.valueOf(daysi);/如果日历是周日、周六,并且是上一月和下一月的周六和周/日if(i%7=0|(i-6)%7=0)&&text.startsWith("*")(paint.setC010r(0xFF990000);elseif(i%7=0|(i-6)%7=0)(paint.setColor(sundaySaturdayColor);elseif(text.startsWith("*")/非周六周日,但为上一月的日期(paint.setColor(0xFF999999);else(paint.setColor(0xF
38、FFFFFFF);/普通日历)/去掉上月一下月日期前的星号text=text.startsWith("*")?text.substring(l):text;paint.setTextSize(15);floattextLeft=left+cellWidth*col+(cellWidth-paint.measureText(text)/2;floattextTop=top+cellHeight*row+(cellHeight-paint.getTextSize()/2+11;/绘制方格中的文字canvas.drawText(text,textLeft,textTop,pain
39、t);)/会战表示当前日历的图像if(myYear=currentYear&&myMonth=currentMonth&&i=todayindex)(paint.setColor(Color.RED);Bitmapbitmap=BitmapFactory.decodeResource(activity.getResources(),R.drawable.day);Rectsrc=newRect();src.left=0;src.top=0;src.right=bitmap.getWidth();src.bottom=bitmap.getHeight();Rect
40、dst=newRect();dst.left=(int)(left+cellWidth*col);dst.top=(int)(top+cellHeight*row);dst.bottom=(int)(dst.top+cellHeight+1);dst.right=(int)(dst.left+cellWidth+1);/绘制表示当前日期的图像canvas.drawBitmap(bitmap,src,dst,paint);)5触摸事件现在为日历添加一系列动画。首先需要添加的是日历的触摸事件。由于所实现的日历都是通过绘制完成的,因此,在触摸时必须要判断触摸的位置,以确定触摸的是日历的哪一部分。例如
41、,触摸的是哪一天。下面来看看如何为日历添加触摸事件。首先添加两个变量,用于保存当前触摸的坐标。默认值都是-1,表示用户还未触摸:privatefloatcellX=-1,cellY=-1;再加两个setter方法用来设置这个值:publicvoidsetCellX(floatcellX)(this.cellX=cellX;)publicvoidsetCellY(floatcellY)(this.cellY=cellY;)下面来编写一个isBoundary方法,用来判断用户是否触摸了非日历网络部分。publicbooleaninBoundary()(/判断边界if(cellX<borderMargin|cellX>(view.getMeasuredWidth()-borderMargin)|cellY<top|cellY>(view.getMeasuredHeight()-borderMargin)(returnfalse;)else(returntrue;)下面在CalendarView类中添加一个触摸事件方法publicbooleanonTouchEvent(MotionEventmotion)(ce.grid.setCellX(motion.getX();ce.grid.setCellY(motion.getY();if(ce.grid.inBou
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025磁盘制作复制委托合同
- 茶叶知识直播考试内容及答案
- 现代俄语文学题目及答案
- 2025整车货物的运输合同
- 物体表面采样试题及答案
- 2025年公安辅警考核试题及答案
- 2025高考地理试题分类汇编:农业含解析
- 营运车辆保养课件
- 2025汽车租赁合同范本(简化版)
- 2025年人教版七年级语文上册月考试卷(含答案)
- 人美版八年级上册初中美术全册教案
- 平安车辆保险合同电子版
- SYT 6968-2021 油气输送管道工程水平定向钻穿越设计规范-PDF解密
- 中医护理进修脑病科汇报
- 养老机构入住护理、风险评估表、计划表、记录、告知书等健康档案护理记录模板
- 汽车传感器的原理与应用课件
- 《健康评估技术》课件-7.《发绀》
- 《分析化学总复习》课件
- 《生物试卷分析》课件
- 皮肤科常见疾病瘙痒症护理的课件
- 2023年湖北黄石新港(物流)工业园区总工会协理员招考聘用笔试历年难易错点考题荟萃附带答案详解
评论
0/150
提交评论