【笔记】ViewPager+自定义控件实现的日历控件CalenderView
来源:互联网 发布:数据分析师证 编辑:程序博客网 时间:2024/04/30 13:18
接入OEM模块,产品想要人家App上的日历控件,只能乖乖自己写一个。。。
需求
实现一个能左右滑动的,带选中日期效果的日历控件。
看到左右滑动,第一反应就是ViewPager,现成的就是方便。接下来要实现的就是每月的日历了,并且可以点击选中某一天。
无限滑动ViewPager
先把简单的实现了,理论上来说,日历应该可以一直往前翻,或者一直向后翻,就是一个可以无限滚动的ViewPager。
1、设置ViewPager的总量为Integer.MAX_VALUE;
2、设置ViewPager最初页数为中间位置Integer.MAX_VALUE/2;
3、为了不浪费太多内存,实际只生成3页,当前页、前一页和后一页;
简单粗暴的代码块
public class CalenderViewAdapter extends PagerAdapter { private Context context; private List<CalenderBean> list; private List<CalenderItemView> viewList; public CalenderViewAdapter(Context context, List<CalenderBean> list) { this.context = context; this.list = list; initCalenderView(); } private void initCalenderView() { //只创建当前页、前一页和后一页 if (viewList == null) { viewList = new ArrayList<>(); viewList.add(new CalenderItemView(context)); viewList.add(new CalenderItemView(context)); viewList.add(new CalenderItemView(context)); } for (int i = 0; i < list.size(); i++) { CalenderBean calenderBean = viewList.get(i).getCalenderBean(); viewList.get(i).setDate(calenderBean.getYear(), calenderBean.getMonth()); } } @Override public int getCount() { return (list == null || list.size() == 0) ? 0 : Integer.MAX_VALUE; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, int position) { position = position % 3; CalenderItemView calenderItemView = viewList.get(position); calenderItemView.setDate(list.get(position).getYear(), list.get(position).getMonth()); try { if (calenderItemView.getParent() != null) { container.removeView(calenderItemView); } container.addView(calenderItemView); } catch (Exception e) { e.printStackTrace(); } return calenderItemView; } @Override public void destroyItem(ViewGroup container, int position, Object object) {// super.destroyItem(container, position, object);// container.removeView((View) object); } public void setList(List<CalenderBean> list) { this.list = list; notifyDataSetChanged(); } /** * 设置当前页 * @param position */ public void setCurrentPosition(int position) { //当前页改变后,把其他两页的数据设置成当前页的前一页和后一页 position = position % 3; CalenderBean calenderBean = list.get(position); int tmpPosition = (position + 1) % 3; list.remove(tmpPosition); list.add(tmpPosition, CalenderUtil.getNextCalender(calenderBean.getYear(), calenderBean.getMonth())); tmpPosition = (position - 1 + 3) % 3; list.remove(tmpPosition); list.add(tmpPosition, CalenderUtil.getPreCalender(calenderBean.getYear(), calenderBean.getMonth())); initCalenderView(); notifyDataSetChanged(); }}
每月日历
一个显示每月数据的日历控件。
1、第一行星期,周日到周六
2、六行具体天数,根据每月1号的星期和每月总天数,每行7天,可能需要5+1(空行)或6行数据
3、点击某日期选中
绘制头部星期和具体天数
/** * 头部绘制 * * @param canvas */ private void drawHeader(Canvas canvas) { drawOneText(canvas, "日", itemWidth / 2 + itemWidth * 0, itemWidth / 2, headerPaint); drawOneText(canvas, "一", itemWidth / 2 + itemWidth * 1, itemWidth / 2, headerPaint); drawOneText(canvas, "二", itemWidth / 2 + itemWidth * 2, itemWidth / 2, headerPaint); drawOneText(canvas, "三", itemWidth / 2 + itemWidth * 3, itemWidth / 2, headerPaint); drawOneText(canvas, "四", itemWidth / 2 + itemWidth * 4, itemWidth / 2, headerPaint); drawOneText(canvas, "五", itemWidth / 2 + itemWidth * 5, itemWidth / 2, headerPaint); drawOneText(canvas, "六", itemWidth / 2 + itemWidth * 6, itemWidth / 2, headerPaint); } /** * 绘制一个文字 * * @param canvas * @param text * @param centerX * @param centerY * @param paint */ private void drawOneText(Canvas canvas, String text, int centerX, int centerY, Paint paint) { float textWidth = paint.measureText(text); canvas.drawText(text, centerX - textWidth / 2, centerY - (paint.descent() + paint.ascent()) / 2, paint); } /** * 日期绘制 * * @param canvas */ private void drawDayItem(Canvas canvas) { for (int i = 0; i < cols; i++) { for (int j = 0; j < rows; j++) { if (dates[i][j] == preSelectDate) { drawSelectItem(canvas, String.valueOf(dates[i][j]), itemWidth * j + itemWidth / 2, itemHeight * (i + 1) + itemHeight / 2, false); } if (dates[i][j] == selectDate) { drawSelectItem(canvas, String.valueOf(dates[i][j]), itemWidth * j + itemWidth / 2, itemHeight * (i + 1) + itemHeight / 2, true); } else if (dates[i][j] > 0) { drawOneText(canvas, String.valueOf(dates[i][j]), itemWidth * j + itemWidth / 2, itemHeight * (i + 1) + itemHeight / 2, datePaint); } } } }
绘制选中和未选中日期
/** * 绘制选中项选中和未选中状态 * * @param canvas * @param text * @param centerX * @param centerY * @param isSelect */ private void drawSelectItem(Canvas canvas, String text, int centerX, int centerY, boolean isSelect) { selectItemPaint.setColor(isSelect ? selectBackColor : backColor); canvas.drawCircle(centerX, centerY, Math.min(itemWidth, itemHeight) / 2, selectItemPaint); if (isSelect) { selectItemPaint.setColor(selectTextColor); drawOneText(canvas, text, centerX, centerY, selectItemPaint); } }
点击选中具体日期
根据点击位置是否在某具体日期范围内,绘制选中日期
private PointF startPoint; @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { startPoint = new PointF(event.getX(), event.getY());// Log.i(TAG,startPoint.toString()); return true; } else if (event.getAction() == MotionEvent.ACTION_UP) { float x = event.getX(); float y = event.getY();// Log.i(TAG,x+","+y); //选中日期 if (Math.abs(startPoint.x - x) < 20 && Math.abs(startPoint.y - y) < 20) { for (int i = 0; i < cols; i++) { for (int j = 0; j < rows; j++) { if (dates[i][j] > 0 && x > itemWidth * j && x < itemWidth * (j + 1) && y > itemHeight * (i + 1) && y < itemHeight * (i + 2)) { preSelectDate = selectDate; selectDate = dates[i][j]; if (onItemSelectListener != null) { onItemSelectListener.onSelect(CalenderUtil.getCalender(year, month, selectDate)); } invalidate(); } } } return true; } } return super.onTouchEvent(event); }
ViewPager+日历控件 合体
实现一个继承自ViewPager的自定义控件,具体实现就是将上面两个的代码整合,在继承ViewPager的CalenderView控件中setAdapter无限滚动,每一页都返回一个具体月份的CalenderItemView控件。
源码Demo
阅读全文
0 0
- 【笔记】ViewPager+自定义控件实现的日历控件CalenderView
- 自定义控件实现日历
- 复杂自定义控件---自定义ViewPager的实现
- iOS自定义实现日历控件
- Android 自定义实现日历控件
- flex日历控件的自定义
- 安卓可滑动的自定义日历控件的实现
- 自定义SWT日历控件及其下拉菜单组件的实现
- 通过GridView实现一个自定义的一个日历控件
- Android自定义日历控件的实现过程详解
- js实现的日历控件
- Android 日历控件的实现
- 自定义日历控件(Calendar)
- 自定义日历控件
- Flex自定义日历控件
- 自定义Flex日历控件
- C#自定义日历控件
- android 自定义日历控件
- OpenGl(jogl)分形算法生成树
- 垃圾回收机制如何优化程序
- Python3 爬虫
- Intellij idea创建javaWeb以及Servlet简单实现
- VS 动态链接库(.dll)的加载问题
- 【笔记】ViewPager+自定义控件实现的日历控件CalenderView
- 定时任务demo
- Drools 运行时出现 java.lang.RuntimeException: wrong class format 问题解决
- linux-5-压缩打包
- ios 巧用UIButton的UIControlStateSelected属性
- 使用黄金分割比值计算斐波那契数列
- Linux编程:Valgrind在调试中的使用
- windows IO 设备以及打开
- Android SystemProperties设置/取得系统属性