TimePicker时间选择器

TimePicker时间选择器
public class TimePicker extends View {
    private Context context;
    private Paint paintBackground,paintText,paintAlpha;

    private int width;//设置高
    private int height;//设置高

    private List<Integer> yearList,monthList,dateList,hourList;
    private List<String>minuteList;

    private int year=0,month=0,day=0,hour=0,minute=0,daysThisMonth=0;
    private String strMinute="";

    public TimePicker(Context context) {
        super(context);
        this.context=context;
        init();
    }

    public TimePicker(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context=context;
        init();
    }

    public TimePicker(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context=context;
        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawBackground(canvas);
        drawYear(canvas);
        drawMonth(canvas);
        drawDate(canvas);
        drawHour(canvas);
        drawMinute(canvas);
        drawAlpha(canvas);
    }

    /**
     * 背景
     */
    private void drawBackground(Canvas canvas) {
        paintBackground.setColor(Color.GRAY);
        canvas.drawRect(0,0,width,height,paintBackground);
        paintBackground.setColor(Color.DKGRAY);
        for (int i = 0; i < 5; i++) {
            canvas.drawRect(height/20+i*width/5,height/20,width/5-height/20+i*width/5,height*19/20,paintBackground);
            canvas.drawLine(height/20+i*width/5,height/2-height/8,width/5-height/20+i*width/5,height/2-height/8,paintText);
            canvas.drawLine(height/20+i*width/5,height/2+height/8,width/5-height/20+i*width/5,height/2+height/8,paintText);
        }
        canvas.clipRect(height/20,height/20,width-height/20,height*19/20);
    }

    /**
     * 渐变边框
     */
    private void drawAlpha(Canvas canvas) {
        Shader mShader = new LinearGradient(height/20+width/10,height/20,height/20+width/10,height*19/20,new int[]{Color.BLACK,0x00000000,Color.BLACK},null, Shader.TileMode.CLAMP);
        paintAlpha.setShader(mShader);
        for (int i = 0; i < 5; i++) {
            canvas.drawRect(height/20+i*width/5,height/20,width/5-height/20+i*width/5,height*19/20,paintAlpha);
        }
    }

    private float yearX,yearY,yearY2;
    /**
     * 年
     */
    private void drawYear(Canvas canvas) {
        Rect rect = new Rect();
        String year=yearList.get(0)+"";
        paintText.getTextBounds(year, 0, year.length(), rect);
        for (int i = 0; i < yearList.size(); i++) {
            canvas.drawText(yearList.get(i)+"",yearX,yearY2+rect.height()/2+i*height/4,paintText);
        }
    }

    private float monthX,monthY,monthY2;
    /**
     * 月
     */
    private void drawMonth(Canvas canvas) {
        Rect rect = new Rect();
        String month=monthList.get(0)+"";
        paintText.getTextBounds(month, 0, month.length(), rect);
        for (int i = 0; i < monthList.size(); i++) {
            canvas.drawText(monthList.get(i)+"",monthX,monthY2+rect.height()/2+i*height/4,paintText);
        }
    }

    private float dateX,dateY,dateY2;
    /**
     * 日
     */
    private void drawDate(Canvas canvas) {
        Rect rect = new Rect();
        String date=dateList.get(0)+"";
        paintText.getTextBounds(date, 0, date.length(), rect);
        for (int i = 0; i < dateList.size(); i++) {
            canvas.drawText(dateList.get(i)+"",dateX,dateY2+rect.height()/2+i*height/4,paintText);
        }
    }

    private float hourX,hourY,hourY2;
    /**
     * 时
     */
    private void drawHour(Canvas canvas) {
        Rect rect = new Rect();
        String hour=hourList.get(0)+"";
        paintText.getTextBounds(hour, 0, hour.length(), rect);
        for (int i = 0; i < hourList.size(); i++) {
            canvas.drawText(hourList.get(i)+"",hourX,hourY2+rect.height()/2+i*height/4,paintText);
        }
    }

    private float minuteX,minuteY,minuteY2;
    /**
     * 分
     */
    private void drawMinute(Canvas canvas) {
        Rect rect = new Rect();
        String minute=minuteList.get(0)+"";
        paintText.getTextBounds(minute, 0, minute.length(), rect);
        for (int i = 0; i < minuteList.size(); i++) {
            canvas.drawText(minuteList.get(i)+"",minuteX,minuteY2+rect.height()/2+i*height/4,paintText);
        }
    }



    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int measureWidth = getDefaultSize(getMeasuredWidth(), widthMeasureSpec);// 获得控件的宽度
        setMeasuredDimension(measureWidth , measureWidth/3);//设置宽和高
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        initTime();

        width=w;
        height=h;

        paintText.setTextSize(height/8);

        yearX=width/10;
        yearY2=height/2;
        yearLastY=yearY2;

        monthX=width/10+width/5;
        monthY2=height/2-(month+2)*height/4;
        monthLastY=monthY2;

        dateX=width/10+width*2/5;
        dateY2=height/2-(day+4)*height/4;
        dateLastY=dateY2;

        hourX=width/10+width*3/5;
        hourY2=height/2-(hour+3)*height/4;
        hourLastY=hourY2;

        minuteX=width/10+width*4/5;
        minuteY2=height/2-(minute+3)*height/4;
        minuteLastY=minuteY2;
    }

    private void init() {
        initPaint();
    }

    /**
     * 初始化时间
     */
    private void initTime() {
        Date date=new Date();
        //年
        yearList=new ArrayList<>();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        for (int i = 0; i < 30; i++) {
            yearList.add(cal.get(Calendar.YEAR)+i);
        }

        year=cal.get(Calendar.YEAR);
        month=cal.get(Calendar.MONTH)+1;
        day=cal.get(Calendar.DATE);
        hour=cal.get(Calendar.HOUR_OF_DAY);
        minute=cal.get(Calendar.MINUTE);
        if(minute<10){
            strMinute="0"+minute;
        }else {
            strMinute=""+minute;
        }

        //月份
        monthList=new ArrayList<>();
        for (int i = 0; i < 18; i++) {
            monthList.add((9+i)%12+1);
        }

        //日期
        dateList=new ArrayList<>();
        initDate();

        //小时
        hourList=new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            hourList.add((21+i)%24);
        }

        //分钟
        minuteList=new ArrayList<>();
        for (int i = 0; i < 66; i++) {
            int minute=(57+i)%60;
            if(minute<10){
                String strMinute="0"+minute;
                minuteList.add(strMinute);
            }else {
                minuteList.add(minute+"");
            }
        }
    }

    private void initDate() {
        Date date=new Date(year,month,0);
        daysThisMonth=date.getDate();
        dateList=new ArrayList<>();
        for (int i = 0; i < daysThisMonth+10; i++) {
            dateList.add((daysThisMonth+i-5)%daysThisMonth+1);
        }
    }


    /**
     * 初始化画笔
     */
    private void initPaint() {
        paintBackground=new Paint();
        paintBackground.setAntiAlias(true);
        paintBackground.setColor(Color.GRAY);
        paintBackground.setStyle(Paint.Style.FILL);
        paintBackground.setStrokeWidth(DensityUtil.dip2px(context,2));

        paintText=new Paint();
        paintText.setAntiAlias(true);
        paintText.setColor(Color.WHITE);
        paintText.setStyle(Paint.Style.FILL);
        paintText.setTextAlign(Paint.Align.CENTER);

        paintAlpha=new Paint();
        paintAlpha.setAntiAlias(true);
        paintAlpha.setStyle(Paint.Style.FILL);
    }

    private float downX,downY;
    private int moveIndex;
    private float yearLastY,monthLastY,dateLastY,hourLastY,minuteLastY;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                moveIndex=-1;
                //获取屏幕上点击的坐标
                downX = event.getX();
                downY = event.getY();

                for (int i = 0; i < 5; i++) {
                    if(Util.isInside(downX,downY,height/20+i*width/5,height/20,width/5-height/20+i*width/5,height*19/20)){
                        moveIndex=i;
                        return true;
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if(moveIndex==0){
                    yearY=yearLastY+event.getY()-downY;
                    if(yearY>height/2){
                        yearY=height/2;
                    }else if(yearY<height/2-(yearList.size()-1)*height/4){
                        yearY=height/2-(yearList.size()-1)*height/4;
                    }
                    yearY2=yearY;
                    invalidate();
                }else if(moveIndex==1){
                    monthY=monthLastY+event.getY()-downY;
                    if(monthY>height/2){
                        monthY=height/2;
                    }else if(monthY<height/2-(monthList.size()-1)*height/4){
                        monthY=height/2-(monthList.size()-1)*height/4;
                    }

                    if(monthY>0){
                        monthLastY=monthLastY-12*height/4;
                        monthY=monthLastY+event.getY()-downY;
                    }else if(monthY<-13*height/4){
                        monthLastY=monthLastY+12*height/4;
                        monthY=monthLastY+event.getY()-downY;
                    }

                    monthY2=monthY;
                    invalidate();
                }else if(moveIndex==2){
                    dateY=dateLastY+event.getY()-downY;
                    if(dateY>height/2){
                        dateY=height/2;
                    }else if(dateY<height/2-(dateList.size()-1)*height/4){
                        dateY=height/2-(dateList.size()-1)*height/4;
                    }

                    if(dateY>-height/2){
                        dateLastY=dateLastY-daysThisMonth*height/4;
                        dateY=dateLastY+event.getY()-downY;
                    }else if(dateY<-(daysThisMonth+1)*height/4){
                        dateLastY=dateLastY+daysThisMonth*height/4;
                        dateY=dateLastY+event.getY()-downY;
                    }

                    dateY2=dateY;
                    invalidate();
                }else if(moveIndex==3){
                    hourY=hourLastY+event.getY()-downY;
                    if(hourY>height/2){
                        hourY=height/2;
                    }else if(hourY<height/2-(hourList.size()-1)*height/4){
                        hourY=height/2-(hourList.size()-1)*height/4;
                    }

                    if(hourY>0){
                        hourLastY=hourLastY-24*height/4;
                        hourY=hourLastY+event.getY()-downY;
                    }else if(hourY<-25*height/4){
                        hourLastY=hourLastY+24*height/4;
                        hourY=hourLastY+event.getY()-downY;
                    }

                    hourY2=hourY;
                    invalidate();
                }else if(moveIndex==4){
                    minuteY=minuteLastY+event.getY()-downY;
                    if(minuteY>height/2){
                        minuteY=height/2;
                    }else if(minuteY<height/2-(minuteList.size()-1)*height/4){
                        minuteY=height/2-(minuteList.size()-1)*height/4;
                    }

                    if(minuteY>0){
                        minuteLastY=minuteLastY-60*height/4;
                        minuteY=minuteLastY+event.getY()-downY;
                    }else if(minuteY<-61*height/4){
                        minuteLastY=minuteLastY+60*height/4;
                        minuteY=minuteLastY+event.getY()-downY;
                    }

                    minuteY2=minuteY;
                    invalidate();
                }
                break;
            case MotionEvent.ACTION_UP:
                if(moveIndex==0){
                    yearLastY=yearY;
                    fixYearAnim((height/2-yearY)%(height/4));
                    int position=(int)((height/2-yearLastY+height/8)/(height/4));
                    year=yearList.get(position);
                    initDate();
                }else if(moveIndex==1){
                    monthLastY=monthY;
                    fixMonthAnim((height/2-monthY)%(height/4));
                    int position=(int)((height/2-monthLastY+height/8)/(height/4));
                    month=monthList.get(position);
                    initDate();
                }else if(moveIndex==2){
                    dateLastY=dateY;
                    fixDateAnim((height/2-dateY)%(height/4));
                    int position=(int)((height/2-dateLastY+height/8)/(height/4));
                    day=dateList.get(position);
                }else if(moveIndex==3){
                    hourLastY=hourY;
                    fixHourAnim((height/2-hourY)%(height/4));
                    int position=(int)((height/2-hourLastY+height/8)/(height/4));
                    hour=hourList.get(position);
                }else if(moveIndex==4){
                    minuteLastY=minuteY;
                    fixMinuteAnim((height/2-minuteY)%(height/4));
                    int position=(int)((height/2-minuteLastY+height/8)/(height/4));
                    strMinute=minuteList.get(position);
                }
                return true;
        }
        return super.onTouchEvent(event);
    }

    private float valueYear=0;
    private void fixYearAnim(final float slipY) {
        ValueAnimator valueAnimatorYear;
        if(slipY<=height/8){
            valueAnimatorYear= ValueAnimator.ofFloat(0f,slipY);
        }else {
            valueAnimatorYear= ValueAnimator.ofFloat(0f,slipY-height/4);
        }
        valueAnimatorYear.setDuration(300);
        valueAnimatorYear.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                valueYear= (float) animation.getAnimatedValue();
                yearY2=yearY+valueYear;
                yearLastY=yearY+valueYear;
                invalidate();
            }
        });
        valueAnimatorYear.start();
    }

    private float valueMonth=0;
    private void fixMonthAnim(final float slipY) {
        ValueAnimator valueAnimatorMonth;
        if(slipY<=height/8){
            valueAnimatorMonth= ValueAnimator.ofFloat(0f,slipY);
        }else {
            valueAnimatorMonth= ValueAnimator.ofFloat(0f,slipY-height/4);
        }
        valueAnimatorMonth.setDuration(300);
        valueAnimatorMonth.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                valueMonth= (float) animation.getAnimatedValue();
                monthY2=monthY+valueMonth;
                monthLastY=monthY+valueMonth;
                invalidate();
            }
        });
        valueAnimatorMonth.start();
    }

    private float valueDate=0;
    private void fixDateAnim(final float slipY) {
        ValueAnimator valueAnimatorDate;
        if(slipY<=height/8){
            valueAnimatorDate= ValueAnimator.ofFloat(0f,slipY);
        }else {
            valueAnimatorDate= ValueAnimator.ofFloat(0f,slipY-height/4);
        }
        valueAnimatorDate.setDuration(300);
        valueAnimatorDate.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                valueDate= (float) animation.getAnimatedValue();
                dateY2=dateY+valueDate;
                dateLastY=dateY+valueDate;
                invalidate();
            }
        });
        valueAnimatorDate.start();
    }

    private float valueHour=0;
    private void fixHourAnim(final float slipY) {
        ValueAnimator valueAnimatorHour;
        if(slipY<=height/8){
            valueAnimatorHour= ValueAnimator.ofFloat(0f,slipY);
        }else {
            valueAnimatorHour= ValueAnimator.ofFloat(0f,slipY-height/4);
        }
        valueAnimatorHour.setDuration(300);
        valueAnimatorHour.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                valueHour= (float) animation.getAnimatedValue();
                hourY2=hourY+valueHour;
                hourLastY=hourY+valueHour;
                invalidate();
            }
        });
        valueAnimatorHour.start();
    }

    private float valueMinute=0;
    private void fixMinuteAnim(final float slipY) {
        ValueAnimator valueAnimatorMinute;
        if(slipY<=height/8){
            valueAnimatorMinute = ValueAnimator.ofFloat(0f,slipY);
        }else {
            valueAnimatorMinute = ValueAnimator.ofFloat(0f,slipY-height/4);
        }
        valueAnimatorMinute.setDuration(300);
        valueAnimatorMinute.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                valueMinute= (float) animation.getAnimatedValue();
                minuteY2=minuteY+valueMinute;
                minuteLastY=minuteY+valueMinute;
                invalidate();
            }
        });
        valueAnimatorMinute.start();
    }

    public String getDateStr(){
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String calender=format.format(new Date(getDate()));
        return calender;
    }

    public long getDate(){
        int position=(int)((height/2-dateLastY+height/8)/(height/4));
        day=dateList.get(position);
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm");
        try {
            Date date=format.parse(year+"-"+month+"-"+day+" "+hour+":"+strMinute);
            return date.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
            return new Date().getTime();
        }
    }
}

GitHub地址 https://github.com/ZuoJinDong/TimePicker

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容