日历控件

来源:互联网 发布:超级指南针软件 编辑:程序博客网 时间:2024/05/17 09:12

用了两种方式实现日历控件

先来看看效果图
效果图
第一种就是用gridview简单点

class CalendarAdapter extends BaseAdapter {        AbsListView.LayoutParams params;        Context context;        Calendar today;        Calendar calendar;        List<String> list;        int select = -1;        public CalendarAdapter(Context context, int year, int month) {            this.context = context;            int width = context.getResources().getDisplayMetrics().widthPixels;            params = new AbsListView.LayoutParams(-1, width / 7);//让每个块的高度等于屏幕宽的1/7,宽度就自动平分了            today = Calendar.getInstance();//今天日期            calendar = Calendar.getInstance();            calendar.set(year, month - 1, 1);//这月的一号            int sc = calendar.get(Calendar.DAY_OF_WEEK);//一号是周几            list = new ArrayList<String>();            for (int i = 0; i < sc - 1; i++) {                list.add("");            }//然后把一号前的数据都设为空串            int count = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);            for (int i = 0; i < count; i++) {                list.add(i + 1 + "");            }        }        private long getTime(int position) {            return getCalendar(position).getTimeInMillis();        }//获取点击的日期        private Calendar getCalendar(int position) {            int day = Integer.valueOf(getItem(position));            calendar.set(Calendar.DAY_OF_MONTH, day);            return calendar;        }//判断是今天前,今天还是今天以后        private int isToday(int position) {            if (getTime(position) > today.getTimeInMillis()) {                return 1;            } else if (getTime(position) < today.getTimeInMillis()) {                return -1;            } else {                return 0;            }        }        private void select(int position) {            this.select = position;            notifyDataSetChanged();        }        public int getCount() {            if (list == null) {                return 0;            }            return list.size();        }        public String getItem(int position) {            return list.get(position);        }        public long getItemId(int position) {            return position;        }//是不是周末        private boolean isWeekday(int position) {            if (position % 7 == 0 || position % 7 == 6) {                return true;            }            return false;        }        public View getView(int position, View convertView, ViewGroup parent) {            TextView textView = new TextView(context);            textView.setGravity(Gravity.CENTER);            textView.setText(list.get(position));            textView.setTextSize(18);            textView.setLayoutParams(params);            if (list.get(position).equals("")) {                return textView;            }            if (isToday(position) < 0) {                textView.setTextColor(0xff999999);            } else {                if (isToday(position) == 0) {                    textView.setTextColor(0xff333333);                    textView.setText("今天");                } else {                    textView.setTextColor(0xff666666);                }                if (isWeekday(position)) {                    textView.setTextColor(0xffffa417);                }                if (select == position) {                    textView.setTextColor(0xffffffff);                    textView.setBackgroundResource(R.drawable.circle_blue_bg);                }            }            return textView;        }    }

然后就写item点击事件选择日期等。
不过感觉这样写逼格不够高,就直接继承view画一个月历

    private int year;    private int month;    private Calendar calendar;    private Calendar today;    private List<Position> list;    private Paint paint;    private int width;    private float perWidth;//每块的宽高    private int textSize = 30;    private int textColor = 0xff000000;    private int textColorSelect = 0xffffffff;    private int selectRectColor = 0xff04ade5;    private int weekendTextColor = 0xffffa417;    private float touchSlop;//手指移动距离小于这个判定它触发点击事件    private float startX = 0;    private float startY = 0;    private double distance = 0;//手指移动距离    private Position selectPosition; //选中的位置    private OnDayClickListener onDayClickListener;//日点击事件    public RItemCalendarView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    public RItemCalendarView(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public RItemCalendarView(Context context) {        super(context);        init();    }    private void init() {        paint = new Paint();        paint.setAntiAlias(true);        paint.setTextSize(textSize);        calendar = Calendar.getInstance();        today = Calendar.getInstance();        touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();    }    public void setData(int year, int month) {        LogUtil.i(year + "-" + month);        this.year = year;        this.month = month;        calendar.set(Calendar.YEAR, year);        calendar.set(Calendar.MONTH, month - 1);        int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);//本月一共多少天        if (list == null) {            list = new ArrayList<>();        } else {            list.clear();        }        for (int i = 1; i <= maxDay; i++) {            calendar.set(Calendar.DAY_OF_MONTH, i);            int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);//当天是周几            int weekOfMonth = calendar.get(Calendar.WEEK_OF_MONTH);//是第几周            list.add(new Position(dayOfWeek - 1, weekOfMonth + 1, i, dayOfWeek, calendar.getTimeInMillis()));//position记录每天是第几行第几列,是几号,还有具体时间,第0行放了日期,第一行放了周,所以weekOfMonth+1        }    }    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int height;        if (widthMode == MeasureSpec.EXACTLY) {            width = widthSize;        } else {            width = textSize * 20;//wrap时计算一个大致的宽度        }        if (heightMode == MeasureSpec.EXACTLY) {            height = heightSize;        } else {            int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);            calendar.set(Calendar.DAY_OF_MONTH, maxDay);//计算最后一天是本月的第几周,就知道一共该有多少行,来计算高度            int weekOfMonth = calendar.get(Calendar.WEEK_OF_MONTH);            height = width / 7 * (weekOfMonth + 2);//多加两行显示日期和周        }        perWidth = width * 1.0f / 7;        setMeasuredDimension(width, height);    }    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        drawDate(canvas);        drawWeek(canvas);        drawSelect(canvas);        drawDay(canvas);        selectPosition = null;    }//第一行画xxxx年xx月    private void drawDate(Canvas canvas) {        paint.setColor(textColor);        String time = TimeUtil.getFormatTime(calendar.getTime(), "yyyy-MM");        float x = width / 2 - paint.measureText(time) / 2;        float y = perWidth * 0.5f - (paint.ascent() + paint.descent()) / 2;        canvas.drawText(time, x, y, paint);    }    private void drawWeek(Canvas canvas) {        String[] weeks = new String[]{"日", "一", "二", "三", "四", "五", "六"};        paint.setColor(textColor);        float x, y;        for (int i = 0; i < weeks.length; i++) {            x = perWidth * (i + 0.5f) - paint.measureText(weeks[i]) / 2;            y = perWidth * 1.5f - (paint.ascent() + paint.descent()) / 2;            canvas.drawText(weeks[i], x, y, paint);        }    }//画天    private void drawDay(Canvas canvas) {        float x, y;        String string;        for (Position position : list) {            paint.setColor(textColor);            if (selectPosition != null && position.time == selectPosition.time) {                paint.setColor(textColorSelect);//选中那天换个颜色            }            if (position.week == 1 || position.week == 7) {                paint.setColor(weekendTextColor);//周末变色            }            string = String.valueOf(position.time);            if (position.time == today.getTimeInMillis()) {                string = "今天";            }            x = perWidth * (position.x + 0.5f) - paint.measureText(string) / 2;            y = perWidth * (position.y + 0.5f) - (paint.ascent() + paint.descent()) / 2;            canvas.drawText(string, x, y, paint);        }    }//选中的块画了个背景圆    private void drawSelect(Canvas canvas) {        if (selectPosition == null) {            return;        }        int x = selectPosition.x;        int y = selectPosition.y;        RectF rect = new RectF((x + 0.3f) * perWidth, (y + 0.3f) * perWidth, (x + 0.7f) * perWidth, (y + 0.7f) * perWidth);        paint.setColor(selectRectColor);        canvas.drawRoundRect(rect, perWidth / 2, perWidth / 2, paint);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                startX = event.getX();                startY = event.getY();//手势起始位置                int x = (int) (startX / perWidth);                int y = (int) (startY / perWidth);                selectPosition = getValue(x, y);                break;            case MotionEvent.ACTION_MOVE:                break;            case MotionEvent.ACTION_UP:                if (selectPosition != null) {                    distance = Math.sqrt((event.getX() - startX) * (event.getX() - startX) + (event.getY() - startY) * (event.getY() - startY));//手指移动距离                    if (distance < touchSlop) {                        LogUtil.i(year + "-" + month + "-" + selectPosition.day);                        if (onDayClickListener != null) {                            onDayClickListener.onClick(year, month, selectPosition.day);//回调监听                        }                        invalidate();                    }                    distance = 0;                }                break;        }        return true;    }//触摸在了哪块    private Position getValue(int x, int y) {        for (Position position :                list) {            if (position.x == x && position.y == y) {                return position;            }        }        return null;    }    public void setOnDayClickListener(OnDayClickListener onDayClickListener) {        this.onDayClickListener = onDayClickListener;    }    public interface OnDayClickListener {        void onClick(int year, int month, int day);    }    private class Position {        int x;        int y;        int day;        int week;        long time;        public Position(int x, int y, int day, int week, long tiem) {            this.x = x;            this.y = y;            this.day = day;            this.week = week;            this.time = time;        }    }

画完一个月后放在viewpager里就可以了

public OnDayClickListener onDayClickListener;private int currentYear;private int currentMonth;    //日历的范围private int minDateYear = 1900;private int minDateMonth = 1;private int maxDateYear = 2100;private int maxDateMonth = 12;public RCalendarView(Context context) {    super(context);    init();}public RCalendarView(Context context, AttributeSet attrs) {    super(context, attrs);    init();}private void init() {    Calendar now = Calendar.getInstance();    currentYear = now.get(Calendar.YEAR);    currentMonth = now.get(Calendar.MONTH) + 1;    setAdapter(new CalendarAdapter());    setCurrent(currentYear,currentMonth);//默认设置为当前月}//计算xxxx年 xx 月是在第几个位置并设置public void setCurrent(int year,int month){    int p = year * 12 + month - minDateYear * 12 - minDateMonth;    setCurrentItem(p);}//设置年月范围public void setRange(Calendar minDate, Calendar maxDate) {    if (maxDate.getTimeInMillis() < minDate.getTimeInMillis()) {        return;    }    this.minDateYear = minDate.get(Calendar.YEAR);    this.minDateMonth = minDate.get(Calendar.MONTH) + 1;    this.maxDateYear = maxDate.get(Calendar.YEAR);    this.maxDateMonth = maxDate.get(Calendar.MONTH) + 1;}public void setOnDayClickListener(OnDayClickListener onDayClickListener) {    this.onDayClickListener = onDayClickListener;}//某天的点击事件public interface OnDayClickListener {    void onClick(int year, int month, int day);}class CalendarAdapter extends PagerAdapter {    private RItemCalendarView.OnDayClickListener onItemClickListener = new RItemCalendarView.OnDayClickListener() {        @Override        public void onClick(int year, int month, int day) {            if (onDayClickListener != null) {                onDayClickListener.onClick(year, month, day);            }        }    };    @Override    public int getCount() {        return maxDateYear * 12 + maxDateMonth - minDateYear * 12 - minDateMonth + 1;    }    @Override    public boolean isViewFromObject(View view, Object object) {        return view == object;    }    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        container.removeView((View) object);    }    @Override    public Object instantiateItem(ViewGroup container, int position) {        RItemCalendarView view = new RItemCalendarView(getContext());        view.setData(getYear(position), getMonth(position));        view.setOnDayClickListener(onItemClickListener);        container.addView(view);        return view;    }    //第position个位置是哪年    private int getYear(int position) {        int t = minDateYear * 12 + minDateMonth + position;        if (t % 12 == 0) {            return t / 12 - 1;        }        return t / 12;    }    //第position个位置是几月    private int getMonth(int position) {        int t = minDateMonth + position;        if (t % 12 == 0) {            return 12;        }        return t % 12;    }}
0 0
原创粉丝点击