• 第一阶段冲刺7


    package com.example.zbytexttwo;

    import android.os.Bundle;

    import android.util.Log;

    import android.widget.Toast;

    import androidx.appcompat.app.AppCompatActivity;

    import java.util.ArrayList;

    import java.util.Date;

    import java.util.List;

    public class MainJmActivity extends AppCompatActivity {

        private CustomCalendar cal;

        @Override

        protected void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_main_jm);

            cal = (CustomCalendar)findViewById(R.id.cal);

            //TODO 模拟请求当月数据

            final List<DayFinish> list = new ArrayList<>();

            list.add(new DayFinish(1,2,2));

            list.add(new DayFinish(2,1,2));

            list.add(new DayFinish(3,0,2));

            list.add(new DayFinish(4,2,2));

            list.add(new DayFinish(5,2,2));

            list.add(new DayFinish(6,2,2));

            list.add(new DayFinish(7,2,2));

            list.add(new DayFinish(8,0,2));

            list.add(new DayFinish(9,1,2));

            list.add(new DayFinish(10,2,2));

            list.add(new DayFinish(11,5,2));

            list.add(new DayFinish(12,2,2));

            list.add(new DayFinish(13,2,2));

            list.add(new DayFinish(14,3,2));

            list.add(new DayFinish(15,2,2));

            list.add(new DayFinish(16,1,2));

            list.add(new DayFinish(17,0,2));

            list.add(new DayFinish(18,2,2));

            list.add(new DayFinish(19,2,2));

            list.add(new DayFinish(20,0,2));

            list.add(new DayFinish(21,2,2));

            list.add(new DayFinish(22,1,2));

            list.add(new DayFinish(23,2,0));

            list.add(new DayFinish(24,0,2));

            list.add(new DayFinish(25,2,2));

            list.add(new DayFinish(26,2,2));

            list.add(new DayFinish(27,2,2));

            list.add(new DayFinish(28,2,2));

            list.add(new DayFinish(29,2,2));

            list.add(new DayFinish(30,2,2));

            list.add(new DayFinish(31,2,2));

            cal.setRenwu("20171", list);

            cal.setOnClickListener(new CustomCalendar.onClickListener() {

                @Override

                public void onLeftRowClick() {

                    Toast.makeText(MainJmActivity.this, "点击减箭头", Toast.LENGTH_SHORT).show();

                    cal.monthChange(-1);

                    new Thread(){

                        @Override

                        public void run() {

                            try{

                                Thread.sleep(1000);

                                MainJmActivity.this.runOnUiThread(new Runnable() {

                                    @Override

                                    public void run() {

                                        cal.setRenwu(list);

                                    }

                                });

                            }catch (Exception e){

                            }

                        }

                    }.start();

                }

                @Override

                public void onRightRowClick() {

                    Toast.makeText(MainJmActivity.this, "点击加箭头", Toast.LENGTH_SHORT).show();

                    cal.monthChange(1);

                    new Thread(){

                        @Override

                        public void run() {

                            try{

                                Thread.sleep(1000);

                                MainJmActivity.this.runOnUiThread(new Runnable() {

                                    @Override

                                    public void run() {

                                        cal.setRenwu(list);

                                    }

                                });

                            }catch (Exception e){

                            }

                        }

                    }.start();

                }

                @Override

                public void onTitleClick(String monthStr, Date month) {

                    Toast.makeText(MainJmActivity.this, "点击了标题:"+monthStr, Toast.LENGTH_SHORT).show();

                }

                @Override

                public void onWeekClick(int weekIndex, String weekStr) {

                    Toast.makeText(MainJmActivity.this, "点击了星期:"+weekStr, Toast.LENGTH_SHORT).show();

                }

                @Override

                public void onDayClick(int day, String dayStr, DayFinish finish) {

                    Toast.makeText(MainJmActivity.this, "点击了日期:"+dayStr, Toast.LENGTH_SHORT).show();

                    Log.w("", "点击了日期:"+dayStr);

                }

            });

        }

        class DayFinish{

            int day;

            int all;

            int finish;

            public DayFinish(int day, int finish, int all) {

                this.day = day;

                this.all = all;

                this.finish = finish;

            }

        }

    }

    MainJmActivity

    package com.example.zbytexttwo;

    import android.content.Context;

    import android.content.res.TypedArray;

    import android.graphics.Bitmap;

    import android.graphics.BitmapFactory;

    import android.graphics.Canvas;

    import android.graphics.Color;

    import android.graphics.DashPathEffect;

    import android.graphics.Paint;

    import android.graphics.PathEffect;

    import android.graphics.PointF;

    import android.graphics.RectF;

    import android.util.AttributeSet;

    import android.util.Log;

    import android.view.MotionEvent;

    import android.view.View;

    import java.text.SimpleDateFormat;

    import java.util.Calendar;

    import java.util.Date;

    import java.util.HashMap;

    import java.util.List;

    import java.util.Map;

    /**

     * author : openXu

     * create at : 2017/1/3 9:56

     * blog : http://blog.csdn.net/xmxkf

     * gitHub : https://github.com/openXu

     * project : CustomCalendar

     * class name : CustomCalendar

     * version : 1.0

     * class describe:自定义日历控件

     */

    public class CustomCalendar extends View{

        private String TAG = "CustomCalendar";

        /** 各部分背景*/

        private int mBgMonth, mBgWeek, mBgDay, mBgPre;

        /** 标题的颜色、大小*/

        private int mTextColorMonth;

        private float mTextSizeMonth;

        private int mMonthRowL, mMonthRowR;

        private float mMonthRowSpac;

        private float mMonthSpac;

        /** 星期的颜色、大小*/

        private int mTextColorWeek, mSelectWeekTextColor;

        private float mTextSizeWeek;

        /** 日期文本的颜色、大小*/

        private int mTextColorDay;

        private float mTextSizeDay;

        /** 任务次数文本的颜色、大小*/

        private int mTextColorPreFinish, mTextColorPreUnFinish, mTextColorPreNull;

        private float mTextSizePre;

        /** 选中的文本的颜色*/

        private int mSelectTextColor;

        /** 选中背景*/

        private int mSelectBg, mCurrentBg;

        private float mSelectRadius, mCurrentBgStrokeWidth;

        private float[] mCurrentBgDashPath;

        /** 行间距*/

        private float mLineSpac;

        /** 字体上下间距*/

        private float mTextSpac;

        private Paint mPaint;

        private Paint bgPaint;

        private float titleHeight, weekHeight, dayHeight, preHeight, oneHeight;

        private int columnWidth;       //每列宽度

        private Date month; //当前的月份

        private boolean isCurrentMonth;       //展示的月份是否是当前月

        private int currentDay, selectDay, lastSelectDay;    //当前日期 、 选中的日期 、上一次选中的日期(避免造成重复回调请求)

        private int dayOfMonth;    //月份天数

        private int firstIndex;    //当月第一天位置索引

        private int todayWeekIndex;//今天是星期几

        private int firstLineNum, lastLineNum; //第一行、最后一行能展示多少日期

        private int lineNum;      //日期行数

        private String[] WEEK_STR = new String[]{"Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat", };

        public CustomCalendar(Context context) {

            this(context, null);

        }

        public CustomCalendar(Context context, AttributeSet attrs) {

            this(context, attrs, 0);

        }

        public CustomCalendar(Context context, AttributeSet attrs, int defStyleAttr) {

            super(context, attrs, defStyleAttr);

            //获取自定义属性的值

            TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomCalendar, defStyleAttr, 0);

            mBgMonth = a.getColor(R.styleable.CustomCalendar_mBgMonth, Color.TRANSPARENT);

            mBgWeek = a.getColor(R.styleable.CustomCalendar_mBgWeek, Color.TRANSPARENT);

            mBgDay = a.getColor(R.styleable.CustomCalendar_mBgDay, Color.TRANSPARENT);

            mBgPre = a.getColor(R.styleable.CustomCalendar_mBgPre, Color.TRANSPARENT);

            mMonthRowL = a.getResourceId(R.styleable.CustomCalendar_mMonthRowL, R.drawable.custom_calendar_row_left);

            mMonthRowR = a.getResourceId(R.styleable.CustomCalendar_mMonthRowR, R.drawable.custom_calendar_row_right);

            mMonthRowSpac = a.getDimension(R.styleable.CustomCalendar_mMonthRowSpac, 20);

            mTextColorMonth = a.getColor(R.styleable.CustomCalendar_mTextColorMonth, Color.BLACK);

            mTextSizeMonth = a.getDimension(R.styleable.CustomCalendar_mTextSizeMonth, 100);

            mMonthSpac = a.getDimension(R.styleable.CustomCalendar_mMonthSpac, 20);

            mTextColorWeek = a.getColor(R.styleable.CustomCalendar_mTextColorWeek, Color.BLACK);

            mSelectWeekTextColor = a.getColor(R.styleable.CustomCalendar_mSelectWeekTextColor, Color.BLACK);

            mTextSizeWeek = a.getDimension(R.styleable.CustomCalendar_mTextSizeWeek, 70);

            mTextColorDay = a.getColor(R.styleable.CustomCalendar_mTextColorDay, Color.GRAY);

            mTextSizeDay = a.getDimension(R.styleable.CustomCalendar_mTextSizeDay, 70);

            mTextColorPreFinish = a.getColor(R.styleable.CustomCalendar_mTextColorPreFinish, Color.BLUE);

            mTextColorPreUnFinish = a.getColor(R.styleable.CustomCalendar_mTextColorPreUnFinish, Color.BLUE);

            mTextColorPreNull  = a.getColor(R.styleable.CustomCalendar_mTextColorPreNull, Color.BLUE);

            mTextSizePre = a.getDimension(R.styleable.CustomCalendar_mTextSizePre, 40);

            mSelectTextColor = a.getColor(R.styleable.CustomCalendar_mSelectTextColor, Color.YELLOW);

            mCurrentBg = a.getColor(R.styleable.CustomCalendar_mCurrentBg, Color.GRAY);

            try {

                int dashPathId = a.getResourceId(R.styleable.CustomCalendar_mCurrentBgDashPath, R.array.customCalendar_currentDay_bg_DashPath);

                int[] array = getResources().getIntArray(dashPathId);

                mCurrentBgDashPath = new float[array.length];

                for(int i=0;i<array.length;i++){

                    mCurrentBgDashPath[i]=array[i];

                }

            }catch (Exception e){

                e.printStackTrace();

                mCurrentBgDashPath = new float[]{2, 3, 2, 3};

            }

            mSelectBg = a.getColor(R.styleable.CustomCalendar_mSelectBg, Color.YELLOW);

            mSelectRadius = a.getDimension(R.styleable.CustomCalendar_mSelectRadius, 20);

            mCurrentBgStrokeWidth = a.getDimension(R.styleable.CustomCalendar_mCurrentBgStrokeWidth, 5);

            mLineSpac = a.getDimension(R.styleable.CustomCalendar_mLineSpac, 20);

            mTextSpac = a.getDimension(R.styleable.CustomCalendar_mTextSpac, 20);

            a.recycle();  //注意回收

            initCompute();

        }

        /**计算相关常量,构造方法中调用*/

        private void initCompute(){

            mPaint = new Paint();

            bgPaint = new Paint();

            mPaint.setAntiAlias(true); //抗锯齿

            bgPaint.setAntiAlias(true); //抗锯齿

            map = new HashMap<>();

            //标题高度

            mPaint.setTextSize(mTextSizeMonth);

            titleHeight = FontUtil.getFontHeight(mPaint) + 2 * mMonthSpac;

            //星期高度

            mPaint.setTextSize(mTextSizeWeek);

            weekHeight = FontUtil.getFontHeight(mPaint);

            //日期高度

            mPaint.setTextSize(mTextSizeDay);

            dayHeight = FontUtil.getFontHeight(mPaint);

            //次数字体高度

            mPaint.setTextSize(mTextSizePre);

            preHeight = FontUtil.getFontHeight(mPaint);

            //每行高度 = 行间距 + 日期字体高度 + 字间距 + 次数字体高度

            oneHeight = mLineSpac + dayHeight + mTextSpac + preHeight;

            //默认当前月份

            String cDateStr = getMonthStr(new Date());

    //        cDateStr = "201508";

            setMonth(cDateStr);

        }

        /**设置月份*/

        private void setMonth(String Month){

            //设置的月份(201701月)

            month = str2Date(Month);

            Calendar calendar = Calendar.getInstance();

            calendar.setTime(new Date());

            //获取今天是多少号

            currentDay = calendar.get(Calendar.DAY_OF_MONTH);

            todayWeekIndex = calendar.get(Calendar.DAY_OF_WEEK)-1;

            Date cM = str2Date(getMonthStr(new Date()));

            //判断是否为当月

            if(cM.getTime() == month.getTime()){

                isCurrentMonth = true;

                selectDay = currentDay;//当月默认选中当前日

            }else{

                isCurrentMonth = false;

                selectDay = 0;

            }

            Log.d(TAG, "设置月份:"+month+"   今天"+currentDay+", 是否为当前月:"+isCurrentMonth);

            calendar.setTime(month);

            dayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);

            //第一行1号显示在什么位置(星期几)

            firstIndex = calendar.get(Calendar.DAY_OF_WEEK)-1;

            lineNum = 1;

            //第一行能展示的天数

            firstLineNum = 7-firstIndex;

            lastLineNum = 0;

            int shengyu = dayOfMonth - firstLineNum;

            while (shengyu>7){

                lineNum ++;

                shengyu-=7;

            }

            if(shengyu>0){

                lineNum ++;

                lastLineNum = shengyu;

            }

            Log.i(TAG, getMonthStr(month)+"一共有"+dayOfMonth+",第一天的索引是:"+firstIndex+"   "+lineNum+

                    "行,第一行"+firstLineNum+"个,最后一行"+lastLineNum+"");

        }

        @Override

        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

            //宽度 = 填充父窗体

            int widthSize = MeasureSpec.getSize(widthMeasureSpec);   //获取宽的尺寸

            columnWidth = widthSize / 7;

            //高度 = 标题高度 + 星期高度 + 日期行数*每行高度

            float height = titleHeight + weekHeight + (lineNum * oneHeight);

            Log.v(TAG, "标题高度:"+titleHeight+" 星期高度:"+weekHeight+" 每行高度:"+oneHeight+

                    " 行数:"+ lineNum + "   控件高度:"+height);

            setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),

                    (int)height);

        }

        @Override

        protected void onDraw(Canvas canvas) {

            drawMonth(canvas);

            drawWeek(canvas);

            drawDayAndPre(canvas);

        }

        /**绘制月份*/

        private int rowLStart, rowRStart, rowWidth;

        private void drawMonth(Canvas canvas){

            //背景

            bgPaint.setColor(mBgMonth);

            RectF rect = new RectF(0, 0, getWidth(), titleHeight);

            canvas.drawRect(rect, bgPaint);

            //绘制月份

            mPaint.setTextSize(mTextSizeMonth);

            mPaint.setColor(mTextColorMonth);

            float textLen = FontUtil.getFontlength(mPaint, getMonthStr(month));

            float textStart = (getWidth() - textLen)/ 2;

            canvas.drawText(getMonthStr(month), textStart,

                    mMonthSpac+FontUtil.getFontLeading(mPaint), mPaint);

            /*绘制左右箭头*/

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), mMonthRowL);

            int h = bitmap.getHeight();

            rowWidth = bitmap.getWidth();

            //float left, float top

            rowLStart = (int)(textStart-2*mMonthRowSpac-rowWidth);

            canvas.drawBitmap(bitmap, rowLStart+mMonthRowSpac , (titleHeight - h)/2, new Paint());

            bitmap = BitmapFactory.decodeResource(getResources(), mMonthRowR);

            rowRStart = (int)(textStart+textLen);

            canvas.drawBitmap(bitmap, rowRStart+mMonthRowSpac, (titleHeight - h)/2, new Paint());

        }

        /**绘制绘制星期*/

        private void drawWeek(Canvas canvas){

            //背景

            bgPaint.setColor(mBgWeek);

            RectF rect = new RectF(0, titleHeight, getWidth(), titleHeight + weekHeight);

            canvas.drawRect(rect, bgPaint);

            //绘制星期:七天

            mPaint.setTextSize(mTextSizeWeek);

            for(int i = 0; i < WEEK_STR.length; i++){

                if(todayWeekIndex == i && isCurrentMonth){

                    mPaint.setColor(mSelectWeekTextColor);

                }else{

                    mPaint.setColor(mTextColorWeek);

                }

                int len = (int)FontUtil.getFontlength(mPaint, WEEK_STR[i]);

                int x = i * columnWidth + (columnWidth - len)/2;

                canvas.drawText(WEEK_STR[i], x, titleHeight + FontUtil.getFontLeading(mPaint), mPaint);

            }

        }

        /**绘制日期和次数*/

        private void drawDayAndPre(Canvas canvas){

            //某行开始绘制的Y坐标,第一行开始的坐标为标题高度+星期部分高度

            float top = titleHeight+weekHeight;

            //

            for(int line = 0; line < lineNum; line++){

                if(line == 0){

                    //第一行

                    drawDayAndPre(canvas, top, firstLineNum, 0, firstIndex);

                }else if(line == lineNum-1){

                    //最后一行

                    top += oneHeight;

                    drawDayAndPre(canvas, top, lastLineNum, firstLineNum+(line-1)*7, 0);

                }else{

                    //满行

                    top += oneHeight;

                    drawDayAndPre(canvas, top, 7, firstLineNum+(line-1)*7, 0);

                }

            }

        }

        /**

         * 绘制某一行的日期

         * @param canvas

         * @param top 顶部坐标

         * @param count 此行需要绘制的日期数量(不一定都是7天)

         * @param overDay 已经绘制过的日期,从overDay+1开始绘制

         * @param startIndex 此行第一个日期的星期索引

         */

        private void drawDayAndPre(Canvas canvas, float top,

                                   int count, int overDay, int startIndex){

    //        Log.e(TAG, "总共"+dayOfMonth+"天  有"+lineNum+""+ "  已经画了"+overDay+",下面绘制:"+count+"");

            //背景

            float topPre = top + mLineSpac + dayHeight;

            bgPaint.setColor(mBgDay);

            RectF rect = new RectF(0, top, getWidth(), topPre);

            canvas.drawRect(rect, bgPaint);

            bgPaint.setColor(mBgPre);

            rect = new RectF(0, topPre, getWidth(), topPre + mTextSpac + dayHeight);

            canvas.drawRect(rect, bgPaint);

            mPaint.setTextSize(mTextSizeDay);

            float dayTextLeading = FontUtil.getFontLeading(mPaint);

            mPaint.setTextSize(mTextSizePre);

            float preTextLeading = FontUtil.getFontLeading(mPaint);

    //        Log.v(TAG, "当前日期:"+currentDay+"   选择日期:"+selectDay+"  是否为当前月:"+isCurrentMonth);

            for(int i = 0; i<count; i++){

                int left = (startIndex + i)*columnWidth;

                int day = (overDay+i+1);

                mPaint.setTextSize(mTextSizeDay);

                //如果是当前月,当天日期需要做处理

                if(isCurrentMonth && currentDay == day){

                    mPaint.setColor(mTextColorDay);

                    bgPaint.setColor(mCurrentBg);

                    bgPaint.setStyle(Paint.Style.STROKE);  //空心

                    PathEffect effect = new DashPathEffect(mCurrentBgDashPath, 1);

                    bgPaint.setPathEffect(effect);   //设置画笔曲线间隔

                    bgPaint.setStrokeWidth(mCurrentBgStrokeWidth);       //画笔宽度

                    //绘制空心圆背景

                    canvas.drawCircle(left+columnWidth/2, top + mLineSpac +dayHeight/2,

                            mSelectRadius-mCurrentBgStrokeWidth, bgPaint);

                }

                //绘制完后将画笔还原,避免脏笔

                bgPaint.setPathEffect(null);

                bgPaint.setStrokeWidth(0);

                bgPaint.setStyle(Paint.Style.FILL);

                //选中的日期,如果是本月,选中日期正好是当天日期,下面的背景会覆盖上面绘制的虚线背景

                if(selectDay == day){

                    //选中的日期字体白色,橙色背景

                    mPaint.setColor(mSelectTextColor);

                    bgPaint.setColor(mSelectBg);

                    //绘制橙色圆背景,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是paint对象;

                    canvas.drawCircle(left+columnWidth/2, top + mLineSpac +dayHeight/2, mSelectRadius, bgPaint);

                }else{

                    mPaint.setColor(mTextColorDay);

                }

                int len = (int)FontUtil.getFontlength(mPaint, day+"");

                int x = left + (columnWidth - len)/2;

                canvas.drawText(day+"", x, top + mLineSpac + dayTextLeading, mPaint);

                //绘制次数

                mPaint.setTextSize(mTextSizePre);

                MainJmActivity.DayFinish finish = map.get(day);

                String preStr = "0/0";

                if(isCurrentMonth){

                    if(day>currentDay){

                        mPaint.setColor(mTextColorPreNull);

                    }else if(finish!=null){

                        //区分完成未完成

                        if(finish.finish >= finish.all) {

                            mPaint.setColor(mTextColorPreFinish);

                        }else{

                            mPaint.setColor(mTextColorPreUnFinish);

                        }

                        preStr = finish.finish+"/"+finish.all;

                    }else{

                        mPaint.setColor(mTextColorPreNull);

                    }

                }else{

                    if(finish!=null){

                        //区分完成未完成

                        if(finish.finish >= finish.all) {

                            mPaint.setColor(mTextColorPreFinish);

                        }else{

                            mPaint.setColor(mTextColorPreUnFinish);

                        }

                        preStr = finish.finish+"/"+finish.all;

                    }else{

                        mPaint.setColor(mTextColorPreNull);

                    }

                }

                len = (int)FontUtil.getFontlength(mPaint, preStr);

                x = left + (columnWidth - len)/2;

                canvas.drawText(preStr, x, topPre + mTextSpac + preTextLeading, mPaint);

            }

        }

        /**获取月份标题*/

        private String getMonthStr(Date month){

            SimpleDateFormat df = new SimpleDateFormat("yyyyMM");

            return df.format(month);

        }

        private Date str2Date(String str){

            try {

                SimpleDateFormat df = new SimpleDateFormat("yyyyMM");

                return df.parse(str);

            }catch (Exception e){

                e.printStackTrace();

                return null;

            }

        }

        /****************************事件处理↓↓↓↓↓↓↓****************************/

        //焦点坐标

        private PointF focusPoint = new PointF();

        @Override

        public boolean onTouchEvent(MotionEvent event) {

            int action = event.getAction() & MotionEvent.ACTION_MASK;

            switch (action) {

                case MotionEvent.ACTION_DOWN:

                    focusPoint.set(event.getX(), event.getY());

                    touchFocusMove(focusPoint, false);

                    break;

                case MotionEvent.ACTION_MOVE:

                    focusPoint.set(event.getX(), event.getY());

                    touchFocusMove(focusPoint, false);

                    break;

                case MotionEvent.ACTION_OUTSIDE:

                case MotionEvent.ACTION_CANCEL:

                case MotionEvent.ACTION_UP:

                    focusPoint.set(event.getX(), event.getY());

                    touchFocusMove(focusPoint, true);

                    break;

            }

            return true;

        }

        /**焦点滑动*/

        public void touchFocusMove(final PointF point, boolean eventEnd) {

            Log.e(TAG, "点击坐标:("+point.x+" "+point.y+"),事件是否结束:"+eventEnd);

            /**标题和星期只有在事件结束后才响应*/

            if(point.y<=titleHeight){

                //事件在标题上

                if(eventEnd && listener!=null){

                    if(point.x>=rowLStart && point.x<(rowLStart+2*mMonthRowSpac+rowWidth)){

                        Log.w(TAG, "点击左箭头");

                        listener.onLeftRowClick();

                    }else if(point.x>rowRStart && point.x<(rowRStart + 2*mMonthRowSpac+rowWidth)){

                        Log.w(TAG, "点击右箭头");

                        listener.onRightRowClick();

                    }else if(point.x>rowLStart && point.x <rowRStart){

                        listener.onTitleClick(getMonthStr(month), month);

                    }

                }

            }else if(point.y<=(titleHeight+weekHeight)){

                //事件在星期部分

                if(eventEnd && listener!=null){

                    //根据X坐标找到具体的焦点日期

                    int xIndex = (int)point.x / columnWidth;

                    Log.e(TAG, "列宽:"+columnWidth+"  x坐标余数:"+(point.x / columnWidth));

                    if((point.x / columnWidth-xIndex)>0){

                        xIndex += 1;

                    }

                    if(listener!=null){

                        listener.onWeekClick(xIndex-1, WEEK_STR[xIndex-1]);

                    }

                }

            }else{

                /**日期部分按下和滑动时重绘,只有在事件结束后才响应*/

                touchDay(point, eventEnd);

            }

        }

        //控制事件是否响应

        private boolean responseWhenEnd = false;

        /**事件点在 日期区域 范围内*/

        private void touchDay(final PointF point, boolean eventEnd){

            //根据Y坐标找到焦点行

            boolean availability = false;  //事件是否有效

            //日期部分

            float top = titleHeight+weekHeight+oneHeight;

            int foucsLine = 1;

            while(foucsLine<=lineNum){

                if(top>=point.y){

                    availability = true;

                    break;

                }

                top += oneHeight;

                foucsLine ++;

            }

            if(availability){

                //根据X坐标找到具体的焦点日期

                int xIndex = (int)point.x / columnWidth;

                if((point.x / columnWidth-xIndex)>0){

                    xIndex += 1;

                }

    //            Log.e(TAG, "列宽:"+columnWidth+"  x坐标余数:"+(point.x / columnWidth));

                if(xIndex<=0)

                    xIndex = 1;   //避免调到上一行最后一个日期

                if(xIndex>7)

                    xIndex = 7;   //避免调到下一行第一个日期

    //            Log.e(TAG, "事件在日期部分,第"+foucsLine+"/"+lineNum+", "+xIndex+"");

                if(foucsLine == 1){

                    //第一行

                    if(xIndex<=firstIndex){

                        Log.e(TAG, "点到开始空位了");

                        setSelectedDay(selectDay, true);

                    }else{

                        setSelectedDay(xIndex-firstIndex, eventEnd);

                    }

                }else if(foucsLine == lineNum){

                    //最后一行

                    if(xIndex>lastLineNum){

                        Log.e(TAG, "点到结尾空位了");

                        setSelectedDay(selectDay, true);

                    }else{

                        setSelectedDay(firstLineNum + (foucsLine-2)*7+ xIndex, eventEnd);

                    }

                }else{

                    setSelectedDay(firstLineNum + (foucsLine-2)*7+ xIndex, eventEnd);

                }

            }else{

                //超出日期区域后,视为事件结束,响应最后一个选择日期的回调

                setSelectedDay(selectDay, true);

            }

        }

        /**设置选中的日期*/

        private void setSelectedDay(int day, boolean eventEnd){

            Log.w(TAG, "选中:"+day+"  事件是否结束"+eventEnd);

            selectDay = day;

            invalidate();

            if(listener!=null && eventEnd && responseWhenEnd && lastSelectDay!=selectDay) {

                lastSelectDay = selectDay;

                listener.onDayClick(selectDay, getMonthStr(month) + selectDay + "", map.get(selectDay));

            }

            responseWhenEnd = !eventEnd;

        }

        /****************************事件处理↑↑↑↑↑↑↑****************************/

        @Override

        public void invalidate() {

            requestLayout();

            super.invalidate();

        }

        /***********************接口API↓↓↓↓↓↓↓**************************/

        private Map<Integer, MainJmActivity.DayFinish> map;

        public void setRenwu(String month, List<MainJmActivity.DayFinish> list){

            setMonth(month);

            if(list!=null && list.size()>0){

                map.clear();

                for(MainJmActivity.DayFinish finish : list){

                    map.put(finish.day, finish);

                }

            }

            invalidate();

        }

        public void setRenwu(List<MainJmActivity.DayFinish> list){

            if(list!=null && list.size()>0){

                map.clear();

                for(MainJmActivity.DayFinish finish : list){

                    map.put(finish.day, finish);

                }

            }

            invalidate();

        }

        /**月份增减*/

        public void monthChange(int change){

            Calendar calendar = Calendar.getInstance();

            calendar.setTime(month);

            calendar.add(Calendar.MONTH, change);

            setMonth(getMonthStr(calendar.getTime()));

            map.clear();

            invalidate();

        }

        private onClickListener listener;

        public void setOnClickListener(onClickListener listener){

            this.listener = listener;

        }

        interface onClickListener{

            public abstract void onLeftRowClick();

            public abstract void onRightRowClick();

            public abstract void onTitleClick(String monthStr, Date month);

            public abstract void onWeekClick(int weekIndex, String weekStr);

            public abstract void onDayClick(int day, String dayStr, MainJmActivity.DayFinish finish);

        }

        /***********************接口API↑↑↑↑↑↑↑**************************/

    }

    CustomCalendar

    package com.example.zbytexttwo;

    import android.graphics.Paint;

    /**

     * author : openXu

     * create at : 2016/07/8 12:40

     * blog : http://blog.csdn.net/xmxkf

     * gitHub : https://github.com/openXu

     * project : StockChart

     * class name : FontUtil

     * version : 1.0

     * class describe:文字相关处理帮助类

     */

    public class FontUtil {

        /**

         * @param paint

         * @param str

         * @return 返回指定笔和指定字符串的长度

         * @add yujiangtao 16/8/5

         */

        public static float getFontlength(Paint paint, String str) {

            return paint.measureText(str);

        }

        /**

         * @return 返回指定笔的文字高度

         * @add yujiangtao 16/8/5

         */

        public static float getFontHeight(Paint paint)  {

            Paint.FontMetrics fm = paint.getFontMetrics();

            return fm.descent - fm.ascent;

        }

        /**

         * @return 返回指定笔离文字顶部的基准距离

         * @add yujiangtao 16/8/5

         */

        public static float getFontLeading(Paint paint)  {

            Paint.FontMetrics fm = paint.getFontMetrics();

            return fm.leading- fm.ascent;

        }

    }

    FontUtil

    <?xml version="1.0" encoding="utf-8"?>

    <ScrollView

        xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:openxu="http://schemas.android.com/apk/res-auto"

        android:id="@+id/tab01"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:fillViewport="true">

        <LinearLayout

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:orientation="vertical">

            <com.example.zbytexttwo.CustomCalendar

                android:id="@+id/cal"

                android:layout_width="match_parent"

                android:layout_height="wrap_content"

                openxu:mMonthRowL="@drawable/custom_calendar_row_left"

                openxu:mMonthRowR="@drawable/custom_calendar_row_right"

                openxu:mMonthRowSpac="20dip"

                openxu:mTextSizeMonth="20sp"

                openxu:mTextSizeWeek="17sp"

                openxu:mTextSizeDay="17sp"

                openxu:mTextSizePre="10sp"

                openxu:mTextColorMonth="#4b4b4b"

                openxu:mTextColorWeek="#9e9e9d"

                openxu:mSelectWeekTextColor="#f67633"

                openxu:mTextColorDay="#686768"

                openxu:mTextColorPreFinish="#fc7451"

                openxu:mTextColorPreUnFinish="#60ba8d"

                openxu:mTextColorPreNull="#cecdcd"

                openxu:mSelectTextColor="#ffffff"

                openxu:mMonthSpac="10dip"

                openxu:mLineSpac="12dip"

                openxu:mTextSpac="8dip"

                openxu:mCurrentBg="#6E6E6E"

                openxu:mCurrentBgStrokeWidth="1.5dip"

                openxu:mCurrentBgDashPath="@array/customCalendar_currentDay_bg_DashPath"

                openxu:mSelectBg="#fe7f5c"

                openxu:mSelectRadius="15dip" />

            <!-- <CalendarView

                 android:layout_width="match_parent"

                 android:layout_height="wrap_content"/>-->

        </LinearLayout>

    </ScrollView>

    activity_main_jm

    <?xml version="1.0" encoding="utf-8"?>

    <resources>

        <array name="customCalendar_currentDay_bg_DashPath">

            <item>8</item>

            <item>8</item>

            <item>8</item>

            <item>4</item>

            <item>4</item>

            <item>4</item>

        </array>

    </resources>

    Array

    <?xml version="1.0" encoding="utf-8"?>

    <resources>

        <declare-styleable name="CustomCalendar">

            <!--这四个颜色分别是月份、星期、日期、任务的背景色,只是方便调试测量时使用,正式试用时可配置透明色-->

            <attr name="mBgMonth" format="color" />

            <attr name="mBgWeek" format="color" />

            <attr name="mBgDay" format="color" />

            <attr name="mBgPre" format="color" />

            <attr name="mTextColorMonth" format="color" />           <!--标题字体颜色-->

            <attr name="mTextColorWeek" format="color" />            <!--星期字体颜色-->

            <attr name="mSelectWeekTextColor" format="color" />      <!--当前星期字体颜色-->

            <attr name="mTextColorDay" format="color" />             <!--日期字体颜色-->

            <attr name="mTextColorPreFinish" format="color" />       <!--任务次数字体颜色-->

            <attr name="mTextColorPreUnFinish" format="color" />

            <attr name="mTextColorPreNull" format="color" />

            <attr name="mTextSizeMonth" format="dimension" />        <!--标题字体大小-->

            <attr name="mTextSizeWeek" format="dimension" />         <!--星期字体大小-->

            <attr name="mTextSizeDay" format="dimension" />          <!--日期字体大小-->

            <attr name="mTextSizePre" format="dimension" />          <!--任务次数字体大小-->

            <attr name="mMonthRowL" format="reference" />            <!--月份箭头-->

            <attr name="mMonthRowR" format="reference" />            <!--月份箭头-->

            <attr name="mMonthRowSpac" format="dimension" />

            <attr name="mSelectTextColor" format="color" />          <!--选中日期字体颜色-->

            <attr name="mSelectBg" format="color" />                 <!--选中日期背景-->

            <attr name="mSelectRadius" format="dimension" />         <!--选中日期背景半径-->

            <attr name="mCurrentBg" format="color" />                <!--当天日期背景-->

            <attr name="mCurrentBgStrokeWidth" format="dimension" /> <!--当天日期背景虚线宽度-->

            <attr name="mCurrentBgDashPath" format="reference" />    <!--当天日期背景虚线数组-->

            <attr name="mMonthSpac" format="dimension" />            <!--标题月份上下间隔-->

            <attr name="mLineSpac" format="dimension" />             <!--日期行间距-->

            <attr name="mTextSpac" format="dimension" />             <!--日期和任务次数字体上下间距-->

        </declare-styleable>

    </resources>

    attrs

  • 相关阅读:
    dotnet 新项目格式与对应框架预定义的宏
    dotnet 线程静态字段
    dotnet 线程静态字段
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取系统信息
    dotnet 通过 WMI 获取系统信息
    PHP show_source() 函数
  • 原文地址:https://www.cnblogs.com/zaixiachengxuyuan/p/13111150.html
Copyright © 2020-2023  润新知