首页 > 代码库 > 【Sprint3冲刺之前】日历表的事件处理和管理(刘铸辉)
【Sprint3冲刺之前】日历表的事件处理和管理(刘铸辉)
我的Sprint2冲刺——日历表的事件处理和管理(刘铸辉,刘静)
我的Sprint2冲刺计划领到的任务是和静姐结对编程,完成日历表的事件处理和管理,下面详细讲解下技术细节。
1.设计结构图
首先要画出整个UI设计图,方便理解这个日历布局和日历样式的绘制。
这里总共分解为两个 View 文件:
1:calender_main.xml(Calender.java用来绘制日历表和日历表中的事件)
作为启动的主画面,新建项目时,首先生成。
schedule_toptext:用来显示年月日,闰几月,年份和干支
flipper:因为要实现左右滑屏,这里采用的方案是使用 ViewFlipper。我们设计的目标是显示公历 1901 - 2100 年区间的月历,相应的帧画面有 (2100 - 1900) * 12 幅帧画面,如果多创建出来,将占用非常大的内存资源。将由 ViewFlipper 来管理,由它决定某一帧何时创建,何时销毁,以节约内存资源。
2:calender_main.xml(代码在CalenderView.java中)
tvtext:日历gridview中的每一个item显示的textview
2.开始制作 Activity 画面
1.首先绘制整个日历的框架
这里有android指定的类,相关资源都从这里获取http://developer.android.com/guide/topics/providers/calendar-provider.html#intents
1 public CalendarView(){ 2 Date date = new Date(); 3 sysDate = sdf.format(date); //当期日期 4 sys_year = sysDate.split("-")[0]; 5 sys_month = sysDate.split("-")[1]; 6 sys_day = sysDate.split("-")[2]; 7 8 } 9 10 public CalendarView(Context context,Resources rs,int jumpMonth,int jumpYear,int year_c,int month_c,int day_c){ 11 this(); 12 this.context= context; 13 specialCalendar = new SpecialCalendar(); 14 lunarCalendar = new LunarCalendar(); 15 this.res = rs; 16 17 int stepYear = year_c+jumpYear; 18 int stepMonth = month_c+jumpMonth ; 19 if(stepMonth > 0){ 20 //往下一个月滑动 21 if(stepMonth%12 == 0){ 22 stepYear = year_c + stepMonth/12 -1; 23 stepMonth = 12; 24 }else{ 25 stepYear = year_c + stepMonth/12; 26 stepMonth = stepMonth%12; 27 } 28 }else{ 29 //往上一个月滑动 30 stepYear = year_c - 1 + stepMonth/12; 31 stepMonth = stepMonth%12 + 12; 32 if(stepMonth%12 == 0){ 33 34 } 35 } 36 37 currentYear = String.valueOf(stepYear);; //得到当前的年份 38 currentMonth = String.valueOf(stepMonth); //得到本月 (jumpMonth为滑动的次数,每滑动一次就增加一月或减一月) 39 currentDay = String.valueOf(day_c); //得到当前日期是哪天 40 41 getCalendar(Integer.parseInt(currentYear),Integer.parseInt(currentMonth)); 42 43 } 44 45 public CalendarView(Context context,Resources rs,int year, int month, int day){ 46 this(); 47 this.context= context; 48 specialCalendar = new SpecialCalendar(); 49 lunarCalendar = new LunarCalendar(); 50 this.res = rs; 51 currentYear = String.valueOf(year); //得到跳转到的年份 52 currentMonth = String.valueOf(month); //得到跳转到的月份 53 currentDay = String.valueOf(day); //得到跳转到的天 54 55 getCalendar(Integer.parseInt(currentYear),Integer.parseInt(currentMonth)); 56 }
2.给每一个gridview添加相应的文字,月份,农历,节日等信息
这里面有一个要注意的是
农历计算:农历计算的算法,来源于:http://sean.o4u.com/ap/calendar/,包名是LunarCalendar,就不贴代码了,我也是参考的这篇文章
1 //给Gridview添加值 2 @SuppressLint("ResourceAsColor") 3 public View getView(int position, View convertView, ViewGroup parent) { 4 5 if(convertView == null){ 6 convertView = LayoutInflater.from(context).inflate(R.layout.calendar, null); 7 } 8 TextView textView = (TextView) convertView.findViewById(R.id.tvtext); 9 String d = dayNumber[position].split("\\.")[0]; 10 String dv = dayNumber[position].split("\\.")[1]; 11 Log.i("calendarview", d+","+dv); 12 SpannableString sp = new SpannableString(d+"\n"+dv); 13 14 Log.i(Tag, "SpannableString---"+sp); 15 16 sp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, d.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 17 sp.setSpan(new RelativeSizeSpan(1.2f) , 0, d.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 18 sp.setSpan(new TypefaceSpan("monospace"), 0, d.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 19 20 if(dv != null || dv != ""){ 21 //农历显示的样式 22 sp.setSpan(new RelativeSizeSpan(0.75f), d.length()+1, dayNumber[position].length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 23 24 } 25 26 textView.setText(sp); 27 textView.setTextColor(Color.RED); 28 29 // 当前月字体属性,设字体和背景 30 if (position < daysOfMonth + firstDayOfMonth+7 && position >= firstDayOfMonth+7) { 31 32 textView.setTextColor(Color.BLACK);// 当月字体设黑 33 drawable = res.getDrawable(R.drawable.item); 34 textView.setBackgroundDrawable(drawable); 35 //星期日和星期六加红 36 if(position%7==0||position%7==6){ 37 textView.setTextColor(Color.rgb(255,120,20)); 38 } 39 40 }else { 41 42 //设置周的字体属性,如果position为0-6 43 if(position<7){ 44 45 textView.setTextColor(Color.BLACK); 46 textView.setTextSize(14.0f); 47 // textView.setGravity(45); 48 drawable = res.getDrawable(R.drawable.week_top); 49 textView.setBackgroundDrawable(drawable); 50 } 51 //设置当月其他不在月内显示的字体为浅灰色 52 else{ 53 54 textView.setTextColor(Color.rgb(200, 195, 200)); 55 } 56 } 57 if(schDateTagFlag != null && schDateTagFlag.length >0){ 58 for(int i = 0; i < schDateTagFlag.length; i++){ 59 if(schDateTagFlag[i] == position){ 60 //设置有日程安排的标记背景 61 textView.setBackgroundResource(R.drawable.mark); 62 } 63 } 64 } 65 //设置当天的背景 66 if(currentFlag == position){ 67 68 drawable = res.getDrawable(R.drawable.current_day_bgc); 69 textView.setBackgroundDrawable(drawable); 70 textView.setTextColor(Color.WHITE); 71 } 72 //获得每个月的周末 73 Calendar calendar=Calendar.getInstance(); 74 if(calendar.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY||calendar.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY){ 75 textView.setTextColor(Color.rgb(255, 145, 90)); 76 } 77 78 return convertView; 79 } 80 81 //得到某年的某月的天数且这月的第一天是星期几 82 public void getCalendar(int year, int month){ 83 isLeapyear = specialCalendar.isLeapYear(year); //是否为闰年 84 daysOfMonth = specialCalendar.getDaysOfMonth(isLeapyear, month); //某月的总天数 85 firstDayOfMonth = specialCalendar.getWeekdayOfMonth(year, month); //某月第一天为星期几 86 lastDaysOfMonth = specialCalendar.getDaysOfMonth(isLeapyear, month-1); //上一个月的总天数 87 88 Log.d("DAY", isLeapyear+" ====== "+daysOfMonth+" ============ "+firstDayOfMonth+" ========= "+lastDaysOfMonth); 89 getweek(year,month); 90 } 91 92 //将一个月中的每一天的值添加入数组dayNuMber中 93 private void getweek(int year, int month) { 94 int j = 1; 95 int flag = 0; 96 String lunarDay = ""; 97 98 //得到当前月的所有日程日期(这些日期需要标记并计数) 99 dao = new ScheduleDAO(context); 100 ArrayList<ScheduleDateTag> dateTagList = dao.getTagDate(year,month); 101 if(dateTagList != null && dateTagList.size() > 0){ 102 schDateTagFlag = new int[dateTagList.size()]; 103 } 104 105 for (int i = 0; i < dayNumber.length; i++) { 106 // 周一 107 if(i<7){ 108 dayNumber[i]=week[i]+"."+" "; 109 } 110 else if(i < firstDayOfMonth+7){ //前一个月 111 int temp = lastDaysOfMonth - firstDayOfMonth+1-7; 112 //获得阳历对应的农历 113 lunarDay = lunarCalendar.getLunarDate(year, month-1, temp+i,false); 114 dayNumber[i] = (temp + i)+"."+lunarDay; 115 }else if(i < daysOfMonth + firstDayOfMonth+7){ //本月 116 String day = String.valueOf(i-firstDayOfMonth+1-7); 117 //得到的日期 118 lunarDay = lunarCalendar.getLunarDate(year, month, i-firstDayOfMonth+1-7,false); 119 dayNumber[i] = i-firstDayOfMonth+1-7+"."+lunarDay; 120 //对于当前月才去标记当前日期 121 if(sys_year.equals(String.valueOf(year)) && sys_month.equals(String.valueOf(month)) && sys_day.equals(day)){ 122 //标记当前日期 123 currentFlag = i; 124 } 125 126 //标记日程日期 127 if(dateTagList != null && dateTagList.size() > 0){ 128 for(int m = 0; m < dateTagList.size(); m++){ 129 ScheduleDateTag dateTag = dateTagList.get(m); 130 int matchYear = dateTag.getYear(); 131 int matchMonth = dateTag.getMonth(); 132 int matchDay = dateTag.getDay(); 133 if(matchYear == year && matchMonth == month && matchDay == Integer.parseInt(day)){ 134 schDateTagFlag[flag] = i; 135 flag++; 136 } 137 } 138 } 139 140 setShowYear(String.valueOf(year)); 141 setShowMonth(String.valueOf(month)); 142 setAnimalsYear(lunarCalendar.animalsYear(year)); 143 setLeapMonth(lunarCalendar.leapMonth == 0?"":String.valueOf(lunarCalendar.leapMonth)); 144 setCyclical(lunarCalendar.cyclical(year)); 145 }else{ //下一个月 146 lunarDay = lunarCalendar.getLunarDate(year, month+1, j,false); 147 dayNumber[i] = j+"."+lunarDay; 148 j++; 149 } 150 } 151 152 String dayStr = ""; 153 for(int i = 0; i < dayNumber.length; i++){ 154 dayStr = dayStr+dayNumber[i]+":"; 155 } 156 Log.d("calendarview",dayStr); 157 158 159 } 160
3.设计滑动效果ViewFlipper,给每一个滑动过去的gridview,添加一个addGridView
1 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 2 float velocityY) { 3 int gvFlag = 0; //每次添加gridview到viewflipper中时给的标记 4 if (e1.getX() - e2.getX() > 50) { 5 //像左滑动 6 addGridView(); //添加一个gridView 7 jumpMonth++; //下一个月 8 9 calV = new CalendarView(this, getResources(),jumpMonth,jumpYear,year_c,month_c,day_c); 10 gridView.setAdapter(calV); 11 //flipper.addView(gridView); 12 addTextToTopTextView(topText); 13 gvFlag++; 14 flipper.addView(gridView, gvFlag); 15 this.flipper.setInAnimation(AnimationUtils.loadAnimation(this,R.anim.push_left_in)); 16 this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this,R.anim.push_left_out)); 17 this.flipper.showNext(); 18 flipper.removeViewAt(0); 19 return true; 20 } else if (e1.getX() - e2.getX() < -50) { 21 //向右滑动 22 addGridView(); //添加一个gridView 23 jumpMonth--; //上一个月 24 25 calV = new CalendarView(this, getResources(),jumpMonth,jumpYear,year_c,month_c,day_c); 26 gridView.setAdapter(calV); 27 gvFlag++; 28 addTextToTopTextView(topText); 29 flipper.addView(gridView,gvFlag); 30 31 this.flipper.setInAnimation(AnimationUtils.loadAnimation(this,R.anim.push_right_in)); 32 this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this,R.anim.push_right_out)); 33 this.flipper.showPrevious(); 34 flipper.removeViewAt(0); 35 return true; 36 } 37 return false; 38 }
4.添加一个addGridView,并设置GridView的点击事件
1 //添加gridview,显示具体的日期 2 @SuppressLint("ResourceAsColor") 3 private void addGridView() { 4 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( 5 LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); 6 //取得屏幕的宽度和高度 7 WindowManager windowManager = getWindowManager(); 8 Display display = windowManager.getDefaultDisplay(); 9 int Width = display.getWidth(); 10 int Height = display.getHeight(); 11 12 Log.d(Tag, "屏幕分辨率=="+"height*weight"+Height+Width); 13 14 gridView = new GridView(this); 15 gridView.setNumColumns(7); 16 gridView.setColumnWidth(46); 17 if(Width == 480 && Height == 800){ 18 gridView.setColumnWidth(69); 19 }else if(Width==800&&Height==1280){ 20 gridView.setColumnWidth(69); 21 } 22 23 24 gridView.setGravity(Gravity.CENTER_VERTICAL); 25 gridView.setSelector(new ColorDrawable(Color.TRANSPARENT)); // 去除gridView边框 26 gridView.setVerticalSpacing(1); 27 gridView.setHorizontalSpacing(1); 28 gridView.setBackgroundResource(R.drawable.gridview_bk); 29 gridView.setOnTouchListener(new OnTouchListener() { 30 //将gridview中的触摸事件回传给gestureDetector 31 32 public boolean onTouch(View v, MotionEvent event) { 33 // TODO Auto-generated method stub 34 return CalendarActivity.this.gestureDetector 35 .onTouchEvent(event); 36 } 37 }); 38 39 40 gridView.setOnItemClickListener(new OnItemClickListener() { 41 //gridView中的每一个item的点击事件 42 43 public void onItemClick(AdapterView<?> arg0, View arg1, int position, 44 long arg3) { 45 //点击任何一个item,得到这个item的日期(排除点击的是周日到周六(点击不响应)) 46 int startPosition = calV.getStartPositon(); 47 int endPosition = calV.getEndPosition(); 48 if(startPosition <= position && position <= endPosition){ 49 String scheduleDay = calV.getDateByClickItem(position).split("\\.")[0]; //这一天的阳历 50 //String scheduleLunarDay = calV.getDateByClickItem(position).split("\\.")[1]; //这一天的阴历 51 String scheduleYear = calV.getShowYear(); 52 String scheduleMonth = calV.getShowMonth(); 53 String week = ""; 54 55 Log.i("日程历史浏览", scheduleDay); 56 57 //通过日期查询这一天是否被标记,如果标记了日程就查询出这天的所有日程信息 58 scheduleIDs = dao.getScheduleByTagDate(Integer.parseInt(scheduleYear) 59 , Integer.parseInt(scheduleMonth), Integer.parseInt(scheduleDay)); 60 61 //得到这一天是星期几 62 switch(position%7){ 63 case 0: 64 week = "星期日"; 65 break; 66 case 1: 67 week = "星期一"; 68 break; 69 case 2: 70 week = "星期二"; 71 break; 72 case 3: 73 week = "星期三"; 74 break; 75 case 4: 76 week = "星期四"; 77 break; 78 case 5: 79 week = "星期五"; 80 break; 81 case 6: 82 week = "星期六"; 83 break; 84 } 85 86 scheduleDate = new ArrayList<String>(); 87 scheduleDate.add(scheduleYear); 88 scheduleDate.add(scheduleMonth); 89 scheduleDate.add(scheduleDay); 90 scheduleDate.add(week); 91 92 93 LayoutInflater inflater=getLayoutInflater(); 94 View linearlayout= inflater.inflate(R.layout.schedule_detail, null); 95 add=(Button)linearlayout.findViewById(R.id.btn_add); 96 quit=(Button) linearlayout.findViewById(R.id.btn_back); 97 day_tv=(TextView) linearlayout.findViewById(R.id.todayDate); 98 launarDay=(TextView)linearlayout.findViewById(R.id.tv_launar); 99 schdule_tip=(com.dream.tdzhushou.base.BorderTextView)linearlayout.findViewById(R.id.schdule_tip); 100 listView=(ListView)linearlayout.findViewById(R.id.schedulelist1); 101 //星期 102 weekday=(TextView)linearlayout.findViewById(R.id.dayofweek); 103 //农历日期 104 lunarTime=(TextView)linearlayout.findViewById(R.id.lunarTime); 105 list=(ListView)linearlayout.findViewById(R.id.schedulelist1); 106 107 dateInfo=scheduleYear+"年"+scheduleMonth+"月"+scheduleDay+"日"; 108 //添加农历信息 109 String scheduleLunarDay = getLunarDay(Integer.parseInt(scheduleYear), 110 Integer.parseInt(scheduleMonth), Integer.parseInt(scheduleDay)); 111 112 Log.i("LunarDay", scheduleLunarDay); 113 //设置选中的日期的阳历,星期和农历信息 114 day_tv.setText(dateInfo); 115 weekday.setText(week); 116 addLunarDayInfo(lunarTime); 117 launarDay.setText( scheduleLunarDay); 118 119 Log.i("scheduleDate", "scheduleDate的所有信息:"+scheduleDate); 120 //添加日程按钮 121 //TableLayout dialog_tab=(TableLayout) linearlayout.findViewById(R.id.dialog_tab); 122 add.setOnClickListener(new OnClickListener() { 123 124 public void onClick(View v) { 125 // TODO Auto-generated method stub 126 if(builder!=null&&builder.isShowing()){ 127 builder.dismiss(); 128 Intent intent = new Intent(); 129 intent.putStringArrayListExtra("scheduleDate", scheduleDate); 130 intent.setClass(CalendarActivity.this, ScheduleViewAddActivity.class); 131 startActivity(intent); 132 } 133 } 134 }); 135 //返回按钮 136 quit.setOnClickListener(new OnClickListener() { 137 138 public void onClick(View v) { 139 // TODO Auto-generated method stub 140 if(builder!=null&&builder.isShowing()){ 141 builder.dismiss(); 142 } 143 } 144 }); 145 146 //如果被标记,则加载相应的日程信息列表 147 if(scheduleIDs != null && scheduleIDs.length > 0){ 148 149 150 //list.setAdapter(new MyAdapter()); 151 View inflate=getLayoutInflater().inflate(R.layout.schedule_detail_item, null); 152 //通过arraylist绑定数据导listview中去 153 ArrayList<HashMap<String,String>> Data = http://www.mamicode.com/new ArrayList<HashMap<String, String>>(); 154 ScheduleDAO dao=new ScheduleDAO(CalendarActivity.this); 155 String time=""; 156 String content=""; 157 for(int i=0;i<scheduleIDs.length;i++){ 158 scheduleVO=dao.getScheduleByID(CalendarActivity.this,Integer.parseInt(scheduleIDs[i])); 159 time=""; 160 content=""; 161 162 time=dateInfo+" "+scheduleVO.getTime(); 163 content=scheduleVO.getScheduleContent(); 164 165 166 167 HashMap<String, String> map=new HashMap<String, String>(); 168 map.put("date", time); 169 map.put("content", content); 170 Data.add(map); 171 172 } 173 String from[]={"date","content"}; 174 int to[]={R.id.itemTime,R.id.itemContent}; 175 176 SimpleAdapter adapter=new SimpleAdapter(CalendarActivity.this, Data, R.layout.schedule_detail_item, from, to); 177 178 list.setAdapter(adapter); 179 180 //点击list的item相应事件 181 // list.setOnClickListener(CalendarActivity.this); 182 // list.setOnLongClickListener(CalendarActivity.this); 183 184 185 }else{ //如果没有标记位直接则跟换为“暂无安排” 186 187 188 schdule_tip.setText("暂无安排"); 189 listView.setVisibility(View.INVISIBLE); 190 191 192 } 193 194 builder = new Dialog(CalendarActivity.this,R.style.FullScreenDialog); 195 builder.setContentView(linearlayout); 196 WindowManager windowManager = getWindowManager(); 197 Display display = windowManager.getDefaultDisplay(); 198 WindowManager.LayoutParams lp = builder.getWindow().getAttributes(); 199 lp.width = (int)(display.getWidth()); //设置宽度 200 lp.height=display.getHeight(); 201 builder.getWindow().setAttributes(lp); 202 builder.setCanceledOnTouchOutside(true); 203 builder.show(); 204 205 list.setOnItemClickListener(new OnItemClickListener() { 206 207 @Override 208 public void onItemClick(AdapterView<?> adapterview, 209 View view, int position, long id) { 210 211 212 Log.i("日程item点击", "第"+position+"个item"); 213 Intent intent=new Intent(); 214 215 if(view!=null){ 216 217 HashMap<String, String> map=(HashMap<String, String>) adapterview.getItemAtPosition(position); 218 219 ScheduleVO scheduleVO= (ScheduleVO) view.getTag();// 220 Log.i("scheduleVo", "scheduleVO的值="+scheduleVO); 221 222 if(scheduleDate!=null){ 223 //intent.putStringArrayListExtra("scheduleDate", scheduleDate); 224 intent.setClass(CalendarActivity.this,ScheduleInfoDetailActivity.class); 225 intent.putStringArrayListExtra("scheduleDate", scheduleDate); 226 intent.putExtra("scheduleVO", scheduleVO); 227 228 Log.i("scheduleVo", "往intent存放的值"+scheduleVO); 229 startActivity(intent); 230 231 } 232 } 233 234 } 235 }); 236 } 237 } 238 }); 239 gridView.setLayoutParams(params); 240 } 241
使用 ViewPager 是因为我在官方教程里看到了这篇文章:Using ViewPager for Screen Slides,里面还提供了例程下载,再结合上图,可以了解整个过程。
运行的流程按我的理解如下:
<!--[if !supportLists]-->1 首先要点击到每周日历表CalendarActivity执行,当屏幕初始化显示时,调用 onCreate() (这里用回调方式,可以避免对象在内存中创建,但未让屏幕显示时被执行画图处理,可以节约系统开支)
<!--[if !supportLists]-->2 <!--[endif]-->onCreate() 中初始化 ViewFlipper,给出用于页帧管理的对象 CalendarView;并且初始化gridView的设置addGridView设置初始要显示的页码。
<!--[if !supportLists]-->3 初始化日历表和日历表中每一个GridView中的信息后,滑动屏幕,会自动跳转到下一个月的信息,并再次初始化CalendarView,addGridView中的信息,并释放上一个ViewFlipper的资源。
<!--[if !supportLists]-->4 <!--[endif]-->当某一帧要在屏幕上显示时,CalendarView,addGridView类的 onCreateView() 方法被回调,在 onCreateView() 方法里,CalendarView类的 getView 方法接着被调用,在循环里反复调用,直到一整个月所有的单元格被创建。
5.在点击其中一个gridView时,跳转到ScheduleViewAddActivity,给相应的日期添加日程,并保存在数据库中。