• / 9
  • 下载费用:5 金币  

实现基于Android的日历系统.pdf

关 键 词:
实现 基于 ANDROID 日历 系统
资源描述:
实 用第一 智慧密集2011. 05实现基于 Android 的日历系统李 宁1 引言要实现的日历除了常规的日历功能外 , 还可以显示与当前日期相关的信息 , 如当前日期的农历日期 、 天干地支 、 节日等信息 。 下面先看看日历的绚丽界面 , 如图 1、 图 2 所示 。2 绘画基础由于实现的日历系统要涉及到大量的 Android 绘图技术 ,因此 , 要简单介绍 Android 的绘图技术 。绘制图形通常在 Android.view.View 或其子类的 onDraw 方法中进行 。 该方法的定义如下 :protected void onDraw(Canvas canvas);其中 Canvas 对象提供了大量用于绘图的方法 , 这些方法主要包括绘制像素点 、 直线 、 圆形 、 弧 、 文本 , 这些都是组成复杂图形的基本元素 。 如果要画更复杂的图形 , 可以采用组合这些图形基本元素的方式来完成 。 例如 , 可以采用画 3 条直线的方式来画三角形 。 下面来看一下绘制图形基本元素的方法 。2.1 绘制像素点public native void drawPoint(float x, float y, Paint paint);// 画一个像素点public native void drawPoints(float[] pts, int offset, int count,Paint paint); // 画多个像素点public void drawPoints(float[] 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 drawLine (float startX, float startY, float stopX,float stopY,Paint paint);// 画一条直线public native void drawLines(float[] pts, int offset, int count,Paint paint); // 画多条直线public void drawLines(float[] pts, Paint paint);// 画多条直线参数的含义如下 :(1) startX: 直线开始端点的横坐标 。(2) startY: 直线开始端点的纵坐标 。摘 要 : Android 作为目前较为流行的智能手机操作系统已成为大多数人的首选 。 在美国乃至世界的很多地方的出货量已经超越 Iphone, 成为世界上最大智能手机操作系统 。 因此 , 世界各地的程序员都跃跃欲试地想学习 Android 的开发 , 并希望从中捞得属于自己的第一桶金 。 在此给出一个基于 Android 的日历系统的完整实现过程 。关键词 : Android; 日历 ; 绘画 ; 农历 ; 记录 ; 提醒图 1 日历的主界面 图 2 日历的主要功能242011. 05(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, Paintpaint);参数的含义如下 :(1) cx: 圆心的横坐标 。(2) cy: 圆心的纵坐标 。(3) radius: 圆的半径 。2.4 绘制弧public void drawArc (RectF oval, float startAngle, floatsweepAngle, boolean useCenter, Paint paint);参数的含义如下 :(1) oval: 弧的外切矩形的坐标 。 需要设置该矩形的左上角和 右 下 角 的 坐 标 , 也 就 是 oval.left、 oval.top、 oval.right 和oval.bottom。(2) startAngle: 弧的起始角度 。(3) sweepAngle: 弧的结束角度 。 如果 sweepAngle - star-tAngle 的值大于等于 360, drawArc 画的就是一个圆或椭圆 (如果 oval 指定的坐标画出来的是长方形 , drawArc 画的就是椭圆 )。(4) useCenter: 如果该参数值为 true, 在画弧时弧的两个端点会连接圆心 。 如果该参数值为 false, 则只会画弧 。 效果如图 3所示 。 前两个弧未设置填充状态 , 后两个弧设置了填充状态 。2.5 绘制文本// 绘制 text 指定的文本public native void drawText (String text, float x, float y, Paintpaint);// 绘制 text 指定的文本 。 文本中的每一个字符的起始坐标由//pos 数组中的值决定 。public void drawPosText(String text, float[] pos, Paint paint);// 绘制 text 指定的文本 。 text 中的每一个字符的起始坐标由//pos 数组中的值决定 。 并且可以选择 text 中的某一段// 连续的字符绘制public void drawPosText(char[] text, int index, int count, float[] pos,Paint paint);参数的含义如下 :(1) text: drawText 方法中的 text 参数表示要绘制的文本 。drawPostText 方法中的 text 虽然也表示要绘制的文本 , 但每一个字符的坐标需要单独指定 。 如果未指定某个字符的坐标 , 系统会抛出异常 。(2) x: 绘制文本的起始点的横坐标 。(3) y: 绘制文本的起始点的纵坐标 。(4) index: 选定的字符集合在 text 数组中的索引 。(5) count: 选定的字符集中字符个数 。3 绘制日历的框架从图 1 可以看出 , 日历的上部是 3 行文字 , 显示了当前日期的相关信息 。 下面来看看如何布局显示这些文字的组件 。在日历主界面的上半部需要放置 4 个 组 件 , 1 个 Im-ageView 组件和 3 个 TextView 组件 。 其中 ImageView 组件用于显示左上角的图像 。 3 个 TextView 组件用于显示当前日期的信息 。 由于目前还没有当前日期的信息 。 因此 , 这 3 个 TextView组件暂时设置了固定的信息 。下面开始在 main.xml 文件中设置这 4 个 组 件 。 在 修 改main.xml 文件的内容之前 , 先复制一个 calendar.png 文件 , 作为日历的 logo (修改 AndroidManifest.xml 文件中的应用程序图标 )。 建立一个 Calendar 工程 , 并编写 main.xml 文件 。下面在 Main 类的 Oncreate 方法中编写代码装载 main.xml:public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);LinearLayout mainLayout = (LinearLayout) getLayoutIn-flater().inflate(R.layout.main, null);setContentView(mainLayout);// 需要向 mainLayout 中加入日历网络}在绘制日历之前 , 要先介绍一下日历绘制的方法 。 虽然从底层技术来看 , 绘制日历是在 onDraw 方法中完成的 。 但在本系统中将要绘制的部分分成了很多块 。 而这些要绘制的块都需要放在一个叫 CalendarView 的类中 , 代码如下 :public class CalendarView extends View{private Activity activity;@Overrideprotected void onDraw(Canvas canvas){}public CalendarView(Activity activity){super(activity);this.activity = activity;}}在编写完 CalendarView 类后 , 需要在 Main 类中定义该类的变量 , 并在 onCreate 方法中创建类的对象实例 , 代码如下 :private CalendarView calendarView;calendarView = new CalendarView(this);mainLayout.addView(calendarView);在前面已经介绍过 , 在本系统中会将要绘制的日历分成若干块 , 而每一块都需要有同样的接口 , 以便统一绘制它们 。 因此 , 这些块都要实现一个 CalendarElement 接口 。这些要绘制的块包括日历边框 、 网络 、 日历头等 , 而在CalendarElement 接口中有一个 draw 方法 。 在绘制日历元素时只需调用 draw 方法即可 。 在后面的实现中会看到更多实现 Calen-darElement 接口的类 , 下面先来编写 CalendarElement 接口 。package project.calendar.interfaces;import android.graphics.Canvas;public interface CalendarElement{public void draw(Canvas canvas);}package project.calendar.interfaces;import android.graphics.Canvas;public interface CalendarElement{public void draw(Canvas canvas);}现在需要一个总的类来绘制上述的这些块 。 这个功能由Calendar 类来完成 。 Calendar 是一个总的日历元素类 , 在该类的 draw 方法中绘制了所有的日历元素 。 Calendar 是第一个实现CalendarElement 接口的类 , 代码如下 :public class Calendar extends CalendarParent{// elements 用于保存多功能日历中所有的日历元素private ArrayList elements = newArrayList();public Calendar(Activity activity, View view){super(activity, view);}@Overridepublic void draw(Canvas canvas){// 在 draw 方法中通过扫描 elements 变量来获得所//有日历元素的对象 ,并调用 draw 方法绘制这些日历元素for (CalendarElement ce : elements)ce.draw(canvas);}}在 CalendarView 类中需要调用 Calendar 类来绘制日历 , 因此 , 需要在 CalendarView 类中创建 Calendar 类的对象实例 , 并调用 draw 进行绘制 , 代码如下 :public Calendar ce;@Overrideprotected void onDraw(Canvas canvas){ce.draw(canvas);}public CalendarView(Activity activity){ce = new Calendar(activity, this);}下面编写第一个绘制元素类 : Border。 Border 类用于绘制日历的边框 , 该类是日历元素类 , 需要实现 CalendarElement接口 , 不过该类只要继承刚实现的 CalendarParent 类即可 。public class Border extends CalendarParent262011. 05{public Border(Activity activity, View view){super(activity, view);// 注意 ,一定要 4 个字节的颜色值 ,包括一个透明色paint.setColor(0xFFFFFFFF);}@Overridepublic void draw(Canvas canvas){float left = borderMargin;float top = borderMargin;float right = view.getMeasuredWidth() - left;float bottom = view.getMeasuredHeight() - top;canvas.drawLine(left, top, right, top, paint);canvas.drawLine(right, top, right, bottom, paint);canvas.drawLine(right, bottom, left, bottom, paint);canvas.drawLine(left, bottom, left, top, paint);Log.d(“draw“,String.valueOf(right));}}Grid 类用于绘制日历的网格 , 该类是日历元素类 , 需要继承 CalendarParent 类 。public class Grid extends CalendarParent{private float top, left;@Overridepublic void draw(Canvas 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.setColor(0xFFFFFFFF);canvas.drawLine(left, top, left + view.getMeasuredWidth()- borderMargin * 2, top, paint);paint.setColor(0xFF666666);// 画横线for (int i = 1; i 1; i--, day--){days[i - 2] = “*“ + String.valueOf(day);}// 设置指定月 (在这里是当前月 )的天数for (int day = 1, i = week - 1; day (view.getMeasuredWidth() - borderMargin)|| cellY (view.getMeasuredHeight() - borderMargin)){return false;}else{return true;}}下面在 CalendarView 类中添加一个触摸事件方法public boolean onTouchEvent(MotionEvent motion){ce.grid.setCellX(motion.getX());ce.grid.setCellY(motion.getY());if (ce.grid.inBoundary()){this.invalidate();}return super.onTouchEvent(motion);}现在来修改 Grid 类 , 在该类中需要获得农历信息 , 这是一个现成的类库 (在文中提供的源代码中可以找到 , Lunar29实 用第一 智慧密集2011. 05类 ), 可以直接使用 。private Lunar lunar = new Lunar();private int today;// 保存月的名称 (一至十二月 )private String[] monthNames = new String[12];private TextView tvMsg1;private TextView tvMsg2;private TextView tvMsg3;由于系统中需要使用月份信息 , 因此 , 需要在 res\values目录中建立一个 values.xml 文件 , 并输入要用到的月份信息 。一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月 下面继续修改 Grid 类 , 在构造方法中添加如下代码 :today = currentDay;tvMsg1 = (TextView) activity.findViewById(R.id.tvMsg1);tvMsg2 = (TextView) activity.findViewById(R.id.tvMsg2);tvMsg3 = (TextView) activity.findViewById(R.id.tvMsg3);// 装载刚才定义的资源monthNames = activity.getResources().getStringArray(R.array.month_name);在切换到相应的日期后 , 需要在屏幕的正上方显示当前日期的信息 。 显示的内容如图 1 所示 。 这些功能由 updateMsg 方法实现 , 代码如下 :private void updateMsg(boolean today){String monthName = monthNames[currentMonth];String dateString = ““;SimpleDateFormat sdf = new SimpleDateFormat(“yyyy年 m 月 d 日 “);java.util.Calendar calendar = java.util.Calendar.getInstance();calendar.set(currentYear, currentMonth, currentDay);dateString = sdf.format(calendar.getTime());String lunarStr = ““;lunar.setDate(calendar.getTime());lunarStr = lunar.getAnimalString() + “年 (“;lunarStr += lunar.getCyclicaYear() + “年 )“;lunarStr += lunar.getLunarMonthString() + “月 “;lunarStr += lunar.getLunarDayString();String term = lunar.getTermString();if (! ““.equals(term))term += “ “;monthName += “ 本月第 “ + calendar.get(java.util.Cal-endar.WEEK_OF_MONTH)+ “周 “;tvMsg1.setText(monthName);if (today)dateString += “(今天 )“;dateString += “ 本年第 “ + calendar.get(java.util.Calen-dar.WEEK_OF_YEAR)+ “周 “;tvMsg2.setText(dateString);tvMsg3.setText(term + lunarStr);}6 键盘操作介绍如何通过手机按键来操作日历 , 也就是通过按建来移动日历 。 另外一个功能是当日历移动到上月或下月的日期时切换到上月或下月的日历 。下面看看如何通过按键来操作日历 , 首先要在 Grid 类中添加几个变量 , 用来控制当前的日历坐标 。private int currentRow, currentCol;private boolean redrawForKeyDown = false;在使用键盘来控制日历时 , 当按下手机按键的上 、 下 、左 、 右时 , 会调用 setCurrentRow、 setCurrentCol 方法来更新当前的坐标 (横 、 纵坐标 )。 setCurrentRow 方法的代码如下 :public void setCurrentRow(int currentRow){redrawForKeyDown = true;cellX = -1;cellX = -1;if (currentRow >= 0 setCurrentRow(--currentRow);}else302011. 05{this.currentCol = 0;}}}else if (currentCol > 6){this.currentCol = 0;setCurrentRow(++currentRow);}else{this.currentCol = currentCol;}}最后修改 CalendarView 类的代码 , 加入键盘触摸事件 ,代码如下 :@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event){switch (keyCode){case KeyEvent.KEYCODE_DPAD_UP:{ce.grid.setCurrentRow(ce.grid.getCurrentRow() - 1);break;}case KeyEvent.KEYCODE_DPAD_DOWN:{ce.grid.setCurrentRow(ce.grid.getCurrentRow() + 1);break;}case KeyEvent.KEYCODE_DPAD_LEFT:{ce.grid.setCurrentCol(ce.grid.getCurrentCol() - 1);break;}case KeyEvent.KEYCODE_DPAD_RIGHT:{ce.grid.setCurrentCol(ce.grid.getCurrentCol() + 1);break;}}invalidate();return true;}7 显示当前日期显示当前日期的详细信息是本系统的主要功能之一 。 这个功能也是将 Web 技术和 Android 相结合的典型案例 。 下面来看看是如何来实现这个功能的 。 首先来看看实现效果 , 如图 4 所示 。虽然 JavaScript 有着丰富的函数库 , 但仍然有很多无法完成的工作 , 例如 , 对硬件的访问 。 不过 WebView 为 JavaScript提供了一种强有力的扩展 , 通过这种扩展 , 可以在 JavaScript中象调用 JavaScript 函数一样调用 Java 代码 。 因此 , JavaScript也就拥有了同 Java 一样的能力 。通过 WebView 组件使 JavaScript 调用 Java 方法 , 首先需要打开 WebView 的 JavaScript 支持 , 代码如下 :webSettings.setJavaScriptEnabled(true);//然后使用 addJavascriptInterface 方法添加 JavaScript 和 Java//方法的映射 。public void addJavascriptInterface (Object obj, String inter-faceName);建立一个空的 OnMsgMenuItemClick, 代码如下 :pub lic class OnMsgMenuItemClick implements OnMenu-ItemClickListener{private CalendarView calendarView;public OnMsgMenuItemClick (CalendarView calen-darView){this.calendarView = calendarView;}@Overridepublic boolean onMenuItemClick(MenuItem item){return true;}}下面来编写布局文件 msg.xml。下面需要使用一个 Lunar 类 (在前面曾使用过 ) 来获得当前日期的农历信息 , 代码如下 :private Lunar lunar = new Lunar();private java.util.Calendar calendar = java.util.Calendar.getInstance();private String dateString, weekString, lunarDate, term,festival, lunarFestival,description;从图 4 看出在上方显示了与当前年相匹配的 12 天干 。 这个功能需要通过 loadAnimal 方法来完成 。 这个方法要通过 Lunar类的 getAnimalString 方法获得当前年的天干 , 然后通过比较来确定要显示哪正值天干的图像 。 loadAnimal 方法的代码如下 :private void loadAnimal(){ImageView ivMsgImage = (ImageView) findViewById(R.id.ivSXImage);ImageView ivMsgText = (ImageView) findViewById(R.id.ivSXText);if (“鼠 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a01);ivMsgText.setImageResource(R.drawable.b01);}else if (“牛 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a02);ivMsgText.setImageResource(R.drawable.b02);}else if (“虎 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a03);ivMsgText.setImageResource(R.drawable.b03);}else if (“兔 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a04);ivMsgText.setImageResource(R.drawable.b04);}else if (“龙 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a05);ivMsgText.setImageResource(R.drawable.b05);}else if (“蛇 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a06);ivMsgText.setImageResource(R.drawable.b06);}else if (“马 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a07);ivMsgText.setImageResource(R.drawable.b07);}else if (“羊 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a08);ivMsgText.setImageResource(R.drawable.b08);}else if (“猴 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a09);ivMsgText.setImageResource(R.drawable.b09);}else if (“鸡 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a10);ivMsgText.setImageResource(R.drawable.b10);}else if (“狗 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a11);ivMsgText.setImageResource(R.drawable.b11);}else if (“猪 “.equals(lunar.getAnimalString())){ivMsgImage.setImageResource(R.drawable.a12);ivMsgText.setImageResource(R.drawable.b12);}}8 结语给出基于 Android 的日历系统的核心代码 。 本系统全部的代码已放到文章中 , 感兴趣的读者可以查看源代码 。 在这个系统中涉及了多项 Android 技术 , 其中包括图形技术 、 Web 技术 、 数据库技术等 。 通过深入研究本系统的技术可以实现更丰富多彩的 Android 应用程序 。(收稿日期 : 2010-12-27)32
展开阅读全文
1
  金牌文库所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
0条评论

还可以输入200字符

暂无评论,赶快抢占沙发吧。

关于本文
本文标题:实现基于Android的日历系统.pdf
链接地址:http://www.gold-doc.com/p-255418.html
收起
展开