自定义View日历

今天是周六,趁着还有多余的空闲,把这周的干活拿出来晒一晒。首先看项目的截图。



这个就是项目的截图,很明显这是一个日历,由于有特殊的需求,比如每个日期需要添加点击事件,分别为每天设置不同的考勤信息,类似于这种只能用自定义view去实现。

分析:

1.首先观察日历每一行的背景都是岔开的,这种如何实现。


2.每周六跟周日的日期颜色不一样。


3.特殊日期有圆形图形包起来。


4.星期要跟日期对应起来。


5.需要考虑如果一个月只有28天的话,就不需要绘制那么多行。



技术难点:

1.关于坐标的计算,这个是比较麻烦的,因为涉及到点击事件,还涉及到日期与星期的对应。


2.屏幕适配,坐标的计算以及字体的大小需要根据屏幕的适配进行调整。


3.绘制文字圆形背景的时候,如何保证文字在圆圈的中间。


5.日期切换,数据及逻辑处理等等。


我在拿到项目的需求后,首先我也在网上找了下,也有很多成熟的方案,但是我还是想自己写一些,第一给人的感觉这个应该是不难的,但是实际自己动起手来才发现,事实并不如此。当中的坑是你想不到的。但是只有自己真正的写出来才会进步,我感觉能把这个自己写出来,自定义view方面也都不是什么难事了。



解析思路:

1.为了避免背景被文字覆盖,所以需要先要绘制背景。


2.计算每个月有多少天,每个月的第一天是周几。


3.绘制文字,在绘制文字的同时,需要给文字绘制圆形背景,避免圆形背景覆盖文字。


4.添加点击事件,判断点击的坐标点是在哪个点的范围内。


(这些代码大家复制过去直接能用了)

代码:

时间处理的工具类:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;

/*
 *  @项目名:  Zhukeyunfu 
 *  @包名:    com.eben.zhukeyunfu.Activity.utils
 *  @文件名:   DateUtils
 *  @创建者:   Administrator
 *  @创建时间:  2016/11/4 15:44
 *  @描述:    TODO
 */
public class DateUtils {
    private static final String TAG = "DateUtils";

    private static String mYear; // 当前年
    private static String mMonth; //     private static String mDay;
    private static String mWay;


    /**
     * 获取当前日期几月几号
     */
    public static String getDateString() {


        final Calendar c = Calendar.getInstance();
        c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
        mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码
        if(Integer.parseInt(mDay) > MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(Integer.parseInt(mMonth)))){
            mDay = String.valueOf(MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(Integer.parseInt(mMonth))));
        }
        return mMonth + "" + mDay + "";
    }


    /**
     * 获取当前年月日
     *
     * @return
     */
    public static String StringData() {
        final Calendar c = Calendar.getInstance();
        c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        mYear = String.valueOf(c.get(Calendar.YEAR));// 获取当前年份
        mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
        mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码
        if(Integer.parseInt(mDay) > MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(Integer.parseInt(mMonth)))){
            mDay = String.valueOf(MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(Integer.parseInt(mMonth))));
        }
        return mYear + "-" + (mMonth.length()==1?"0"+mMonth:mMonth) + "-" + (mDay.length()==1?"0"+mDay:mDay);
    }


    /**
     * 根据当前日期获得是星期几
     *
     * @return
     */
    public static String getWeek(String time) {
        String Week = "";


        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        Calendar c = Calendar.getInstance();
        try {


            c.setTime(format.parse(time));


        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (c.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            Week += "周天";
        }
        if (c.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
            Week += "周一";
        }
        if (c.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY) {
            Week += "周二";
        }
        if (c.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) {
            Week += "周三";
        }
        if (c.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) {
            Week += "周四";
        }
        if (c.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
            Week += "周五";
        }
        if (c.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
            Week += "周六";
        }
        return Week;
    }


    /**
     * 获取今天往后一周的日期(几月几号)
     */
    public static List<String> getSevendate() {
        List<String> dates = new ArrayList<String>();
        final Calendar c = Calendar.getInstance();
        c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));

        for (int i = 0; i < 7; i++) {
            mYear = String.valueOf(c.get(Calendar.YEAR));// 获取当前年份
            mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
            mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH) + i);// 获取当前日份的日期号码
            if(Integer.parseInt(mDay) > MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(i+1))){
                mDay = String.valueOf(MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(i+1)));
            }
            String date = mMonth + "" + mDay + "";
            dates.add(date);
        }
        return dates;
    }


    /**
     * 获取今天往后一周的集合
     */
    public static List<String> get7week() {
        String week = "";
        List<String> weeksList = new ArrayList<String>();
        List<String> dateList = get7date();
        for (String s : dateList) {
            if (s.equals(StringData())) {
                week = "今天";
            } else {
                week = getWeek(s);
            }
            weeksList.add(week);
        }
        return weeksList;
    }


    public static List<String> get7date() {
        List<String> dates = new ArrayList<String>();
        final Calendar c = Calendar.getInstance();
        c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        java.text.SimpleDateFormat sim = new java.text.SimpleDateFormat(
                "yyyy-MM-dd");
        String date = sim.format(c.getTime());
        dates.add(date);
        for (int i = 0; i < 6; i++) {
            c.add(java.util.Calendar.DAY_OF_MONTH, 1);
            date = sim.format(c.getTime());
            dates.add(date);
        }
        return dates;
    }

    /**得到当年当月的最大日期**/
    public static int MaxDayFromDay_OF_MONTH(int year,int month){
        Calendar time=Calendar.getInstance();
        time.clear();
        time.set(Calendar.YEAR,year);
        time.set(Calendar.MONTH,month-1);//注意,Calendar对象默认一月为0
        int day=time.getActualMaximum(Calendar.DAY_OF_MONTH);//本月份的天数
        return day;
    }

    public static List<String> get7dateBefore() {
        List<String> dates = new ArrayList<String>();
     Long   currenttime=System.currentTimeMillis();
        for(int i=0;i<=6;i++){
            SimpleDateFormat format =  new SimpleDateFormat("yyyy-MM-dd");
            Long time=new  Long(currenttime-24*3600*1000*i);
            String d = format.format(time);
            dates.add(d);
        }


        return dates;
    }

        /*返回最近的12个月的月份集合*/
    public static List<String> get12Month(){

        List<String> dates = new ArrayList<String>();
        final Calendar c = Calendar.getInstance();
        c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));

        mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
        int month= Integer.parseInt(mMonth);
        for (int i=0;i<12;i++){
            if(month-i>0){
                dates.add(month-i+"");
            }
            else if (month-i==0){
            dates.add(12+"");
            }else if (month-i<0){
            dates.add(Math.abs(month-i)+"");
            }
        }

        return dates;
    }


    /**
     * 1-6 代表星期一至星期六 0 代表星期日
     * 如果返回 -1 表示参数不正确
     */
    public static int calWeek(int y, int m, int d) {
        if (m < 1 || m > 12 || d < 1 || d > 31) return -1;
        if (m == 1) {
            m = 13;
            y--;
        } else if (m == 2) {
            m = 14;
            y--;
        }
        int c = y / 100;
        y = y - c * 100;
        int week = y + y / 4 + c / 4 - 2 * c + 26 * (m + 1) / 10 + d - 1;
        week %= 7;
        week = week < 0 ? week + 7 : week;
        return week;
    }


    /**
     * 获取当月的 天数
     * */
    public static int getCurrentMonthDay() {

        Calendar a = Calendar.getInstance();
        a.set(Calendar.DATE, 1);
        a.roll(Calendar.DATE, -1);
        int maxDate = a.get(Calendar.DATE);
        return maxDate;
    }


    /*获取当前是哪一年*/
    public static int getYear(){

        final Calendar c = Calendar.getInstance();
        c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        /*mYear = String.valueOf(c.get(Calendar.YEAR));// 获取当前年份
        mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
        mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码*/
        return c.get(Calendar.YEAR);

    }


    /*获取当前的月份*/
    public static int getMonth(){
        final Calendar c = Calendar.getInstance();
        c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        /*mYear = String.valueOf(c.get(Calendar.YEAR));// 获取当前年份
        mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
        mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码*/
        return c.get(Calendar.MONTH) + 1;
    }


    /**
     * 根据年 月 获取对应的月份 天数
     * */
    public static int getDaysByYearMonth(int year, int month) {

        Calendar a = Calendar.getInstance();
        a.set(Calendar.YEAR, year);
        a.set(Calendar.MONTH, month - 1);
        a.set(Calendar.DATE, 1);
        a.roll(Calendar.DATE, -1);
        int maxDate = a.get(Calendar.DATE);
        return maxDate;
    }

}

自定义View的代码,因为是做项目的,所以没办法把所有的代码都放进来,后面会建一个文件夹打包把所有需要的放一起,给大家下载使用。

package com.eben.zhukeyunfu.Activity.view;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import com.eben.zhukeyunfu.Activity.utils.DateUtils;
import com.eben.zhukeyunfu.R;

import java.util.List;

/*
 *  @项目名:  Zhukeyunfu 
 *  @包名:    com.eben.zhukeyunfu.Activity.view
 *  @文件名:   MyCalendar
 *  @创建者:   Administrator
 *  @创建时间:  2017/2/20 9:29
 *  @描述:    TODO
 */
public class MyCalendar extends View {
    private static final String TAG = "MyCalendar";
    private int           mViewWidth;
    private int           mViewHeight;
    private Paint         mPaint;
    private String[]      mWeek;
    private Paint         whiteBgpaint;
    private Paint         grayBgpaint;
    private Paint         mBlackPaint;
    private float         textHight;
    private Paint         kuanggongBgpaint;
    private List<Integer> mKuanggong;
    private List<Integer> mQiantui;
    private List<Integer> mZaotui;
    private List<Integer> mChiDao;
    private List<Integer> mWeiQianDao;
    private Paint         zaotuipaint;
    private Paint         chidaopaint;
    private Paint         weiqiandaopaint;
    private Paint         weiqiantuipaint;

    private int mWeekFirst1;
    private int year;
    private int month;
    private int mMonthdays;
    private Paint grayTextpaint;
    private int mZiti20;
    private int mZiti27;
    private int mZiti25;
    private float mTextHeight;
    private float mTextWidth;


    public MyCalendar(Context context) {
        super(context);
    }

    public MyCalendar(Context context, AttributeSet attrs) {
        super(context, attrs);
        initWeek();
        //initdata();
        initZiTi();
        initBluePaint();
        initGrayPaint();
        initGrayTextPaint();
        initWhiteBackgroundPaint();
        initGrayBackgroundPaint();
        initKuangGongPaint();
        initWeiQianTuiPaint();
        initWeiQianDaoPaint();
        initChiDaoPaint();
        initZaoTuiPaint();


    }

    private void initZiTi() {
        mZiti20 = sp2px(getContext(),13);
        mZiti27 =sp2px(getContext(),15);;
        mZiti25 =sp2px(getContext(),17);;
        Log.d(TAG,mZiti20+"-----"+mZiti27+"----"+mZiti25);

    }

    /*ps转成sp保证字体大小不变*/
    //注意:这里的paint设置字体大小是非常重要的,但是grayBgpaint.setTextSize(20); 这里的20px,所以需要将sp转成ps转成

    public  float px2sp(Context context, int pxValue) {
        /**/
        DisplayMetrics dm       =context.getResources().getDisplayMetrics();
        int            w_screen = dm.widthPixels;
        int            h_screen = dm.heightPixels;
        int dpi=dm.densityDpi;
       // Toast.makeText(context,"屏幕尺寸2:宽度 = " + w_screen + "高度 = " + h_screen + "密度 = " + dm.densityDpi,Toast.LENGTH_SHORT).show();
        Log.i(TAG, "屏幕尺寸2:宽度 = " + w_screen + "高度 = " + h_screen + "密度 = " + dm.densityDpi);

        /*pxValue 传入 25  27  29*/
        return 240*pxValue/260;
    }
    /**
     * sp值转换为px值,保证文字大小不变
     *            DisplayMetrics类中属性scaledDensity     * @return
     */
    public  int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }






    private void initWeek() {
        mWeek = new String[]{"",
                             "",
                             "",
                             "",
                             "",
                             "",
                             ""};
    }



    /*测量*/
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        /*特别注意,此处必须要自己进行测量,否则系统会默认讲 wrap_cotentmatch_parent视为相同,也就是会填充整个布局*/
        setMeasuredDimension(measure(widthMeasureSpec), measure(heightMeasureSpec));

        getViewXY();

    }

    /*自己测量view的宽高*/
    private int measure(int measureSpec) {
        int result = 0;
        //分别获取测量模式 和 测量大小
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        //如果是精确度模式,呢就按xml中定义的来
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        }
        //如果是最大值模式,就按我们定义的来
        else if (specMode == MeasureSpec.AT_MOST) {

            result = mViewWidth * 6 / 8;
        }

        return result;
    }


    /*获取自定义view的宽度*/
    private void getViewXY() {
        mViewWidth = getMeasuredWidth();
        mViewHeight = getMeasuredHeight();
    }



    /*根据paint获取绘制文字的宽高*/
    public float getFontHeight(Paint paint)
    {
        Paint.FontMetrics fm = paint.getFontMetrics();
        return (float) (Math.ceil(fm.descent - fm.top) + 2);
    }



    /*画图*/
    @Override
    protected void onDraw(Canvas canvas) {
        /*先画背景*/
        drawbackWeekground(canvas);

        /*获取每个竖直列的坐标*/
        float x1 = mViewWidth / 8;

        float y1 = x1 / 2;
        Log.d(TAG, "文字的高度" + textHight / 2);

        Log.d(TAG, "y1-----" + y1);

        Log.d(TAG, "x1-----" + x1);
        
        /*获取屏幕的宽度*/
        /*画文字周日~周六*/
        for (int i = 0; i < 7; i++) {
            canvas.drawText(mWeek[i],
                            x1 * (i + 1) ,
                            y1,
                            mPaint);
        }
        /*获取当前月份的天数*/
        //mMonthdays = DateUtils.getCurrentMonthDay();
        /*获取当前月份的第一天是星期几*/
       /* int year  = DateUtils.getYear();
        int month = DateUtils.getMonth();*/


        Log.d(TAG, "当前月份的第一天是ondraw" + mWeekFirst1);
        if (mMonthdays == 28 && mWeekFirst1 == 0) {
            /*那么只需要画四行,否则需要❀五行数字*/
            /*如果一个月只有28天,并且第一天刚好是周末,那么就刚刚好满足4行共28个数字,那么直需要画四行背景*/
            drawbackground(canvas,4);
            /*这样的话,就依次画数字就行*/

        } else {
            /*继续画背景,其他情况,一个月份就需要画5行背景*/
            drawbackground(canvas,5);
        }

            /*画五行数字*/
            int j = 1;


            for (int i = 1; i <= mMonthdays; i++) {
            /*准备开始画数字*/
            /*如果是10或者20的,就画个圆*/

            /*缺勤的天数处理*/

            /*获取圆的坐标*/
                float cx = x1 * (mWeekFirst1 + 1);
                float cy = x1 * j+y1 ;

                /*获取文字的宽高*/
                Paint.FontMetrics fm         = kuanggongBgpaint.getFontMetrics();
                mTextWidth = kuanggongBgpaint.measureText(i + "");
                mTextHeight = fm.bottom - fm.top;


                if (mKuanggong!=null&&mKuanggong.contains(i)) {

                /*画圆*/

                    canvas.drawCircle(cx, cy, mTextHeight / 2 + 8, kuanggongBgpaint);
                    canvas.drawText(i + "",
                                    cx ,
                                    cy+mTextHeight /4,
                                    whiteBgpaint);

                } else if (mChiDao!=null&&mChiDao.contains(i)) {
                /*迟到*/

                    canvas.drawCircle(cx, cy, mTextHeight /2 + 8, chidaopaint);
                    canvas.drawText(i + "",
                                    cx ,
                                    cy+mTextHeight /4,
                                    whiteBgpaint);

                } else if (mQiantui!=null&&mQiantui.contains(i)) {
                /*未签到*/
                    canvas.drawCircle(cx, cy, mTextHeight / 2 + 8, weiqiandaopaint);
                    canvas.drawText(i + "",
                                    cx ,
                                    cy+mTextHeight /4,
                                    whiteBgpaint);

                } else if (mZaotui!=null&&mZaotui.contains(i)) {
                /**/

                    canvas.drawCircle(cx, cy, mTextHeight / 2 + 8, zaotuipaint);
                    canvas.drawText(i + "",
                                    cx ,
                                    cy+mTextHeight /4,
                                    whiteBgpaint);

                } else if (mQiantui!=null&&mQiantui.contains(i)) {
                /*未签退*/

                    canvas.drawCircle(cx, cy, mTextHeight / 2 + 8, weiqiantuipaint);
                    canvas.drawText(i + "",
                                    cx ,
                                    cy+mTextHeight /4,
                                    whiteBgpaint);
                } else {
                      /*处理周六与周日的文字颜色问题paint   grayTextpaint*/
                    if (mWeekFirst1==0||mWeekFirst1==6){
                        canvas.drawText(i + "",
                                        cx ,
                                        cy+mTextHeight /4,
                                        grayTextpaint);
                    }else {
                        canvas.drawText(i + "",
                                        cx ,
                                        cy+mTextHeight /4,
                                        mBlackPaint);
                    }
                }

                mWeekFirst1++;
                if (mWeekFirst1 == 7) {
                    mWeekFirst1 = 0;
                    j++;
                }

            }

    }


    /*画背景*/
    private void drawbackWeekground(Canvas canvas){
        /*背景1*/
        RectF oval1 = new RectF(0, 0, mViewWidth, mViewWidth / 8);// 设置个新的长方形
        canvas.drawRoundRect(oval1, 0, 0, whiteBgpaint);//第二个参数是x半径,第三个参数是y半径
    }

    /*画背景*/
    private void drawbackground(Canvas canvas,int hangshu) {


         /*背景2*/
        RectF oval2 = new RectF(0, mViewWidth / 8, mViewWidth, mViewWidth * 2 / 8);// 设置个新的长方形
        canvas.drawRoundRect(oval2, 0, 0, grayBgpaint);//第二个参数是x半径,第三个参数是y半径


         /*背景3*/
        RectF oval3 = new RectF(0, mViewWidth * 2 / 8, mViewWidth, mViewWidth * 3 / 8);// 设置个新的长方形
        canvas.drawRoundRect(oval3, 0, 0, whiteBgpaint);//第二个参数是x半径,第三个参数是y半径


         /*背景4*/
        RectF oval4 = new RectF(0, mViewWidth * 3 / 8, mViewWidth, mViewWidth * 4 / 8);// 设置个新的长方形
        canvas.drawRoundRect(oval4, 0, 0, grayBgpaint);//第二个参数是x半径,第三个参数是y半径

        /*背景5*/
        RectF oval5 = new RectF(0, mViewWidth * 4 / 8, mViewWidth, mViewWidth * 5 / 8);// 设置个新的长方形
        canvas.drawRoundRect(oval5, 0, 0, whiteBgpaint);//第二个参数是x半径,第三个参数是y半径
        if(hangshu==4){
            return;
        }else if(hangshu==5){
             /*背景6*/
            RectF oval6 = new RectF(0, mViewWidth * 5 / 8, mViewWidth, mViewWidth * 6 / 8);// 设置个新的长方形
            canvas.drawRoundRect(oval6, 0, 0, grayBgpaint);//第二个参数是x半径,第三个参数是y半径
        }

    }

    /*触摸处理*/

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        float y = event.getY();
        float x = event.getX();
        float lineheight=mViewWidth / 8;
        float row=x/lineheight;
        mWeekFirst1=DateUtils.calWeek(year, month, 1);

        Log.d(TAG, "当前月份的第一天是ontouch" + mWeekFirst1);
        //获取手指的操作--》按下、移动、松开
        Log.d(TAG, "点击了坐标 x = "+x+"  y ="+y);
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN://按下
                Log.i(TAG, "ACTION_DOWN");
                if (y/lineheight>0.0f&&y/lineheight<1.0f){
                    Log.d(TAG, "onTouchEvent: 第一行");

                }
                else if (y/lineheight>1.0f&&y/lineheight<2.0f){
                    Log.d(TAG, "onTouchEvent: 第二行");
                    for (int i=1;i<=7;i++){
                        if (x<i*lineheight+lineheight/2&&x>=i*lineheight-lineheight/2){
                            Log.d(TAG,"点击了第2行的,第"+(i)+"");
                            Log.d(TAG, "onTouchEvent: 实际坐标点"+(i-mWeekFirst1));
                            if (i-mWeekFirst1>0){
                                Toast.makeText(getContext(),"点击了"+month+""+(i-mWeekFirst1)+"",Toast.LENGTH_SHORT).show();
                            }
                            break;
                        }
                    }
                }
                else if (y/lineheight>2.0f&&y/lineheight<3.0f){
                    Log.d(TAG, "onTouchEvent: 第三行");
                    for (int i=1;i<=7;i++){
                        if (x<i*lineheight+lineheight/2&&x>=i*lineheight-lineheight/2){
                            Log.d(TAG,"点击了第3行的,第"+(i)+"");
                            Log.d(TAG, "onTouchEvent: 实际坐标点"+(7-mWeekFirst1+i));
                            Toast.makeText(getContext(),"点击了"+month+""+(7-mWeekFirst1+i)+"",Toast.LENGTH_SHORT).show();
                            break;
                        }
                    }
                }
                else if (y/lineheight>3.0f&&y/lineheight<4.0f){
                    Log.d(TAG, "onTouchEvent: 第四行");
                    for (int i=1;i<=7;i++){
                        if (x<i*lineheight+lineheight/2&&x>=i*lineheight-lineheight/2){
                            Log.d(TAG,"点击了第4行的,第"+(i)+"");
                            Log.d(TAG, "onTouchEvent: 实际坐标点"+(7-mWeekFirst1+i+7));
                            Toast.makeText(getContext(),"点击了"+month+""+(7-mWeekFirst1+i+7)+"",Toast.LENGTH_SHORT).show();
                            break;
                        }
                    }
                }
                else if (y/lineheight>4.0f&&y/lineheight<5.0f){
                    Log.d(TAG, "onTouchEvent: 第五行");
                    for (int i=1;i<=7;i++){
                        if (x<i*lineheight+lineheight/2&&x>=i*lineheight-lineheight/2){
                            Log.d(TAG,"点击了第5行的,第"+(i)+"");
                            Log.d(TAG, "onTouchEvent: 实际坐标点"+(7-mWeekFirst1+i+7*2));
                            Toast.makeText(getContext(),"点击了"+month+""+(7-mWeekFirst1+i+7*2)+"",Toast.LENGTH_SHORT).show();

                            break;
                        }
                    }
                }
                else if (y/lineheight>5.0f&&y/lineheight<6.0f){
                    Log.d(TAG, "onTouchEvent: 第六行");
                    for (int i=1;i<=7;i++){
                        if (x<i*lineheight+lineheight/2&&x>=i*lineheight-lineheight/2){
                            Log.d(TAG,"点击了第6行的,第"+(i)+"");
                            Log.d(TAG, "onTouchEvent: 实际坐标点"+(7-mWeekFirst1+i+7*3));
                            if (7-mWeekFirst1+i+7*3<=mMonthdays){
                                Toast.makeText(getContext(),"点击了"+month+""+(7-mWeekFirst1+i+7*3)+"",Toast.LENGTH_SHORT).show();
                            }
                            break;
                        }
                    }
                }else{
                    Log.d(TAG, "onTouchEvent: 无效区域");
                }

                break;

            case MotionEvent.ACTION_MOVE://移动

                break;
            case MotionEvent.ACTION_UP://松开

                break;

        }
        return  true;

    }


    /*初始化画笔paint*/
    private void initZaoTuiPaint() {
        zaotuipaint = new Paint();
        zaotuipaint.setAntiAlias(true);//去锯齿
        zaotuipaint.setColor(getResources().getColor(R.color.zaotui));
        zaotuipaint.setTextSize(mZiti20);
        //  消除字体锯齿
        zaotuipaint.setFlags(Paint.ANTI_ALIAS_FLAG);
    }

    private void initChiDaoPaint() {

        chidaopaint = new Paint();
        chidaopaint.setAntiAlias(true);//去锯齿
        chidaopaint.setColor(getResources().getColor(R.color.chidao));
        chidaopaint.setTextSize(mZiti20);
        //  消除字体锯齿
        chidaopaint.setFlags(Paint.ANTI_ALIAS_FLAG);

    }

    private void initWeiQianDaoPaint() {
        weiqiandaopaint = new Paint();
        weiqiandaopaint.setAntiAlias(true);//去锯齿
        weiqiandaopaint.setColor(getResources().getColor(R.color.weiqioandao));
        weiqiandaopaint.setTextSize(mZiti20);
        //  消除字体锯齿
        weiqiandaopaint.setFlags(Paint.ANTI_ALIAS_FLAG);

    }

    private void initWeiQianTuiPaint() {
        weiqiantuipaint = new Paint();
        weiqiantuipaint.setAntiAlias(true);//去锯齿
        weiqiantuipaint.setColor(getResources().getColor(R.color.weiqioantui));
        weiqiantuipaint.setTextSize(mZiti20);
        //  消除字体锯齿
        weiqiantuipaint.setFlags(Paint.ANTI_ALIAS_FLAG);

    }

    private void initKuangGongPaint() {
        kuanggongBgpaint = new Paint();
        kuanggongBgpaint.setAntiAlias(true);//去锯齿
        kuanggongBgpaint.setColor(getResources().getColor(R.color.kuanggong));
        kuanggongBgpaint.setTextSize(mZiti20);
        //  消除字体锯齿
        kuanggongBgpaint.setFlags(Paint.ANTI_ALIAS_FLAG);
    }

    private void initBluePaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);//去锯齿
        mPaint.setColor(getResources().getColor(R.color.skyBlue));
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setTextSize(mZiti25);


        //  消除字体锯齿
        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        textHight = getFontHeight(mPaint);
    }



    private void initGrayPaint() {
        mBlackPaint = new Paint();
        mBlackPaint.setAntiAlias(true);//去锯齿
        mBlackPaint.setColor(Color.BLACK);
        mBlackPaint.setTextSize(mZiti27);
        mBlackPaint.setTextAlign(Paint.Align.CENTER);
        //  消除字体锯齿
        mBlackPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
    }

    private void initGrayBackgroundPaint() {
        grayBgpaint = new Paint();
        grayBgpaint.setAntiAlias(true);//去锯齿
        grayBgpaint.setColor(getResources().getColor(R.color.grayBG));
        grayBgpaint.setTextSize(mZiti20);
        //  消除字体锯齿
        grayBgpaint.setFlags(Paint.ANTI_ALIAS_FLAG);
    }


    private void initWhiteBackgroundPaint() {

        whiteBgpaint = new Paint();
        whiteBgpaint.setAntiAlias(true);//去锯齿
        whiteBgpaint.setColor(Color.WHITE);
        whiteBgpaint.setTextSize(mZiti20);
        whiteBgpaint.setTextAlign(Paint.Align.CENTER);
        //  消除字体锯齿
        whiteBgpaint.setFlags(Paint.ANTI_ALIAS_FLAG);
    }



    private void initGrayTextPaint() {

        grayTextpaint = new Paint();
        grayTextpaint.setAntiAlias(true);//去锯齿
        grayTextpaint.setColor(getResources().getColor(R.color.grayText));
        grayTextpaint.setTextSize(mZiti27);
        /*设置文字的重点点坐标开始画*/
        grayTextpaint.setTextAlign(Paint.Align.CENTER);
        //  消除字体锯齿
        grayTextpaint.setFlags(Paint.ANTI_ALIAS_FLAG);
    }

    /*设置是哪一年*/
    public void setYear(int year) {
        this.year=year;

    }


    public void setMonth(int month) {
        this.month=month;

        /*根据年、月获取 该月份的第一天是星期几*/
        mWeekFirst1 = DateUtils.calWeek(year, month, 1);
    }

    public void setTotalDays(int daysByYearMonth) {
        this.mMonthdays=daysByYearMonth;

    }

    public void setdata(List<Integer> kuanggong,
                        List<Integer> qiantui,
                        List<Integer> zaotui,
                        List<Integer> chiDao,
                        List<Integer> weiQianDao) {
        this.mKuanggong=kuanggong;
        this.mQiantui=qiantui;
        this.mZaotui=zaotui;
        this.mChiDao=chiDao;
        this.mWeiQianDao=weiQianDao;

        /*设置数据后,重新绘制图形*/
        postInvalidate();
    }

       /* private void initdata() {
        mKuanggong = Arrays.asList(10, 20, 12);
        mQiantui = Arrays.asList(6);
        mZaotui = Arrays.asList(7);
        mChiDao = Arrays.asList(9);
        mWeiQianDao = Arrays.asList(13);
        }*/
}

Activity代码:

package com.eben.zhukeyunfu.Activity.textexampleActivity;

import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.eben.zhukeyunfu.Activity.utils.DateUtils;
import com.eben.zhukeyunfu.Activity.view.MyCalendar;
import com.eben.zhukeyunfu.R;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.appindexing.Thing;
import com.google.android.gms.common.api.GoogleApiClient;

import java.util.Arrays;
import java.util.List;

import static com.eben.zhukeyunfu.R.anim.slide_left_in;
import static com.eben.zhukeyunfu.R.anim.slide_right_out;

/*
 *  @项目名:  Zhukeyunfu 
 *  @包名:    com.eben.zhukeyunfu.Activity.textexampleActivity
 *  @文件名:   HeartActivity
 *  @创建者:   Administrator
 *  @创建时间:  2017/2/13 15:28
 *  @描述:    TODO
 */
public class KaoQinActivity
        extends AppCompatActivity
{
    private static final String TAG = "FootActivity";
    private int           mYear;
    private int           mMonth;
    private List<Integer> mKuanggong;
    private List<Integer> mQiantui;
    private List<Integer> mZaotui;
    private List<Integer> mChiDao;
    private List<Integer> mWeiQianDao;
    private TextView     mSwitchMdoe;
    private AnimationSet  mAnimationSet1;
    private AnimationSet  mAnimationSet2;
    private AnimationSet  mAnimationSet3;
    private AnimationSet  mAnimationSet4;
    private boolean islist = true;
    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    private GoogleApiClient mClient;
    private LinearLayout mCalendar_mode;
    private ListView mList_mode;
    private int mDays1Month;
    private Myadapter mMyadapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        changeColor();
        setContentView(R.layout.kaoqin);

        //初始化actionbar
        //initactionbar();
        //初始化布局
        //改变手机状态栏颜色
        initview();
        initanimator();
        initlistener();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        mClient = new GoogleApiClient.Builder(this).addApi(AppIndex.API)
                                                   .build();
    }

    private void initanimator() {
        mAnimationSet1 = (AnimationSet) AnimationUtils.loadAnimation(KaoQinActivity.this, R.anim.slide_left_in);
        mAnimationSet2 = (AnimationSet) AnimationUtils.loadAnimation(KaoQinActivity.this, R.anim.slide_left_out);
        mAnimationSet3 = (AnimationSet) AnimationUtils.loadAnimation(KaoQinActivity.this, R.anim.slide_right_in);
        mAnimationSet4 = (AnimationSet) AnimationUtils.loadAnimation(KaoQinActivity.this, R.anim.slide_right_out);

        /*四个动画的监听*/
        mAnimationSet1.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        mAnimationSet2.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                mCalendar_mode.setVisibility(View.GONE);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        mAnimationSet3.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        mAnimationSet4.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                mList_mode.setVisibility(View.GONE);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }





    private void initlistener() {

         /*切换视图*/
        mSwitchMdoe.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*开始切换模式,执行动画*/
                if (islist == true) {
                    mSwitchMdoe.setText("考勤");
                    mCalendar_mode.startAnimation(mAnimationSet2);
                    mList_mode.startAnimation(mAnimationSet3);
                    mList_mode.setVisibility(View.VISIBLE);
                    islist=false;

                }else {
                    mSwitchMdoe.setText("工资");
                    mCalendar_mode.startAnimation(mAnimationSet1);
                    mList_mode.startAnimation(mAnimationSet4);
                    mCalendar_mode.setVisibility(View.VISIBLE);
                    islist=true;
                }

            }
        });

        mMyadapter = new Myadapter();

        mList_mode.setAdapter(mMyadapter);


    }

    private void initview() {
        ImageView mBack = (ImageView) findViewById(R.id.back_heart);
        mBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
                overridePendingTransition(slide_left_in, slide_right_out);
            }
        });


        /*设置日期*/
        final TextView date = (TextView) findViewById(R.id.date);
        /*获取当前的月份及年份*/
        mYear = DateUtils.getYear();
        mMonth = DateUtils.getMonth();
        date.setText(mYear + "" + mMonth + "");

        /**/
        final MyCalendar myCalendar = (MyCalendar) findViewById(R.id.myCalendar);

        /*设置日期*/
        myCalendar.setYear(mYear);
        myCalendar.setMonth(mMonth);
        mKuanggong = Arrays.asList(10, 20, 12);
        mQiantui = Arrays.asList(6);
        mZaotui = Arrays.asList(7);
        mChiDao = Arrays.asList(9);
        mWeiQianDao = Arrays.asList(13);
        /*根据年和月获取天数*/

        mDays1Month = DateUtils.getDaysByYearMonth(mYear, mMonth);
        myCalendar.setTotalDays(mDays1Month);

        myCalendar.setdata(mKuanggong, mQiantui, mZaotui, mChiDao, mWeiQianDao);



        /*查看下一月的数据*/
        ImageView addMonth = (ImageView) findViewById(R.id.addMonth);
        addMonth.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mMonth++;
                if (mMonth == 13) {
                    mMonth = 1;
                    mYear++;
                }
                date.setText(mYear + "" + mMonth + "");
                myCalendar.setYear(mYear);
                myCalendar.setMonth(mMonth);


                /*根据年和月获取天数*/
                myCalendar.setTotalDays(DateUtils.getDaysByYearMonth(mYear, mMonth));
                myCalendar.setdata(null, null, null, null, null);

                mMyadapter.notifyDataSetChanged();
            }
        });

        /*查看前一月的数据*/
        ImageView decreaseMonth = (ImageView) findViewById(R.id.decreaseMonth);
        decreaseMonth.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mMonth--;
                if (mMonth == 0) {
                    mMonth = 12;
                    mYear--;
                }


                date.setText(mYear + "" + mMonth + "");
                myCalendar.setYear(mYear);
                myCalendar.setMonth(mMonth);
                /*根据年和月获取天数*/
                myCalendar.setTotalDays(DateUtils.getDaysByYearMonth(mYear, mMonth));
                if (mMonth % 4 == 0) {
                    myCalendar.setdata(mKuanggong, mQiantui, mZaotui, mChiDao, mWeiQianDao);

                } else {
                    myCalendar.setdata(null, null, null, null, null);

                }
                mMyadapter.notifyDataSetChanged();
            }
        });


        /*切换视图*/
        mSwitchMdoe = (TextView) findViewById(R.id.switch_mdoe);
        /*日历模式view*/
        mCalendar_mode = (LinearLayout) findViewById(R.id.calendar_mode);
        /*列表模式*/
        mList_mode = (ListView) findViewById(R.id.list_mode);


    }

    private void changeColor() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            //            View decorView = getWindow().getDecorView();
            //            int  visibility = View.SYSTEM_UI_FLAG_FULLSCREEN;// 全屏设置
            //            int visibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;// 表示允许应用的主题内容占用状态栏的空间
            //            decorView.setSystemUiVisibility(visibility);
            getWindow().setStatusBarColor(getResources().getColor(R.color.black));// 通知栏颜色
        }

    }


    //处理后退键的情况
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {

            this.finish();  //finish当前activity
            overridePendingTransition(slide_left_in, slide_right_out);
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    public Action getIndexApiAction() {
        Thing object = new Thing.Builder().setName("KaoQin Page") // TODO: Define a title for the content shown.
                                          // TODO: Make sure this auto-generated URL is correct.
                                          .setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
                                          .build();
        return new Action.Builder(Action.TYPE_VIEW).setObject(object)
                                                   .setActionStatus(Action.STATUS_TYPE_COMPLETED)
                                                   .build();
    }

    @Override
    public void onStart() {
        super.onStart();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        mClient.connect();
        AppIndex.AppIndexApi.start(mClient, getIndexApiAction());
    }

    @Override
    public void onStop() {
        super.onStop();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        AppIndex.AppIndexApi.end(mClient, getIndexApiAction());
        mClient.disconnect();
    }


    class  Myadapter extends BaseAdapter{

        @Override
        public int getCount() {
            mDays1Month = DateUtils.getDaysByYearMonth(mYear, mMonth);
            if (mDays1Month>0){
                return mDays1Month;
            }
            return 0;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder=null;
            if (holder==null){
                holder=new ViewHolder();
                convertView=View.inflate(KaoQinActivity.this,R.layout.listitem_kaoqin,null);
                holder.mTextView= (TextView) convertView.findViewById(R.id.datalist);
            }
            holder.mTextView.setText(mMonth+""+(position+1)+"");
            return convertView;
        }

        class  ViewHolder{
                TextView mTextView;
        }
    }
}


当然代码有点多了,还有一些自定义的drawable什么的,都放在后面的压缩包里面,最后谢谢大家,供大家参考,这只是我自己的方案,没有参考别人的,获取网上有其他比我容易的方案,也请大家不要拍砖,我这个不是单独的demo,要使用这个需要自己把相关内容加进去才能使用。代码不简洁,也没有优化,请体谅。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值