Android系统自定义实现日历控件详解手机开发

注:此功能在在Activity中,由三大块组成:头(上月按扭,下月按扭,当前年月文本),日历块(星期区域,日期区域),描述区域 
 
Activity: 
/** 
 * Android实现日历控件 
 * 注:Calendar时间与现在实的时间在月份上需要+1,因为月份是0-11 
 */ 
public class CalenderActivity extends Activity { 
 
    private ArrayList<DateWidgetDayView> days = new ArrayList<DateWidgetDayView>(); 
 
        //颜色代码常量 
    public static int Calendar_WeekBgColor = 0; 
    public static int Calendar_DayBgColor = 0; 
    public static int IsHoliday_BgColor = 0; 
    public static int UnPresentMonth_FontColor = 0; 
    public static int IsPresentMonth_FontColor = 0; 
    public static int IsToday_BgColor = 0; 
    public static int Special_Reminder = 0; 
    public static int Common_Reminder = 0; 
    public static int Calendar_WeekFontColor = 0; 
 
    /** 
     *  表格中的第一天,一般上月的某一天 
     */ 
    public static Calendar mFirstDateOfPanel = Calendar.getInstance(); 
    private Calendar mTodayDate = Calendar.getInstance();// 初始日期,即当天 
    private Calendar mSelectedDate = Calendar.getInstance();//选中的日期,如果未选中则为1970-1-1 
    private Calendar mViewDate = Calendar.getInstance(); 
 
    // 当前操作日期 
    private int firstDayOfWeek = Calendar.SUNDAY;// 是星期日 
    private int currentMonth = 0; 
    private int currentYear = 0; 
 
    private int displayWidth = 0;// 屏幕总宽度 
    private int cell_Width = 0; // 日期单元格宽度 
    private int cell_Height = 35; // 日期单元格高度 
 
    // 页面控件 
    TextView currentYAndM = null; 
    Button preMonthButton = null; 
    Button nextMonthButton = null; 
    LinearLayout mainLayout = null; 
    LinearLayout calendarLayout = null; 
    LinearLayout contentLayout = null; 
    TextView contentText = null; 
 
    // 数据源 
    Boolean[] msgs = null; 
 
    Calendar startDate = null;//表格的第一天的日期 
 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
 
        setContentView(R.layout.calendar_main); 
        this.viewModel = new BlogViewModel(this); 
 
        // 获得屏幕宽和高,并計算出屏幕寬度分七等份的大小 
        WindowManager windowManager = getWindowManager(); 
        Display display = windowManager.getDefaultDisplay(); 
        displayWidth = display.getWidth(); 
        cell_Width = displayWidth / 7 + 1; 
 
        // 制定布局文件,并设置属性 
        mainLayout = (LinearLayout) this.findViewById(R.id.date_calender_framelayout); 
        currentYAndM = (TextView) findViewById(R.id.Top_Date); 
        preMonthButton = (Button) findViewById(R.id.btn_pre_month); 
        nextMonthButton = (Button) findViewById(R.id.btn_next_month); 
 
        preMonthButton.setOnClickListener(new OnClickPreMonthListener()); 
        nextMonthButton.setOnClickListener(new OnClickNextMonthListener()); 
 
        // 计算本月日历中的第一天(一般是上月的某天),并更新日历 
        mFirstDateOfPanel = getCalendarStartDate(); 
        this.mTodayDate = getTodayDate(); 
        this.startDate = getStartDate(); 
 
        /* 
         *  初始化日期视图 
         *  Calendar部分 
         */ 
        View calendarView = generateCalendarView(); 
        this.mainLayout.addView(calendarView); 
 
        //刷新日期视图 
        this.refreshCalendar(); 
 
        /* 
         * Description 部分 
         */ 
        ScrollView view = new ScrollView(this); 
        contentLayout = createLayout(LinearLayout.VERTICAL); 
        contentLayout.setPadding(5, 2, 0, 0); 
 
        contentText = new TextView(this); 
        contentText.setTextColor(Color.BLACK); 
        contentText.setTextSize(18); 
 
        contentLayout.addView(contentText); 
 
        LinearLayout.LayoutParams Param1 = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT); 
        view.addView(contentLayout, Param1); 
        mainLayout.setBackgroundColor(Color.WHITE); 
        mainLayout.addView(view); 
 
        /* 新建线程 
        new Thread() { 
            @Override 
            public void run() { 
                int day = getIndexFromDates(mTodayDate, startDate); 
 
                Log.i("sys", "初始时  day = "+day); 
            } 
        }.start();*/ 
 
        Calendar_WeekBgColor = this.getResources().getColor(R.color.Calendar_WeekBgColor); 
        Calendar_DayBgColor = this.getResources().getColor(R.color.Calendar_DayBgColor); 
        IsHoliday_BgColor = this.getResources().getColor(R.color.isHoliday_BgColor); 
        UnPresentMonth_FontColor = this.getResources().getColor(R.color.unPresentMonth_FontColor); 
        IsPresentMonth_FontColor = this.getResources().getColor(R.color.isPresentMonth_FontColor); 
        IsToday_BgColor = this.getResources().getColor(R.color.isToday_BgColor); 
        Special_Reminder = this.getResources().getColor(R.color.specialReminder); 
        Common_Reminder = this.getResources().getColor(R.color.commonReminder); 
        Calendar_WeekFontColor = this.getResources().getColor(R.color.Calendar_WeekFontColor); 
    } 
 
    protected String getDateShortString(Calendar date) { 
        String returnString = date.get(Calendar.YEAR) + "-"; 
        returnString += date.get(Calendar.MONTH) + 1 + "-"; 
        returnString += date.get(Calendar.DAY_OF_MONTH); 
 
        return returnString; 
    } 
 
    /** 
     * Return the Date's index of [email protected] returnDate} from [email protected] datesList}; 
     * First is Today's index 
     *  
     * @param now 
     *            today 
     * @param returnDate 
     *            click date 
     * @return 
     */ 
    private int getIndexFromDates(Calendar now, Calendar returnDate) { 
        Calendar cNow = (Calendar) now.clone(); 
        Calendar cReturnDate = (Calendar) returnDate.clone(); 
        CalenderUtil.setTimeToMidnight(cNow); 
        CalenderUtil.setTimeToMidnight(cReturnDate); 
 
        long todayMs = cNow.getTimeInMillis(); 
        long returnMs = cReturnDate.getTimeInMillis(); 
        long intervalMs = todayMs - returnMs; 
        int index = CalenderUtil.millisecondsToDays(intervalMs); 
        Log.i("sys", "Index = " + index); 
        return index; 
    } 
 
    /** 
     * 生成日期视图 即初始化calendarLayout 
     *  
     * @return 
     */ 
    private View generateCalendarView() { 
        calendarLayout = createLayout(LinearLayout.VERTICAL); 
        // layContent.setPadding(1, 0, 1, 0); 
        calendarLayout.setBackgroundColor(Color.argb(255, 105, 105, 103)); 
        calendarLayout.addView(generateCalendarWeekRows()); 
        days.clear(); 
 
        for (int iRow = 0; iRow < 6; iRow++) { 
            calendarLayout.addView(generateCalendarDayRows()); 
        } 
 
        return calendarLayout; 
    } 
 
    /** 
     * 生成星期View 
     *  
     * @return View 
     */ 
    private View generateCalendarWeekRows() { 
        LinearLayout weekLayoutRow = createLayout(LinearLayout.HORIZONTAL); 
        weekLayoutRow.setBackgroundColor(Color.argb(255, 207, 207, 205)); 
 
        for (int iDay = 0; iDay < 7; iDay++) { 
            DateWidgetWeekView dayView = new DateWidgetWeekView(this, cell_Width, cell_Height); 
 
            final int iWeekDay = CalenderUtil.getWeekDay(iDay, firstDayOfWeek); 
            dayView.setData(iWeekDay); 
            weekLayoutRow.addView(dayView); 
        } 
 
        return weekLayoutRow; 
    } 
 
    /** 
     * 生成日期行View 
     *  
     * @return View 
     */ 
    private View generateCalendarDayRows() { 
        LinearLayout layRow = createLayout(LinearLayout.HORIZONTAL); 
        //TODO  日期数据消息给添加属性 
 
        for (int iDay = 0; iDay < 7; iDay++) { 
            DateWidgetDayView dateDayView = new DateWidgetDayView(this, cell_Width, cell_Width); 
            dateDayView.setItemClick(mOnDayCellClick); 
            days.add(dateDayView); 
            layRow.addView(dateDayView); 
        } 
 
        return layRow; 
    } 
 
    /** 
     * 由于本日历上的日期都是从周一开始的,此方法可推算出上月在本月日历中显示的天数 计算出本月第一行1号前的空格数 
     */ 
    private void updateStartDateForPanel() { 
        currentMonth = mFirstDateOfPanel.get(Calendar.MONTH); 
        currentYear = mFirstDateOfPanel.get(Calendar.YEAR); 
        mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1); 
        mFirstDateOfPanel.set(Calendar.HOUR_OF_DAY, 0); 
        mFirstDateOfPanel.set(Calendar.MINUTE, 0); 
        mFirstDateOfPanel.set(Calendar.SECOND, 0); 
        // 显示当前是的年月在Header 
        updateCurrentMonthDisplay(); 
        int iDay = 0;// 前面的空格数 
        int iStartDay = firstDayOfWeek;// 当天的星期角标 
 
        if (iStartDay == Calendar.MONDAY) { 
            iDay = mFirstDateOfPanel.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY; 
            if (iDay < 0) 
                iDay = 6; 
        } 
 
        if (iStartDay == Calendar.SUNDAY) { 
            iDay = mFirstDateOfPanel.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY; 
            if (iDay < 0) 
                iDay = 6; 
        } 
 
        mFirstDateOfPanel.add(Calendar.DAY_OF_WEEK, -iDay);// 得出-2,即前面从上月30号开始 
    } 
 
    /** 
     *  更新日历数据并设置日期 
     *  给days中的DateWidgetDayView元素添加Text 
     */ 
    private void refreshCalendar() { 
        DateWidgetDayView dayView = null; 
 
        boolean isSelected = false; 
        final boolean bIsSelection = (mSelectedDate.getTimeInMillis() != 0); 
        final int iSelectedYear = mSelectedDate.get(Calendar.YEAR); 
        final int iSelectedMonth = mSelectedDate.get(Calendar.MONTH); 
        final int iSelectedDay = mSelectedDate.get(Calendar.DAY_OF_MONTH); 
 
        //取得表格中的第一天(一般为上月) 
        mViewDate.setTimeInMillis(mFirstDateOfPanel.getTimeInMillis()); 
 
        for (int i = 0; i < days.size(); i++) { 
            final int iYear = mViewDate.get(Calendar.YEAR); 
            final int iMonth = mViewDate.get(Calendar.MONTH); 
            final int iDay = mViewDate.get(Calendar.DAY_OF_MONTH); 
            final int iDayOfWeek = mViewDate.get(Calendar.DAY_OF_WEEK); 
 
            dayView = days.get(i); 
 
            // Check isToday 
            boolean isToday = false; 
 
            if (mTodayDate.get(Calendar.YEAR) == iYear && mTodayDate.get(Calendar.MONTH) == iMonth && mTodayDate.get(Calendar.DAY_OF_MONTH) == iDay) { 
                isToday = true; 
            } 
 
            // Check isHoliday 
            boolean isHoliday = false; 
            if ((iDayOfWeek == Calendar.SATURDAY) || (iDayOfWeek == Calendar.SUNDAY)) 
                isHoliday = true; 
            /*if ((iMonth == Calendar.JANUARY) && (iDay == 1)) 
                isHoliday = true;*///在格里高利历和罗马儒略历中一年中的第一个月是 JANUARY,它为 0;最后一个月取决于一年中的月份数。 
 
            // Check isSelected 
            isSelected = false; 
 
            if (bIsSelection) 
                if ((iSelectedDay == iDay) && (iSelectedMonth == iMonth) && (iSelectedYear == iYear)) { 
                    isSelected = true; 
                } 
 
            dayView.setSelected(isSelected); 
 
            // Check hasMSG 
            boolean hasMSG = false; 
 
            if (msgs != null && msgs[i] == true ){ 
                //TODO 
            } 
 
            if (isSelected){ 
                dayView.setFocusable(true); 
            } 
 
            dayView.setData(iYear, iMonth, iDay, isToday, isHoliday, currentMonth, hasMSG); 
 
            mViewDate.add(Calendar.DAY_OF_MONTH, 1); 
            Log.i("sys", "mViewDate : "+iYear+"-"+iMonth+"-"+iDay); 
            Log.i("sys", "mFirstDateOfPanel : "+mFirstDateOfPanel.get(Calendar.YEAR)+"-"+mFirstDateOfPanel.get(Calendar.MONTH)+"-"+mFirstDateOfPanel.get(Calendar.DAY_OF_MONTH)); 
        } 
        Log.i("sys", "mSelectedDate : "+iSelectedYear+"-"+iSelectedMonth+"-"+iSelectedDay); 
        Log.i("sys", "startDate : "+startDate.get(Calendar.YEAR)+"-"+startDate.get(Calendar.MONTH)+"-"+startDate.get(Calendar.DAY_OF_MONTH)); 
 
        calendarLayout.invalidate(); 
    } 
 
    /** 
     *  设置当天日期和第并计算出前面第一个星期天的日[email protected] mFirstDateOfPanel} 
     * @return 
     */ 
    private Calendar getCalendarStartDate() { 
        mTodayDate.setTimeInMillis(System.currentTimeMillis()); 
        mTodayDate.setFirstDayOfWeek(firstDayOfWeek); 
 
        // 如果没有选中日期,则设置当前日期为 ? 
        if (mSelectedDate.getTimeInMillis() == 0) { 
            mFirstDateOfPanel.setTimeInMillis(System.currentTimeMillis()); 
            mFirstDateOfPanel.setFirstDayOfWeek(firstDayOfWeek); 
        } else { 
            mFirstDateOfPanel.setTimeInMillis(mSelectedDate.getTimeInMillis()); 
            mFirstDateOfPanel.setFirstDayOfWeek(firstDayOfWeek); 
        } 
 
        updateStartDateForPanel(); 
        return mFirstDateOfPanel; 
    } 
 
    /** 
     * 得到当前日历表中的第一天 
     *  
     * @return Calendar 
     */ 
    public Calendar getStartDate() { 
        int iDay = 0; 
        Calendar cal_Now = Calendar.getInstance(); 
        cal_Now.set(Calendar.DAY_OF_MONTH, 1); 
        cal_Now.set(Calendar.HOUR_OF_DAY, 0); 
        cal_Now.set(Calendar.MINUTE, 0); 
        cal_Now.set(Calendar.SECOND, 0); 
        cal_Now.setFirstDayOfWeek(Calendar.SUNDAY); 
 
        iDay = cal_Now.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY; 
 
        if (iDay < 0) { 
            iDay = 6; 
        } 
 
        cal_Now.add(Calendar.DAY_OF_WEEK, -iDay); 
 
        return cal_Now; 
    } 
 
    public Calendar getTodayDate() { 
        Calendar cal_Today = Calendar.getInstance(); 
        cal_Today.set(Calendar.HOUR_OF_DAY, 0); 
        cal_Today.set(Calendar.MINUTE, 0); 
        cal_Today.set(Calendar.SECOND, 0); 
        cal_Today.setFirstDayOfWeek(Calendar.MONDAY); 
 
        return cal_Today; 
    } 
 
    /** 
     * 更新日历标题上显示的年月 
     */ 
    private void updateCurrentMonthDisplay() { 
        String date = mFirstDateOfPanel.get(Calendar.YEAR) + "年" + (mFirstDateOfPanel.get(Calendar.MONTH) + 1) + "月"; 
        currentYAndM.setText(date); 
    } 
 
    /** 
     *  点击上月按钮,触发事件 
     * @author Win7 
     */ 
 
    // 生成布局LinearLayout 
    private LinearLayout createLayout(int iOrientation) { 
        LinearLayout lay = new LinearLayout(this); 
        lay.setLayoutParams(new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT)); 
        lay.setOrientation(iOrientation); 
 
        return lay; 
    } 
 
    class OnClickPreMonthListener implements OnClickListener { 
        @Override 
        public void onClick(View v) { 
            contentText.setText("aaaa"); 
            mSelectedDate.setTimeInMillis(0); 
            currentMonth--; 
 
            if (currentMonth == -1) { 
                currentMonth = 11; 
                currentYear--; 
            } 
 
            mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1); 
            mFirstDateOfPanel.set(Calendar.MONTH, currentMonth); 
            mFirstDateOfPanel.set(Calendar.YEAR, currentYear); 
            mFirstDateOfPanel.set(Calendar.HOUR_OF_DAY, 0); 
            mFirstDateOfPanel.set(Calendar.MINUTE, 0); 
            mFirstDateOfPanel.set(Calendar.SECOND, 0); 
            mFirstDateOfPanel.set(Calendar.MILLISECOND, 0); 
            updateStartDateForPanel(); 
 
            startDate = (Calendar) mFirstDateOfPanel.clone(); 
 
            // 新建线程 
            new Thread() { 
                @Override 
                public void run() { 
                    int day = getIndexFromDates(mTodayDate, startDate); 
                                        //day是算出当前显示的月份面版第一天与当天的天数 
                    Log.i("sys", "点击上月时  day = "+day); 
                } 
            }.start(); 
 
            refreshCalendar(); 
        } 
 
    } 
 
    /** 
     *  点击下月按钮,触发事件 
     * @author Win7 
     */ 
    class OnClickNextMonthListener implements OnClickListener { 
        @Override 
        public void onClick(View v) { 
            contentText.setText(""); 
            mSelectedDate.setTimeInMillis(0); 
            currentMonth++; 
 
            if (currentMonth == 12) { 
                currentMonth = 0; 
                currentYear++; 
            } 
 
            mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1); 
            mFirstDateOfPanel.set(Calendar.MONTH, currentMonth); 
            mFirstDateOfPanel.set(Calendar.YEAR, currentYear); 
            updateStartDateForPanel(); 
 
            startDate = (Calendar) mFirstDateOfPanel.clone(); 
 
            // 新建线程 
            new Thread() { 
                @Override 
                public void run() { 
                    int day = 5; 
                    Log.i("sys", "点击下月时  day = "+day); 
                } 
            }.start(); 
 
            refreshCalendar(); 
        } 
    } 
 
    // 点击日历,触发事件 
    private DateWidgetDayView.OnDateItemClickListener mOnDayCellClick = new DateWidgetDayView.OnDateItemClickListener() { 
        public void OnClick(DateWidgetDayView item) { 
            mSelectedDate.setTimeInMillis(item.getDate().getTimeInMillis()); 
 
            int day = getIndexFromDates(mSelectedDate, startDate); 
 
            contentText.setText(getDateShortString(mSelectedDate)); 
            contentText.setText("无数据"); 
 
            Log.i("sys", "mFirstDateOfPanel=" + mFirstDateOfPanel.get(Calendar.DATE) + " calCalendar=" + mViewDate.get(Calendar.DATE) + " mTodayDate=" + mTodayDate.get(Calendar.DATE) 
                    + " mSelectedDate=" + mSelectedDate.get(Calendar.DATE) +" day = "+day); 
            item.setSelected(true); 
            refreshCalendar(); 
        } 
    }; 
 
    @Deprecated 
    public Calendar getEndDate(Calendar startDate) { 
        // Calendar end = GetStartDate(enddate); 
        Calendar endDate = Calendar.getInstance(); 
        endDate = (Calendar) startDate.clone(); 
        endDate.add(Calendar.DAY_OF_MONTH, 41); 
        return endDate; 
    } 
} 
 
星期View: 
 
public class DateWidgetWeekView extends View { 
    // 字体大小 
    private final static int fTextSize = 22; 
    private Paint pt = new Paint(); 
    private RectF rect = new RectF(); 
    private int iWeekDay = -1; 
 
    public DateWidgetWeekView(Context context, int iWidth, int iHeight) { 
        super(context); 
        setLayoutParams(new LayoutParams(iWidth, iHeight)); 
    } 
 
    @Override 
    protected void onDraw(Canvas canvas) { 
        super.onDraw(canvas); 
 
        // 设置矩形大小 
        rect.set(0, 0, this.getWidth(), this.getHeight()); 
        rect.inset(1, 1); 
 
        // 绘制日历头部 
        drawDayHeader(canvas); 
    } 
 
    private void drawDayHeader(Canvas canvas) { 
        // 画矩形,并设置矩形画笔的颜色 
        pt.setColor(CalenderActivity.Calendar_WeekBgColor); 
        canvas.drawRect(rect, pt); 
 
        // 写入日历头部,设置画笔参数 
        pt.setTypeface(null); 
        pt.setTextSize(fTextSize); 
        pt.setAntiAlias(true); 
        pt.setFakeBoldText(true); 
        pt.setColor(CalenderActivity.Calendar_WeekFontColor); 
 
        // draw day name 
        final String sDayName = CalenderUtil.getWeekDayName(iWeekDay); 
        final int iPosX = (int) rect.left + ((int) rect.width() >> 1) 
                - ((int) pt.measureText(sDayName) >> 1); 
        final int iPosY = (int) (this.getHeight() 
                - (this.getHeight() - getTextHeight()) / 2 - pt 
                .getFontMetrics().bottom); 
        canvas.drawText(sDayName, iPosX, iPosY, pt); 
    } 
 
    // 得到字体高度 
    private int getTextHeight() { 
        return (int) (-pt.ascent() + pt.descent()); 
    } 
 
    // 得到一星期的第几天的文本标记 
    public void setData(int iWeekDay) { 
        this.iWeekDay = iWeekDay; 
    } 
} 
 
日期View: 
 
/** 
 * 日历控件单元格绘制类 
 * @Description: 日历控件单元格绘制类 
 
 * @FileName: DateWidgetDayView.java  
 */ 
public class DateWidgetDayView extends View { 
    // 字体大小 
    private static final int fTextSize = 28; 
 
    // 基本元素 
    private OnDateItemClickListener itemClick = null; 
    private Paint mPaint = new Paint(); 
    private RectF rect = new RectF(); 
    private String sDate = ""; 
 
    // 当前日期 
    private int iDateYear = 0; 
    private int iDateMonth = 0; 
    private int iDateDay = 0; 
 
    // 布尔变量 
    private boolean hasSelected = false; 
    private boolean isActiveMonth = false; 
    private boolean isToday = false; 
    private boolean isTouchedDown = false; 
    private boolean isHoliday = false; 
    private boolean hasMSG = false; 
 
    public static int ANIM_ALPHA_DURATION = 100; 
 
    public interface OnDateItemClickListener { 
        public void OnClick(DateWidgetDayView item); 
    } 
 
    // 构造函数 
    public DateWidgetDayView(Context context, int iWidth, int iHeight) { 
        super(context); 
        setFocusable(true); 
        setLayoutParams(new LayoutParams(iWidth, iHeight)); 
    } 
 
    // 取变量值 
    public Calendar getDate() { 
        Calendar calDate = Calendar.getInstance(); 
        calDate.clear(); 
        calDate.set(Calendar.YEAR, iDateYear); 
        calDate.set(Calendar.MONTH, iDateMonth); 
        calDate.set(Calendar.DAY_OF_MONTH, iDateDay); 
        return calDate; 
    } 
 
    // 是否有消息 
    public boolean hasMSG() { 
        return this.hasMSG; 
    } 
 
    // 是否假期 
    public boolean isHoliday() { 
        return this.isHoliday; 
    } 
 
    // 设置变量值 
    public void setData(int iYear, int iMonth, int iDay, Boolean bToday, 
            Boolean bHoliday, int iActiveMonth, boolean hasRecord) { 
        iDateYear = iYear; 
        iDateMonth = iMonth; 
        iDateDay = iDay; 
 
        this.sDate = Integer.toString(iDateDay); 
        this.isActiveMonth = (iDateMonth == iActiveMonth); 
        this.isToday = bToday; 
        this.isHoliday = bHoliday; 
        this.hasMSG = hasRecord; 
    } 
 
    // 重载绘制方法 
    @Override 
    protected void onDraw(Canvas canvas) { 
        // TODO Auto-generated method stub 
        super.onDraw(canvas); 
 
        rect.set(0, 0, this.getWidth(), this.getHeight()); 
        rect.inset(1, 1); 
 
        final boolean bFocused = IsViewFocused(); 
 
        drawDayView(canvas, bFocused); 
        drawDayNumber(canvas); 
    } 
 
    public boolean IsViewFocused() { 
        return (this.isFocused() || isTouchedDown); 
    } 
 
    // 绘制日历方格 
    private void drawDayView(Canvas canvas, boolean bFocused) { 
 
        if (hasSelected || bFocused) { 
            LinearGradient lGradBkg = null; 
 
            if (bFocused) { 
                lGradBkg = new LinearGradient(rect.left, 0, rect.right, 0, 
                        0xffaa5500, 0xffffddbb, Shader.TileMode.CLAMP); 
            } 
 
            if (hasSelected) { 
                lGradBkg = new LinearGradient(rect.left, 0, rect.right, 0, 
                        0xff225599, 0xffbbddff, Shader.TileMode.CLAMP); 
            } 
 
            if (lGradBkg != null) { 
                mPaint.setShader(lGradBkg); 
                canvas.drawRect(rect, mPaint); 
            } 
 
            mPaint.setShader(null); 
 
        } else { 
            mPaint.setColor(getColorBkg(isHoliday, isToday)); 
            canvas.drawRect(rect, mPaint); 
        } 
 
        if(isHoliday){ 
            mPaint.setColor(CalenderActivity.IsHoliday_BgColor); 
            canvas.drawRect(rect, mPaint); 
        } 
 
        if (hasMSG) { 
            markHasMSGReminder(canvas, CalenderActivity.Special_Reminder); 
        } 
        // else if (!hasRecord && !bToday && !bSelected) { 
        // CreateReminder(canvas, Calendar_TestActivity.Calendar_DayBgColor); 
        // } 
    } 
 
    // 绘制日历中的数字 
    public void drawDayNumber(Canvas canvas) { 
        // draw day number 
        mPaint.setTypeface(null); 
        mPaint.setAntiAlias(true); 
        mPaint.setShader(null); 
        mPaint.setFakeBoldText(true); 
        mPaint.setTextSize(fTextSize); 
        mPaint.setColor(CalenderActivity.IsPresentMonth_FontColor); 
        mPaint.setUnderlineText(false); 
 
        if (!isActiveMonth) 
            mPaint.setColor(CalenderActivity.UnPresentMonth_FontColor); 
 
        if (isToday) 
            mPaint.setUnderlineText(true); 
 
        final int iPosX = (int) rect.left + ((int) rect.width() >> 1) - ((int) mPaint.measureText(sDate) >> 1); 
 
        final int iPosY = (int) (this.getHeight() - (this.getHeight() - getTextHeight()) / 2 - mPaint .getFontMetrics().bottom); 
 
        canvas.drawText(sDate, iPosX, iPosY, mPaint); 
 
        mPaint.setUnderlineText(false); 
    } 
 
    // 得到字体高度 
    private int getTextHeight() { 
        return (int) (-mPaint.ascent() + mPaint.descent()); 
    } 
 
    // 根据条件返回不同颜色值 
    public static int getColorBkg(boolean bHoliday, boolean bToday) { 
        if (bToday) 
            return CalenderActivity.IsToday_BgColor; 
        // if (bHoliday) //如需周末有特殊背景色,可去掉注释 
        // return Calendar_TestActivity.isHoliday_BgColor; 
        return CalenderActivity.Calendar_DayBgColor; 
    } 
 
    // 设置是否被选中 
    @Override 
    public void setSelected(boolean bEnable) { 
        if (this.hasSelected != bEnable) { 
            this.hasSelected = bEnable; 
            this.invalidate(); 
        } 
    } 
 
    public void setItemClick(OnDateItemClickListener itemClick) { 
        this.itemClick = itemClick; 
    } 
 
    public void doItemClick() { 
        if (itemClick != null) 
            itemClick.OnClick(this); 
    } 
 
    // 点击事件 
    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
        boolean bHandled = false; 
        if (event.getAction() == MotionEvent.ACTION_DOWN) { 
            bHandled = true; 
            isTouchedDown = true; 
            invalidate(); 
            startAlphaAnimIn(DateWidgetDayView.this); 
        } 
        if (event.getAction() == MotionEvent.ACTION_CANCEL) { 
            bHandled = true; 
            isTouchedDown = false; 
            invalidate(); 
        } 
        if (event.getAction() == MotionEvent.ACTION_UP) { 
            bHandled = true; 
            isTouchedDown = false; 
            invalidate(); 
            doItemClick(); 
        } 
        return bHandled; 
    } 
 
    // 点击事件 
    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) { 
        boolean bResult = super.onKeyDown(keyCode, event); 
        if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER) 
                || (keyCode == KeyEvent.KEYCODE_ENTER)) { 
            doItemClick(); 
        } 
        return bResult; 
    } 
 
    // 不透明度渐变 
    public static void startAlphaAnimIn(View view) { 
        AlphaAnimation anim = new AlphaAnimation(0.5F, 1); 
        anim.setDuration(ANIM_ALPHA_DURATION); 
        anim.startNow(); 
        view.startAnimation(anim); 
    } 
 
    //右上角画倒三角 
    public void markHasMSGReminder(Canvas canvas, int Color) { 
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 
        mPaint.setColor(Color); 
        Path path = new Path(); 
        path.moveTo(rect.right - rect.width() / 4, rect.top); 
        path.lineTo(rect.right, rect.top); 
        path.lineTo(rect.right, rect.top + rect.width() / 4); 
        path.lineTo(rect.right - rect.width() / 4, rect.top); 
        path.close(); 
        canvas.drawPath(path, mPaint); 
    } 
} 
 
工具类: 
 
public class CalenderUtil { 
    private final static String[] vecStrWeekDayNames = getWeekDayNames(); 
 
    private static String[] getWeekDayNames() { 
        String[] vec = new String[10]; 
 
        vec[Calendar.SUNDAY] = "星期日"; 
        vec[Calendar.MONDAY] = "星期一"; 
        vec[Calendar.TUESDAY] = "星期二"; 
        vec[Calendar.WEDNESDAY] = "星期三"; 
        vec[Calendar.THURSDAY] = "星期四"; 
        vec[Calendar.FRIDAY] = "星期五"; 
        vec[Calendar.SATURDAY] = "星期六"; 
 
        return vec; 
    } 
 
    public static String getWeekDayName(int iDay) { 
        return vecStrWeekDayNames[iDay]; 
    } 
 
    public static int getWeekDay(int index, int iFirstDayOfWeek) { 
        int iWeekDay = -1; 
 
        if (iFirstDayOfWeek == Calendar.MONDAY) { 
            iWeekDay = index + Calendar.MONDAY; 
 
            if (iWeekDay > Calendar.SATURDAY) 
                iWeekDay = Calendar.SUNDAY; 
        } 
 
        if (iFirstDayOfWeek == Calendar.SUNDAY) { 
            iWeekDay = index + Calendar.SUNDAY; 
        } 
 
        return iWeekDay; 
    } 
 
    /** 
     * Calculate the days with milliseconds 
     * @param intervalMs 
     * @return 
     */ 
    public static int millisecondsToDays(long intervalMs) { 
        return Math.round((intervalMs / (1000 * 86400))); 
    } 
 
    /** 
     * Return the milliseconds from 1970 to just 
     * @param calendar 
     */ 
    public static void setTimeToMidnight(Calendar calendar) { 
        calendar.set(Calendar.HOUR_OF_DAY, 0); 
        calendar.set(Calendar.MINUTE, 0); 
        calendar.set(Calendar.SECOND, 0); 
        calendar.set(Calendar.MILLISECOND, 0); 
    } 
} 
 
calendar_main.xml: 
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:gravity="center_horizontal" 
    android:orientation="vertical" > 
 
    <RelativeLayout 
        android:id="@+id/relativeLayout1" 
        android:layout_width="fill_parent" 
        android:layout_height="60dip" 
        android:background="#EDE8DD" > 
 
        <TextView 
            android:id="@+id/Top_Date" 
            android:layout_width="150dip" 
            android:layout_height="wrap_content" 
            android:layout_centerInParent="true" 
            android:gravity="center_horizontal|center" 
            android:textColor="#424139" 
            android:textSize="19sp" 
            android:textStyle="bold" /> 
 
        <Button 
            android:id="@+id/btn_pre_month" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:layout_alignParentLeft="true" 
            android:layout_centerVertical="true" 
            android:layout_marginLeft="30dp" 
            android:background="@drawable/previous_month" 
            android:text="" /> 
 
        <Button 
            android:id="@+id/btn_next_month" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:layout_alignParentRight="true" 
            android:layout_centerVertical="true" 
            android:layout_marginRight="30dp" 
            android:background="@drawable/next_month" 
            android:text="" /> 
    </RelativeLayout> 
 
    <LinearLayout  
        android:id="@+id/date_calender_framelayout" 
        android:layout_height="fill_parent" 
        android:layout_width="fill_parent" 
        ></LinearLayout> 
 
</LinearLayout> 

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/aiops/3249.html

(0)
上一篇 2021年7月16日 14:07
下一篇 2021年7月16日 14:07

相关推荐

发表回复

登录后才能评论