日历控件
2016-03-28 19:56
387 查看
用了两种方式实现日历控件
先来看看效果图
![](http://img.blog.csdn.net/20160328200106579)
第一种就是用gridview简单点
然后就写item点击事件选择日期等。
不过感觉这样写逼格不够高,就直接继承view画一个月历
画完一个月后放在viewpager里就可以了
先来看看效果图
第一种就是用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; } }
相关文章推荐
- Android Studio关于百度地图so库的配置问题
- oracle中sql语句的优化
- Spring3.2.6中事件驱动模型实现原理深入源码分析
- Educational Codeforces Round 10 D. Nested Segments 离线树状数组 离散化
- tomcat server.xml配置
- tomcat server.xml配置
- Navicat for MySQL每次打开数据库时,总是弹出“取得ER图表信息”框的解决方法
- 一些好用的快捷键
- java 保留小数点后两位
- Windows下yaf的扩展
- 获取url参数的方法
- 魅族手机listview适配问题
- hdu4031 Atack(树状数组区间更新单点求值)
- 检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问
- 三角形5
- iterm2
- html的表单form
- HDU 1064 Financial Management
- Android中Uri的使用
- bzoj4402: Claris的剑