android自定义日历实现事件提醒

来源:互联网 发布:fastjson解析多层json 编辑:程序博客网 时间:2024/05/18 06:46

转载请注明出处:http://blog.csdn.net/ym4189/article/details/77008361

1.概述

前段时间项目需要一个日历提醒,需求是:可以左右无限滑动,可点击监听,根据事件日期在视图中描出,右上角显示事件个数。
在网上搜了很多,但是不是很满足项目特定的需求,所以在网上的例子的基础上自定义了一个,供大家参考。

2.先上图

这里写图片描述

这里日期是自己画的,没有使用GridView,使用自定义view更方便。
我们通过计算每个月的日期,然后根据计算出来的位置绘制我们的日期。这里使用标准的6*7方格图。
我会把注释放在代码里,直接上代码:

1.CalendarView

package com.example.calendar;import java.util.List;import com.example.calendar.DateInfo;import com.example.calendar.DateUtil;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;public class CalendarView extends View {    private static final String TAG = "CalendarView";    /**     * 列     */    private static final int TOTAL_COL = 7;    /**     * 行     */    private static final int TOTAL_ROW = 6;    private Paint BlueBgPaint, HuiseBgPaint, mCirclePaint, linePaint;    private Paint mTextPaint, mCutTextPaint;    private int mViewWidth;//控件宽度    private int mViewHight;//控件高度    private float mCellSpace, mCellwide;//方格的宽和高    private Row rows[] = new Row[TOTAL_ROW];//行数组    private static DateInfo mShowDate;// 自定义的单元格信息 包括year month day    private CallBack mCallBack;// 回调    private int touchSlop;    private float radius;//提醒圆的半径    private Cell mClickCell = null;//点击的单元格    private float mDownX;    private float mDownY;    private boolean callBackCellSpace = false;    String[] str = { "日", "一", "二", "三", "四", "五", "六" };    public interface CallBack {        void clickDate(RepayPlanInfo date);// 回调点击的日期        void onMesureCellHeight(float mCellSpace, float mCellwide);/// 回调cell的高度确定slidingDrawer高度        void changeDate(DateInfo date);// 回调滑动viewPager改变的日期    }    public CalendarView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(context);    }    public CalendarView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    public CalendarView(Context context) {        super(context);        init(context);    }    public CalendarView(Context context, CallBack mCallBack) {        super(context);        // CalendarView.style = style;        this.mCallBack = mCallBack;        init(context);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //画顶部的星期        drawWeek(canvas);        //画日期单元格        for (int i = 0; i < TOTAL_ROW; i++) {            if (rows[i] != null)                rows[i].drawCells(canvas);        }    }    private void drawWeek(Canvas canvas) {        for (int i = 0; i < TOTAL_COL; i++) {            if (i == 0) {                mTextPaint.setColor(Color.parseColor("#b1b1b1"));            } else {                mTextPaint.setColor(Color.parseColor("#80000000"));            }            canvas.drawText(str[i], (float) ((i + 0.5) * mCellSpace - mTextPaint.measureText(str[i]) / 2),                    (float) (0.5 * mCellwide + mTextPaint.measureText(str[i]) / 2), mTextPaint);        }        canvas.drawLine(0, mCellwide, mViewWidth, mCellwide, linePaint);    }    //初始化画笔    private void init(Context context) {        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mCutTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);        linePaint.setTextSize(0.5f);        linePaint.setColor(0x20000000);        BlueBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        BlueBgPaint.setStyle(Paint.Style.FILL);        BlueBgPaint.setColor(Color.parseColor("#3693fd"));        HuiseBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        HuiseBgPaint.setStyle(Paint.Style.FILL);        HuiseBgPaint.setColor(Color.parseColor("#e9e9e9"));        mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mCirclePaint.setStyle(Paint.Style.FILL);        mCirclePaint.setColor(Color.parseColor("#fa4548"));        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();        initDate();    }    private void initDate() {        mShowDate = new DateInfo();        //填充日期的数据        fillDate();    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mViewWidth = w;        mViewHight = h;        mCellSpace = mViewWidth / TOTAL_COL;        radius = mCellSpace / 4;//红色圆圈的半径,这里根据单元格宽度确定        //要在第一行顶部留下画圆的高度,所以这里减去半径        mCellwide = (mViewHight - radius) / 7;        if (!callBackCellSpace) {            mCallBack.onMesureCellHeight(mCellSpace, mCellwide);            callBackCellSpace = true;        }        mTextPaint.setTextSize(mCellSpace / 3);        mCutTextPaint.setTextSize(mCellSpace / 6);        mCutTextPaint.setColor(Color.parseColor("#fffffe"));    }    /*     *      * 触摸事件为了确定点击的位置日期     */    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            mDownX = event.getX();            mDownY = event.getY();            break;        case MotionEvent.ACTION_UP:            float disX = event.getX() - mDownX;            float disY = event.getY() - mDownY;            if (Math.abs(disX) < touchSlop && Math.abs(disY) < touchSlop && event.getY() > mCellwide) {                int col = (int) (mDownX / mCellSpace);                int row = (int) ((mDownY - mCellwide) / mCellwide);                measureClickCell(col, row);            }            break;        }        return true;    }    /**      * 计算绘制点击的单元格      * @param col      * @param row      */      private void measureClickCell(int col, int row) {        if (col >= TOTAL_COL || row >= TOTAL_ROW)            return;        if (mClickCell != null) {            rows[mClickCell.j].cells[mClickCell.i] = mClickCell;        }        if (rows[row] != null) {            mClickCell = new Cell(rows[row].cells[col].date, rows[row].cells[col].state, rows[row].cells[col].i,                    rows[row].cells[col].j);            rows[row].cells[col].state = State.CLICK_DAY;            DateInfo date = rows[row].cells[col].date;            date.week = col;            mCallBack.clickDate(date);            invalidate();        }    }    // 组    class Row {        public int j;        Row(int j) {            this.j = j;        }        public Cell[] cells = new Cell[TOTAL_COL];        public void drawCells(Canvas canvas) {            for (int i = 0; i < cells.length; i++) {                if (cells[i] != null)                    cells[i].drawSelf(canvas);            }        }    }    // 单元格    class Cell {        public DateInfo date;        public State state;        /**         * i = 行 j = 列         */        public int i;        public int j;        public Cell(DateInfo date, State state, int i, int j) {            super();            this.date = date;            this.state = state;            this.i = i;            this.j = j;        }        // 绘制一个单元格 如果颜色需要自定义可以修改        public void drawSelf(Canvas canvas) {            switch (state) {            case CURRENT_MONTH_DAY:                mTextPaint.setColor(Color.parseColor("#80000000"));                break;            case NEXT_MONTH_DAY:            case PAST_MONTH_DAY:                mTextPaint.setColor(Color.parseColor("#b1b1b1"));                break;            case TODAY:                mTextPaint.setColor(Color.parseColor("#F24949"));                break;            case CLICK_DAY:                mTextPaint.setColor(Color.parseColor("#fffffe"));                canvas.drawRect((float) (mCellSpace * i), (float) (mCellwide * (j + 1) + radius / 2),                        (float) (mCellSpace * (i + 1)), (float) (mCellwide * (j + 2) + radius / 2), BlueBgPaint);                break;            case REMIND_DAY:                mTextPaint.setColor(Color.parseColor("#80000000"));                canvas.drawRect((float) (mCellSpace * i), (float) (mCellwide * (j + 1) + radius / 2),                        (float) (mCellSpace * (i + 1)), (float) (mCellwide * (j + 2) + radius / 2), HuiseBgPaint);                break;            }            // 绘制日期文字            String content = date.day + "";            canvas.drawText(content, (float) ((i + 0.5) * mCellSpace - mTextPaint.measureText(content) / 2),                    (float) ((j + 1.5) * mCellwide + mTextPaint.measureText(content, 0, 1) / 2 + radius / 2),                    mTextPaint);            // 绘制右上角提示            String count = date.getCount() + "";            if (!"0".equals(count) && count != null) {                canvas.drawCircle((float) (mCellSpace * (i + 1) - radius / 2),                        (float) ((j + 1) * mCellwide + radius / 2), radius / 2, mCirclePaint);                canvas.drawText(count, (float) (mCellSpace * (i + 1) - radius / 2 - mCutTextPaint.measureText("3") / 2),                        (float) ((j + 1) * mCellwide + radius / 2 + mCutTextPaint.measureText("3") / 2), mCutTextPaint);            }        }    }    /**     * 单元格状态: 当前月日期,过去的月的日期,下个月的日期,今天,点击的日期,提醒日期     */    enum State {        CURRENT_MONTH_DAY, PAST_MONTH_DAY, NEXT_MONTH_DAY, TODAY, CLICK_DAY, REMIND_DAY;    }    /**     * 填充日期的数据     */    private void fillDate() {        fillMonthDate();    }    /**     *  通过getWeekDayFromDate得到一个月第一天是星期几就可以算出所有的日期的位置 然后依次填充 这里最好重构一下     */    private void fillMonthDate() {        int monthDay = DateUtil.getCurrentMonthDay();// 今天         // 上个月的天数        int lastMonthDays = DateUtil.getMonthDays(mShowDate.year, mShowDate.month - 1);        // 当前月的天数         int currentMonthDays = DateUtil.getMonthDays(mShowDate.year, mShowDate.month);        //当月1号是星期几        int firstDayWeek = DateUtil.getWeekDayFromDate(mShowDate.year, mShowDate.month);        boolean isCurrentMonth = false;        if (DateUtil.isCurrentMonth(mShowDate)) {            isCurrentMonth = true;        }        int day = 0;        for (int j = 0; j < TOTAL_ROW; j++) {            rows[j] = new Row(j);            for (int i = 0; i < TOTAL_COL; i++) {                int postion = i + j * TOTAL_COL;// 单元格位置                  // 这个月的                  if (postion >= firstDayWeek && postion < firstDayWeek + currentMonthDays) {                    day++;                    if (isCurrentMonth && day == monthDay) {                        DateInfo date = DateInfo.modifiDayForObject(mShowDate, day);                        mClickCell = new Cell(date, State.TODAY, i, j);                        date.week = i;                        rows[j].cells[i] = new Cell(date, State.CLICK_DAY, i, j);                        continue;                    }                    rows[j].cells[i] = new Cell(DateInfo.modifiDayForObject(mShowDate, day),                            State.CURRENT_MONTH_DAY, i, j);                } else if (postion < firstDayWeek) {                 // 上个月                    rows[j].cells[i] = new Cell(new DateInfo(mShowDate.year, mShowDate.month - 1,                            lastMonthDays - (firstDayWeek - postion - 1)), State.PAST_MONTH_DAY, i, j);                } else if (postion >= firstDayWeek + currentMonthDays) {                 // 下个月                    rows[j].cells[i] = new Cell((new DateInfo(mShowDate.year, mShowDate.month + 1,                            postion - firstDayWeek - currentMonthDays + 1)), State.NEXT_MONTH_DAY, i, j);                }            }        }    }    /**     * 绘制提醒单元格     *      * @param i     * @return     *      */    public void updateMonthDate(List<DateInfo> dateInfos) {        DateInfo dateInfo;        for (int k = 0; k < dateInfos.size(); k++) {            dateInfo = dateInfos.get(k);            //当前显示view为提醒月时绘制提醒日期            if (mShowDate.year == dateInfo.getYear() && mShowDate.month == dateInfo.getMonth()) {                int[] cut = getSubscript(dateInfo.getDay());                rows[cut[0]].cells[cut[1]].state = State.REMIND_DAY;                rows[cut[0]].cells[cut[1]].date = dateInfo;                if (mClickCell != null && mClickCell.date.getDay() == dateInfo.getDay()) {                    mClickCell = rows[cut[0]].cells[cut[1]];                    measureClickCell(cut[1], cut[0]);                }            }        }        invalidate();    }    /**     * 根据日期获得单元格下标     * @param i     * @return      */    private int[] getSubscript(int i) {        int firstDayWeek = DateUtil.getWeekDayFromDate(mShowDate.year, mShowDate.month);        i = i + firstDayWeek - 1;        int a = i / 7;        int b = i % 7;        int[] cut = { a, b };        return cut;    }    //更新日期,用于月份切换时    public void update() {        mClickCell = null;        mCallBack.changeDate(mShowDate);        fillDate();        invalidate();    }    //返回当前时间    public void backToday() {        initDate();        invalidate();    }    // 点击选择切换月份    public void clickSelect(int year, int month) {        mShowDate.month = month;        mShowDate.year = year;        update();    }    // 向右滑动    public void rightSilde() {        if (mShowDate.month == 12) {            mShowDate.month = 1;            mShowDate.year += 1;        } else {            mShowDate.month += 1;        }        update();    }    // 向左滑动    public void leftSilde() {        if (mShowDate.month == 1) {            mShowDate.month = 12;            mShowDate.year -= 1;        } else {            mShowDate.month -= 1;        }        update();    }}

这里红色圆心不是在右上角的顶角,需要改成在顶角的话,只需在右边留下圆半径距离即可,和留顶部距离方式一样。

2.DateUtil时间工具类

package com.example.calendar;import android.annotation.SuppressLint;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;public class DateUtil {    public static int getMonthDays(int year, int month) {        if (month > 12) {            month = 1;            year += 1;        } else if (month < 1) {            month = 12;            year -= 1;        }        int[] arr = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };        int days = 0;        if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {            arr[1] = 29; // 闰年2月29天         }        try {            days = arr[month - 1];        } catch (Exception e) {            e.getStackTrace();        }        return days;    }    public static int getYear() {        return Calendar.getInstance().get(Calendar.YEAR);    }    public static int getMonth() {        return Calendar.getInstance().get(Calendar.MONTH) + 1;    }    public static int getCurrentMonthDay() {        return Calendar.getInstance().get(Calendar.DAY_OF_MONTH);    }    public static int getWeekDay() {        return Calendar.getInstance().get(Calendar.DAY_OF_WEEK);    }    public static int getHour() {        return Calendar.getInstance().get(Calendar.HOUR_OF_DAY);    }    public static int getMinute() {        return Calendar.getInstance().get(Calendar.MINUTE);    }    public static int[] getWeekSunday(int year, int month, int day, int pervious) {        int[] time = new int[3];        Calendar c = Calendar.getInstance();        c.set(Calendar.YEAR, year);        c.set(Calendar.MONTH, month);        c.set(Calendar.DAY_OF_MONTH, day);        c.add(Calendar.DAY_OF_MONTH, pervious);        time[0] = c.get(Calendar.YEAR);        time[1] = c.get(Calendar.MONTH) + 1;        time[2] = c.get(Calendar.DAY_OF_MONTH);        return time;    }    public static int getWeekDayFromDate(int year, int month) {        Calendar cal = Calendar.getInstance();        cal.setTime(getDateFromString(year, month));        int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;        if (week_index < 0) {            week_index = 0;        }        return week_index;    }    @SuppressLint("SimpleDateFormat")    public static Date getDateFromString(int year, int month) {        String dateString = year + "-" + (month > 9 ? month : ("0" + month)) + "-01";        Date date = null;        try {            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");            date = sdf.parse(dateString);        } catch (ParseException e) {            System.out.println(e.getMessage());        }        return date;    }    public static boolean isToday(RepayPlanInfo date) {        return (date.year == DateUtil.getYear() && date.month == DateUtil.getMonth()                && date.day == DateUtil.getCurrentMonthDay());    }    public static boolean isCurrentMonth(RepayPlanInfo date) {        return (date.year == DateUtil.getYear() && date.month == DateUtil.getMonth());    }    public static String getTimeParseInt(int year, int month, int day) {        String dateString = year + "" + (month > 9 ? month : ("0" + month))                             + (day > 9 ? day : ("0" + day));        return dateString;    }    public static String getTimeParseInt(int year, int month) {        String dateString = year + "" + (month > 9 ? month : ("0" + month));        return dateString;    }}

3.自定义日期类DateInfo

package com.example.calendar.data;import java.io.Serializable;import package com.example.calendar.DateUtil;import android.os.Parcel;import android.os.Parcelable;/** * 自定义的日期类 *  **/public class DateInfo implements Serializable {    private static final long serialVersionUID = 1L;    public int year;    public int month;    public int day;    public int week;    public DateInfo(int year, int month, int day) {        if (month > 12) {            month = 1;            year++;        } else if (month < 1) {            month = 12;            year--;        }        this.year = year;        this.month = month;        this.day = day;    }    public DateInfo() {        this.year = DateUtil.getYear();        this.month = DateUtil.getMonth();        this.day = DateUtil.getCurrentMonthDay();    }    public static DateInfo modifiDayForObject(RepayPlanInfo date, int day) {        DateInfo modifiDate = new DateInfo(date.year, date.month, day);        return modifiDate;    }    @Override    public String toString() {        return year + "-" + month + "-" + day;    }    public int getYear() {        return year;    }    public void setYear(int year) {        this.year = year;    }    public int getMonth() {        return month;    }    public void setMonth(int month) {        this.month = month;    }    public int getDay() {        return day;    }    public void setDay(int day) {        this.day = day;    }    public int getWeek() {        return week;    }    public void setWeek(int week) {        this.week = week;    }}

好了,自定义的view已经准备好了,接下来就是使用了。

3.使用

首先,左右滑动使用的是viewpage,为了使能无限滑动,这里我们自定义一个PagerAdapter 。传入一个日历卡数组,让ViewPager循环复用这几个日历卡,避免消耗内存。
同时viewpage在左右滑动时要判断是左滑还是右滑去加载日历数据,所以这里自定义了OnPageChangeListener

package com.example.calendar;import android.os.Parcelable;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.view.View;public class CustomViewPagerAdapter<V extends View> extends PagerAdapter {    private V[] views;    public CustomViewPagerAdapter(V[] views) {        super();        this.views = views;    }    @Override    public void finishUpdate(View arg0) {    }    @Override    public void notifyDataSetChanged() {        super.notifyDataSetChanged();    }    @Override    public int getCount() {        return Integer.MAX_VALUE;    }    @Override    public Object instantiateItem(View arg0, int arg1) {        if (((ViewPager) arg0).getChildCount() == views.length) {            ((ViewPager) arg0).removeView(views[arg1 % views.length]);        }        ((ViewPager) arg0).addView(views[arg1 % views.length], 0);        return views[arg1 % views.length];    }    @Override    public boolean isViewFromObject(View arg0, Object arg1) {        return arg0 == (arg1);    }    @Override    public Parcelable saveState() {        return null;    }    @Override    public void destroyItem(View arg0, int arg1, Object arg2) {        // TODO Auto-generated method stub    }    @Override    public void startUpdate(View arg0) {    }    public V[] getAllItems() {        return views;    }}

CalendarActivity.java

package com.example.calendar;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import com.example.calendar.DateInfo;import com.example.calendar.DateUtil;import com.example.calendar.CalendarView;import com.example.calendar.CalendarView.CallBack;import com.example.calendar.CustomViewPagerAdapter;import com.example.calendar.HomePopMenuWindow;import android.os.Build;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.support.v4.view.ViewPager;import android.support.v4.view.ViewPager.OnPageChangeListener;import android.view.View;import android.view.WindowManager;import android.widget.AdapterView;import android.widget.LinearLayout;import android.widget.RelativeLayout;import android.widget.TextView;import android.widget.AdapterView.OnItemClickListener;import android.widget.PopupWindow.OnDismissListener;public class CalendarActivityextends Activity implements CallBack {    private ViewPager viewPager;    private CustomViewPagerAdapter<CalendarView> viewPagerAdapter;    private LinearLayout linearRepayPlan;    private TextView showYearView, showMonthView, title, xhdtxtMenu;    private List<DateInfo> remindDateInfos = new ArrayList<DateInfo>();    private List<DateInfo> menuDateInfos = new ArrayList<DateInfo>();    private CalendarView[] calendarViews;    private int width;    private int currentYear = DateUtil.getYear();    private int currentMonth = DateUtil.getMonth();    private Context context;    @Override    protected void onStart() {        // TODO Auto-generated method stub        super.onStart();    }    @Override    protected void onStop() {        // TODO Auto-generated method stub        super.onStop();    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_calendar);        context = this;        initData();        initView();    }    private void initData() {        for (int i = 0; i < 6; i++) {            DateInfo info = new DateInfo();            info.setYear(currentYear);            info.setMonth(currentMonth);            if (currentMonth == 12) {                currentYear = currentYear + 1;                currentMonth = 1;            } else {                currentMonth += 1;            }            menuDateInfos.add(0, info);        }        DateInfo info = new DateInfo();        info.setBillDate("2017-08-15");        info.setCount(2);        repayDateInfos.add(info);    }    private void initView() {        viewPager = (ViewPager) findViewById(R.id.viewpager);        showMonthView = (TextView) findViewById(R.id.show_month_view);        showYearView = (TextView) findViewById(R.id.show_year_view);        showYearView.setText(TimeUtil.getCurrentYear1());        showMonthView.setText(TimeUtil.getCurrentMonth1() + "/");        createMassCalendarViews(this, 5, this);        viewPagerAdapter = new CustomViewPagerAdapter<CalendarView>(calendarViews);        viewPager.setAdapter(viewPagerAdapter);        viewPager.setCurrentItem(498);        viewPager.setOnPageChangeListener(new CalendarViewPagerLisenter(viewPagerAdapter));        /**         * 当有提醒数据时,调用此方法绘制提醒日期         */        updateData();    }    public void OnButtonClick(View view) {        switch (view.getId()) {        case R.id.img_calendar:            showPopMenu();            break;        case R.id.xhdTopBack:            finish();            break;        default:            break;        }    }    /**     * 显示弹窗     */    private void showPopMenu() {        // 点击弹出一个popupwindow        final HomePopMenuWindow pop = new HomePopMenuWindow(this, menuDateInfos, 1);        // 定义弹窗按钮        pop.showAsDropDown1(findViewById(R.id.img_calendar));        pop.setOnItemClickListener(new OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                DateInfo info = menuDateInfos.get(position);                CalendarView[] mShowViews = viewPagerAdapter.getAllItems();                mShowViews[viewPager.getCurrentItem() % mShowViews.length].clickSelect(info.getYear(), info.getMonth());                pop.dismiss();            }        });        setBackgroundAlpha(0.5f);        pop.setOnDismissListener(new OnDismissListener() {            @Override            public void onDismiss() {                setBackgroundAlpha(1.0f);            }        });    }    /**     * 设置添加屏幕的背景透明度     *      * @param bgAlpha     *            屏幕透明度0.0-1.0 1表示完全不透明     */    public void setBackgroundAlpha(float bgAlpha) {        WindowManager.LayoutParams lp = getWindow().getAttributes();        lp.alpha = bgAlpha;        getWindow().setAttributes(lp);    }    //绘制提醒日期    private void updateData() {        CalendarView[] mShowViews = viewPagerAdapter.getAllItems();        mShowViews[viewPager.getCurrentItem() % mShowViews.length].updateMonthDate(remindDateInfos);    }    /**     * 生产多个CalendarView     *      */    private void createMassCalendarViews(Context context, int count, CallBack callBack) {        calendarViews = new CalendarView[count];        for (int i = 0; i < count; i++) {            calendarViews[i] = new CalendarView(context, callBack);        }    }    class CalendarViewPagerLisenter implements OnPageChangeListener {        private SildeDirection mDirection = SildeDirection.NO_SILDE;        int mCurrIndex = 498;        private CalendarView[] mShowViews;        public CalendarViewPagerLisenter(CustomViewPagerAdapter<CalendarView> viewAdapter) {            super();            this.mShowViews = viewAdapter.getAllItems();        }        @Override        public void onPageScrollStateChanged(int arg0) {            // TODO Auto-generated method stub        }        @Override        public void onPageScrolled(int arg0, float arg1, int arg2) {            // TODO Auto-generated method stub        }        @Override        public void onPageSelected(int arg0) {            measureDirection(arg0);            updateCalendarView(arg0);            linearRepayPlan.setVisibility(View.GONE);        }        private void updateCalendarView(int arg0) {            if (mDirection == SildeDirection.RIGHT) {                mShowViews[arg0 % mShowViews.length].rightSilde();            } else if (mDirection == SildeDirection.LEFT) {                mShowViews[arg0 % mShowViews.length].leftSilde();            }            mDirection = SildeDirection.NO_SILDE;        }        /**         * 判断滑动方向         *          * @param arg0         */        private void measureDirection(int arg0) {            if (arg0 > mCurrIndex) {                mDirection = SildeDirection.RIGHT;            } else if (arg0 < mCurrIndex) {                mDirection = SildeDirection.LEFT;            }            mCurrIndex = arg0;        }    }    enum SildeDirection {        RIGHT, LEFT, NO_SILDE;    }    /**     * CandlendarView回到当前日期     */    private void backTodayCalendarViews() {        if (calendarViews != null)            for (int i = 0; i < calendarViews.length; i++) {                calendarViews[i].backToday();            }    }    @Override    protected void onDestroy() {        super.onDestroy();    }    //viewpage滑动时显示当前日期    public void setShowDateViewText(int year, int month) {        showYearView.setText(year + "");        if (month < 10) {            showMonthView.setText("0" + month + "/");        } else {            showMonthView.setText(month + "/");        }    }    @Override    public void onMesureCellHeight(float cellSpace, float cellwide) {    }    @Override    public void clickDate(RepayPlanInfo dates) {        // 当点击日历时回调    }    @Override    public void changeDate(RepayPlanInfo dates) {        //viewpage滑动时回调        setShowDateViewText(dates.year, dates.month);    }}

上面代码中我还使用了popupWindow,就是弹出一个listview,可以点击切换月份,我就不贴代码了

布局activity_calendar

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <RelativeLayout        android:layout_width="fill_parent"        android:layout_height="40dip"        android:background="@color/white"        android:paddingLeft="15dip"        android:paddingRight="15dip" >        <LinearLayout            android:id="@+id/layout"            android:layout_width="wrap_content"            android:layout_height="fill_parent"            android:layout_alignParentLeft="true"            android:layout_marginLeft="15dp"            android:orientation="horizontal" >            <TextView                android:id="@+id/show_month_view"                android:layout_width="wrap_content"                android:layout_height="fill_parent"                android:layout_alignParentLeft="true"                android:gravity="center"                android:text="01/"                android:textColor="#646464"                android:textSize="15sp" />            <TextView                android:id="@+id/show_year_view"                android:layout_width="wrap_content"                android:layout_height="fill_parent"                android:gravity="center"                android:text="2017"                android:textColor="#646464"                android:textSize="15sp" />        </LinearLayout>        <ImageView            android:id="@+id/img_calendar"            android:layout_width="40dp"            android:layout_height="40dp"            android:layout_alignParentRight="true"            android:layout_centerVertical="true"            android:onClick="OnButtonClick"            android:padding="10dp"            android:src="@drawable/img_schoolyear" />    </RelativeLayout>    <View        android:layout_width="fill_parent"        android:layout_height="1px"        android:background="#20000000" />    <android.support.v4.view.ViewPager        android:id="@+id/viewpager"        android:layout_width="match_parent"        android:layout_height="280dp"        android:layout_gravity="center"        android:background="#ffffff"        android:paddingLeft="15dip"        android:paddingRight="15dip" >    </android.support.v4.view.ViewPager></LinearLayout>

好了,大功告成了,相关代码就这些了~~~