这里主要记录一下在编写日历apk过程中一些主要的点:先看下效果图

android 日历开发附源码(附源码)_第1张图片

一、主要功能

  • 1、支持农历、节气、常用节假日
  • 2、使用数据库,设置计划

二、基本结构

我们要实现的日历控件采用GestureDetector构造器,使用OnGestureListener监听滑动。目前我们设定日历左右滑动为月份切换的操作,每一个月份显示通过GridView实现,里面的数据是通过构造CalendarView,将其绑定到GridView。每次左右滑动,都会刷新CalendarView。布局上,会在GridView上显示当前日期农历时间。

三、主要代码及解析

CalendarActivity.java
/** * 日历显示activity * * @author 孔乙己大叔 */public class CalendarActivity extends Activity implements OnGestureListener {    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        gestureDetector = new GestureDetector(this, this);        flipper = (ViewFlipper) findViewById(R.id.flipper);        flipper.removeAllViews();        calV = new CalendarView(this, getResources(), jumpMonth, jumpYear, year_c, month_c, day_c);        addGridView();        gridView.setAdapter(calV);        flipper.addView(gridView, 0);        topText = (BorderText) findViewById(R.id.toptext);        addTextToTopTextView(topText);    }    @Override    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {        int gvFlag = 0;         //每次添加gridview到viewflipper中时给的标记        if (e1.getX() - e2.getX() > 120) {            //像左滑动            addGridView();   //添加一个gridView            jumpMonth++;     //下一个月            calV = new CalendarView(this, getResources(), jumpMonth, jumpYear, year_c, month_c, day_c);            gridView.setAdapter(calV);            addTextToTopTextView(topText);            gvFlag++;            flipper.addView(gridView, gvFlag);            this.flipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in));            this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_out));            this.flipper.showNext();            flipper.removeViewAt(0);            return true;        } else if (e1.getX() - e2.getX() < -120) {            //向右滑动            addGridView();   //添加一个gridView            jumpMonth--;     //上一个月            calV = new CalendarView(this, getResources(), jumpMonth, jumpYear, year_c, month_c, day_c);            gridView.setAdapter(calV);            gvFlag++;            addTextToTopTextView(topText);            //flipper.addView(gridView);            flipper.addView(gridView, gvFlag);            this.flipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_in));            this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_out));            this.flipper.showPrevious();            flipper.removeViewAt(0);            return true;        }        return false;    }    /**     * 创建菜单     */    @Override    public boolean onCreateOptionsMenu(Menu menu) {        menu.add(0, menu.FIRST, menu.FIRST, "今天");        menu.add(0, menu.FIRST + 1, menu.FIRST + 1, "跳转");        menu.add(0, menu.FIRST + 2, menu.FIRST + 2, "日程");        menu.add(0, menu.FIRST + 3, menu.FIRST + 3, "日期转换");        return super.onCreateOptionsMenu(menu);    }    /**     * 选择菜单     */    @Override    public boolean onMenuItemSelected(int featureId, MenuItem item) {        switch (item.getItemId()) {            case Menu.FIRST:                //跳转到今天                int xMonth = jumpMonth;                int xYear = jumpYear;                int gvFlag = 0;                jumpMonth = 0;                jumpYear = 0;                addGridView();   //添加一个gridView                year_c = Integer.parseInt(currentDate.split("-")[0]);                month_c = Integer.parseInt(currentDate.split("-")[1]);                day_c = Integer.parseInt(currentDate.split("-")[2]);                calV = new CalendarView(this, getResources(), jumpMonth, jumpYear, year_c, month_c, day_c);                gridView.setAdapter(calV);                addTextToTopTextView(topText);                gvFlag++;                flipper.addView(gridView, gvFlag);                if (xMonth == 0 && xYear == 0) {                    //nothing to do                } else if ((xYear == 0 && xMonth > 0) || xYear > 0) {                    this.flipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in));                    this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_out));                    this.flipper.showNext();                } else {                    this.flipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_in));                    this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_out));                    this.flipper.showPrevious();                }                flipper.removeViewAt(0);                break;            case Menu.FIRST + 1:                new DatePickerDialog(this, new OnDateSetListener() {                    @Override                    public void onDateSet(DatePicker view, int year, int monthOfYear,                                          int dayOfMonth) {                        //1901-1-1 ----> 2049-12-31                        if (year < 1901 || year > 2049) {                            //不在查询范围内                            new AlertDialog.Builder(CalendarActivity.this).setTitle("错误日期").setMessage("跳转日期范围(1901/1/1-2049/12/31)").setPositiveButton("确认", null).show();                        } else {                            int gvFlag = 0;                            addGridView();   //添加一个gridView                            calV = new CalendarView(CalendarActivity.this, CalendarActivity.this.getResources(), year, monthOfYear + 1, dayOfMonth);                            gridView.setAdapter(calV);                            addTextToTopTextView(topText);                            gvFlag++;                            flipper.addView(gridView, gvFlag);                            if (year == year_c && monthOfYear + 1 == month_c) {                                //nothing to do                            }                            if ((year == year_c && monthOfYear + 1 > month_c) || year > year_c) {                                CalendarActivity.this.flipper.setInAnimation(AnimationUtils.loadAnimation(CalendarActivity.this, R.anim.push_left_in));                                CalendarActivity.this.flipper.setOutAnimation(AnimationUtils.loadAnimation(CalendarActivity.this, R.anim.push_left_out));                                CalendarActivity.this.flipper.showNext();                            } else {                                CalendarActivity.this.flipper.setInAnimation(AnimationUtils.loadAnimation(CalendarActivity.this, R.anim.push_right_in));                                CalendarActivity.this.flipper.setOutAnimation(AnimationUtils.loadAnimation(CalendarActivity.this, R.anim.push_right_out));                                CalendarActivity.this.flipper.showPrevious();                            }                            flipper.removeViewAt(0);                            //跳转之后将跳转之后的日期设置为当期日期                            year_c = year;                            month_c = monthOfYear + 1;                            day_c = dayOfMonth;                            jumpMonth = 0;                            jumpYear = 0;                        }                    }                }, year_c, month_c - 1, day_c).show();                break;            case Menu.FIRST + 2:                Intent intent = new Intent();                intent.setClass(CalendarActivity.this, ScheduleAll.class);                startActivity(intent);                break;            case Menu.FIRST + 3:                Intent intent1 = new Intent();                intent1.setClass(CalendarActivity.this, CalendarConvert.class);                intent1.putExtra("date", new int[]{year_c, month_c, day_c});                startActivity(intent1);                break;        }        return super.onMenuItemSelected(featureId, item);    }        //添加头部的年份 闰哪月等信息    public void addTextToTopTextView(TextView view) {        StringBuffer textDate = new StringBuffer();        view.setBackgroundResource(R.drawable.top_day);        view.setBackground(getResources().getDrawable(R.drawable.top_day));        textDate.append(calV.getShowYear()).append("年").append(calV.getShowMonth()).append("月").append("\t");        if (!calV.getLeapMonth().equals("") && calV.getLeapMonth() != null) {            textDate.append("闰").append(calV.getLeapMonth()).append("月").append("\t");        }        textDate.append(calV.getAnimalsYear()).append("年").append("(").append(calV.getCyclical()).append("年)");        view.setText(textDate);        view.setTextColor(Color.BLACK);        view.setTypeface(Typeface.DEFAULT_BOLD);    }    //添加gridview    private void addGridView() {        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(                LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);        DisplayMetrics displayMetrics = new DisplayMetrics();        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);        int Width = displayMetrics.widthPixels;        int Height = displayMetrics.heightPixels;        gridView = new GridView(this);        gridView.setNumColumns(7);        gridView.setColumnWidth(46);        if (Width == 480 && Height == 800) {            gridView.setColumnWidth(69);        }        gridView.setGravity(Gravity.CENTER_VERTICAL);        gridView.setSelector(new ColorDrawable(Color.TRANSPARENT)); // 去除gridView边框        gridView.setVerticalSpacing(1);        gridView.setHorizontalSpacing(1);        gridView.setBackgroundResource(R.drawable.gridview_bk);        gridView.setOnTouchListener(new OnTouchListener() {            //将gridview中的触摸事件回传给gestureDetector            @Override            public boolean onTouch(View v, MotionEvent event) {                // TODO Auto-generated method stub                return CalendarActivity.this.gestureDetector                        .onTouchEvent(event);            }        });        gridView.setOnItemClickListener(new OnItemClickListener() {            //gridView中的每一个item的点击事件            @Override            public void onItemClick(AdapterView<?> arg0, View arg1, int position,                                    long arg3) {                //点击任何一个item,得到这个item的日期(排除点击的是周日到周六(点击不响应))                int startPosition = calV.getStartPositon();                int endPosition = calV.getEndPosition();                if (startPosition <= position && position <= endPosition) {                    String scheduleDay = calV.getDateByClickItem(position).split("\\.")[0];  //这一天的阳历                    String scheduleYear = calV.getShowYear();                    String scheduleMonth = calV.getShowMonth();                    String week = "";                    //通过日期查询这一天是否被标记,如果标记了日程就查询出这天的所有日程信息                    String[] scheduleIDs = dao.getScheduleByTagDate(Integer.parseInt(scheduleYear), Integer.parseInt(scheduleMonth), Integer.parseInt(scheduleDay));                    if (scheduleIDs != null && scheduleIDs.length > 0) {                        //跳转到显示这一天的所有日程信息界面                        Intent intent = new Intent();                        intent.setClass(CalendarActivity.this, ScheduleInfoView.class);                        intent.putExtra("scheduleID", scheduleIDs);                        startActivity(intent);                    } else {                        //直接跳转到需要添加日程的界面                        //得到这一天是星期几                        switch (position % 7) {                            case 0:                                week = "星期日";                                break;                            case 1:                                week = "星期一";                                break;                            case 2:                                week = "星期二";                                break;                            case 3:                                week = "星期三";                                break;                            case 4:                                week = "星期四";                                break;                            case 5:                                week = "星期五";                                break;                            case 6:                                week = "星期六";                                break;                        }                        ArrayList scheduleDate = new ArrayList();                        scheduleDate.add(scheduleYear);                        scheduleDate.add(scheduleMonth);                        scheduleDate.add(scheduleDay);                        scheduleDate.add(week);                        //scheduleDate.add(scheduleLunarDay);                        Intent intent = new Intent();                        intent.putStringArrayListExtra("scheduleDate", scheduleDate);                        intent.setClass(CalendarActivity.this, ScheduleView.class);                        startActivity(intent);                    }                }            }        });        gridView.setLayoutParams(params);    }}

自定义view实现:

/** * 日历gridview中的每一个item显示的textview * * @author 孔乙己大叔 */public class CalendarView extends BaseAdapter {    public CalendarView(Context context, Resources rs, int jumpMonth, int jumpYear, int year_c, int month_c, int day_c) {        this();        this.context = context;        sc = new SpecialCalendar();        lc = new LunarCalendar();        this.res = rs;        int stepYear = year_c + jumpYear;        int stepMonth = month_c + jumpMonth;        if (stepMonth > 0) {            //往下一个月滑动            if (stepMonth % 12 == 0) {                stepYear = year_c + stepMonth / 12 - 1;                stepMonth = 12;            } else {                stepYear = year_c + stepMonth / 12;                stepMonth = stepMonth % 12;            }        } else {            //往上一个月滑动            stepYear = year_c - 1 + stepMonth / 12;            stepMonth = stepMonth % 12 + 12;            if (stepMonth % 12 == 0) {            }        }        currentYear = String.valueOf(stepYear);;  //得到当前的年份        currentMonth = String.valueOf(stepMonth);  //得到本月 (jumpMonth为滑动的次数,每滑动一次就增加一月或减一月)        currentDay = String.valueOf(day_c);  //得到当前日期是哪天        getCalendar(Integer.parseInt(currentYear), Integer.parseInt(currentMonth));    }    public CalendarView(Context context, Resources rs, int year, int month, int day) {        this();        this.context = context;        sc = new SpecialCalendar();        lc = new LunarCalendar();        this.res = rs;        currentYear = String.valueOf(year);        ;  //得到跳转到的年份        currentMonth = String.valueOf(month);  //得到跳转到的月份        currentDay = String.valueOf(day);  //得到跳转到的天        getCalendar(Integer.parseInt(currentYear), Integer.parseInt(currentMonth));    }    @Override    public int getCount() {        // TODO Auto-generated method stub        return dayNumber.length;    }    @Override    public Object getItem(int position) {        // TODO Auto-generated method stub        return position;    }    @Override    public long getItemId(int position) {        // TODO Auto-generated method stub        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        if (convertView == null) {            convertView = LayoutInflater.from(context).inflate(R.layout.calendar, null);        }        TextView textView = (TextView) convertView.findViewById(R.id.tvtext);        String d = dayNumber[position].split("\\.")[0];        String dv = dayNumber[position].split("\\.")[1];        //Typeface typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Helvetica.ttf");        //textView.setTypeface(typeface);        SpannableString sp = new SpannableString(d + "\n" + dv);        sp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, d.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);        sp.setSpan(new RelativeSizeSpan(1.2f), 0, d.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);        if (dv != null || dv != "") {            sp.setSpan(new RelativeSizeSpan(0.75f), d.length() + 1, dayNumber[position].length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);        }        //sp.setSpan(new ForegroundColorSpan(Color.MAGENTA), 14, 16, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)        textView.setText(sp);        textView.setTextColor(Color.GRAY);        if (position < 7) {            //设置周            textView.setTextColor(Color.BLACK);            textView.setBackgroundResource(R.drawable.week_top);        }        if (position < daysOfMonth + dayOfWeek + 7 && position >= dayOfWeek + 7) {            // 当前月信息显示            textView.setTextColor(Color.BLACK);// 当月字体设黑            drawable = res.getDrawable(R.drawable.item);            //textView.setBackgroundDrawable(drawable);            //textView.setBackgroundColor(Color.WHITE);        }        if (schDateTagFlag != null && schDateTagFlag.length > 0) {            for (int i = 0; i < schDateTagFlag.length; i++) {                if (schDateTagFlag[i] == position) {                    //设置日程标记背景                    textView.setBackgroundResource(R.drawable.mark);                }            }        }        if (currentFlag == position) {            //设置当天的背景            textView.setBackgroundResource(R.drawable.current_day_bgc);            textView.setTextColor(Color.WHITE);        }        return convertView;    }    //得到某年的某月的天数且这月的第一天是星期几    public void getCalendar(int year, int month) {        isLeapyear = sc.isLeapYear(year);              //是否为闰年        daysOfMonth = sc.getDaysOfMonth(isLeapyear, month);  //某月的总天数        dayOfWeek = sc.getWeekdayOfMonth(year, month);      //某月第一天为星期几        lastDaysOfMonth = sc.getDaysOfMonth(isLeapyear, month - 1);  //上一个月的总天数        Log.d("DAY", isLeapyear + " ======  " + daysOfMonth + "  ============  " + dayOfWeek + "  =========   " + lastDaysOfMonth);        getweek(year, month);    }    //将一个月中的每一天的值添加入数组dayNuber中    private void getweek(int year, int month) {        int j = 1;        int flag = 0;        String lunarDay = "";        //得到当前月的所有日程日期(这些日期需要标记)        dao = new ScheduleDAO(context);        ArrayList dateTagList = dao.getTagDate(year, month);        if (dateTagList != null && dateTagList.size() > 0) {            schDateTagFlag = new int[dateTagList.size()];        }        for (int i = 0; i < dayNumber.length; i++) {            // 周一            if (i < 7) {                dayNumber[i] = week[i] + "." + " ";            } else if (i < dayOfWeek + 7) {  //前一个月                int temp = lastDaysOfMonth - dayOfWeek + 1 - 7;                lunarDay = lc.getLunarDate(year, month - 1, temp + i, false);                dayNumber[i] = (temp + i) + "." + lunarDay;            } else if (i < daysOfMonth + dayOfWeek + 7) {   //本月                String day = String.valueOf(i - dayOfWeek + 1 - 7);   //得到的日期                lunarDay = lc.getLunarDate(year, month, i - dayOfWeek + 1 - 7, false);                dayNumber[i] = i - dayOfWeek + 1 - 7 + "." + lunarDay;                //对于当前月才去标记当前日期                if (sys_year.equals(String.valueOf(year)) && sys_month.equals(String.valueOf(month)) && sys_day.equals(day)) {                    //笔记当前日期                    currentFlag = i;                }                //标记日程日期                if (dateTagList != null && dateTagList.size() > 0) {                    for (int m = 0; m < dateTagList.size(); m++) {                        ScheduleDateTag dateTag = dateTagList.get(m);                        int matchYear = dateTag.getYear();                        int matchMonth = dateTag.getMonth();                        int matchDay = dateTag.getDay();                        if (matchYear == year && matchMonth == month && matchDay == Integer.parseInt(day)) {                            schDateTagFlag[flag] = i;                            flag++;                        }                    }                }                setShowYear(String.valueOf(year));                setShowMonth(String.valueOf(month));                setAnimalsYear(lc.animalsYear(year));                setLeapMonth(lc.leapMonth == 0 ? "" : String.valueOf(lc.leapMonth));                setCyclical(lc.cyclical(year));            } else {   //下一个月                lunarDay = lc.getLunarDate(year, month + 1, j, false);                dayNumber[i] = j + "." + lunarDay;                j++;            }        }        String abc = "";        for (int i = 0; i < dayNumber.length; i++) {            abc = abc + dayNumber[i] + ":";        }        Log.d("DAYNUMBER", abc);    }  }

判断是否为闰年,当月多少天数,当天是星期几代码实现:

// 判断是否为闰年    public boolean isLeapYear(int year) {        if (year % 100 == 0 && year % 400 == 0) {            return true;        } else if (year % 100 != 0 && year % 4 == 0) {            return true;        }        return false;    }    //得到某月有多少天数    public int getDaysOfMonth(boolean isLeapyear, int month) {        switch (month) {            case 1:            case 3:            case 5:            case 7:            case 8:            case 10:            case 12:                daysOfMonth = 31;                break;            case 4:            case 6:            case 9:            case 11:                daysOfMonth = 30;                break;            case 2:                if (isLeapyear) {                    daysOfMonth = 29;                } else {                    daysOfMonth = 28;                }        }        return daysOfMonth;    }    //指定某年中的某月的第一天是星期几    public int getWeekdayOfMonth(int year, int month) {        Calendar cal = Calendar.getInstance();        cal.set(year, month - 1, 1);        dayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1;        return dayOfWeek;    }

四、小结

这里我们只介绍了日历的基本实现原理,和一些关键的点,其实这种实现方式相对还是比较简单的,容易理解,当然难免有不足的地方,后边根据需要再逐步完善和扩展吧。数据库操作暂时没进行解析,后面会单独用demo说明。

源码下载地址:https://download.csdn.net/download/Ctrl_qun/12436629

更多相关文章

  1. Android中关于日期时间与时区的使用总结
  2. android 日期按钮实现
  3. android datepicker只显示年和日期
  4. 【Android】对话框之日期和时间对话框
  5. Android下常用的正则表达式判断工具类代码(手机,电话,Email,日期等待
  6. Android 获取时间戳 和时间戳转日期
  7. Android自带的时间空间和日期控件
  8. Android学习07-----事件处理(3)监听日期与时间的改变_焦点事件_
  9. Android随笔之——Android时间、日期相关类和方法

随机推荐

  1. Android 5.0(L) 的MediaSession架构分析(
  2. android通知栏提示
  3. Android 获取Sim卡联系人
  4. Android改变MAC地址
  5. Stuff about Android
  6. Android 自动更新代码
  7. BBC发布了android客户端应用
  8. Android 键盘设计
  9. Android FTP Server
  10. Build your first Android Application w