androidios 日历签到demodemo

本帖子已过去太久远了,不再提供回复功能。需求发布后1小时内收到服务商响应每个需求平均有10个服务商参与95%以上的需求得到了圆满解决所有需求不向雇主收取任何佣金电商双十二大促流量暴涨、销量翻倍的秘诀
android仿iphone原生日历控件
有相似问题想解决?专业顾问来帮助您
匹配服务商
选择服务商,签单
服务商工作
验收并付款
参与报价,开始赚钱
提交你的报价和方案
中标后交付作品
获得任务赏金
极速:10分钟急速响应
高品质:精选服务商提供服务
放心:不满意可退款
APP成品套餐
APP成品源码套餐
交易成功的需求
APP开发相关需求&&&&android 日历 demo
android 日历 demo
很好用的安卓日历,可以更改指定日期的颜色,适用于各类项目中
若举报审核通过,可奖励20下载分
被举报人:
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:
VIP下载&&免积分60元/年(1200次)
您可能还需要
移动开发下载排行Android 自定义控件之日历控件的实现_爱开发_传送门
Android 自定义控件之日历控件的实现
来源:IT之家作者:未知版权归原作者所有为什么要自定义控件有时,原生控件不能满足我们对于外观和功能的需求,这时候可以自定义控件来定制外观或功能;有时,原生控件可以通过复杂的编码实现想要的功能,这时候可以自定义控件来提高代码的可复用性。如何自定义控件下面我通过我在github上开源的Android-CalendarView项目为例,来介绍一下自定义控件的方法。该项目中自定义的控件类名是CalendarView。这个自定义控件覆盖了一些自定义控件时常需要重写的一些方法。构造函数为了支持本控件既能使用xml布局文件声明,也可在java文件中动态创建,实现了三个构造函数。public CalendarView(Context context, AttributeSet attrs, int defStyle);public CalendarView(Context context, AttributeSet attrs);public CalendarView(Context context);可以在参数列表最长的第一个方法中写上你的初始化代码,下面两个构造函数调用第一个即可。public CalendarView(Context context, AttributeSet attrs) {
this(context, attrs, 0);}public CalendarView(Context context) {
this(context, null);}那么在构造函数中做了哪些事情呢?1 读取自定义参数读取布局文件中可能设置的自定义属性(该日历控件仅自定义了一个mode参数来表示日历的模式)。代码如下。只要在attrs.xml中自定义了属性,就会自动创建一些R.styleable下的变量。TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CalendarView);mode = typedArray.getInt(R.styleable.CalendarView_mode, Constant.MODE_SHOW_DATA_OF_THIS_MONTH);然后附上res目录下values目录下的attrs.xml文件,需要在此文件中声明你自定义控件的自定义参数。<?xml version="1.0" encoding="utf-8"?>
<declare-styleable name="CalendarView">
<attr name="mode" format="integer" />
declare-styleable>resources>2 初始化关于绘制控件的相关参数如字体的颜色、尺寸,控件各个部分尺寸。3 初始化关于逻辑的相关参数对于日历来说,需要能够判断对应于当前的年月,日历中的每个单元格是否合法,以及若合法,其表示的day的值是多少。未设定年月之前先用当前时间来初始化。实现如下。/** * calculate the values of date[] and the legal range of index of date[] */private void initial() {
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
int monthStart = -1;
if(dayOfWeek >= 2 && dayOfWeek <= 7){
monthStart = dayOfWeek - 2;
}else if(dayOfWeek == 1){
monthStart = 6;
curStartIndex = monthStart;
date[monthStart] = 1;
int daysOfMonth = daysOfCurrentMonth();
for (int i = 1; i < daysOfMonth; i++) {
date[monthStart + i] = i + 1;
curEndIndex = monthStart + daysOfMonth;
if(mode == Constant.MODE_SHOW_DATA_OF_THIS_MONTH){
Calendar tmp = Calendar.getInstance();
todayIndex = tmp.get(Calendar.DAY_OF_MONTH) + monthStart - 1;
}}其中date[]是一个整型数组,长度为42,因为一个日历最多需要6行来显示(6*7=42),curStartIndex和curEndIndex决定了date[]数组的合法下标区间,即前者表示该月的第一天在date[]数组的下标,后者表示该月的最后一天在date[]数组的下标。4 绑定了一个OnTouchListener监听器监听控件的触摸事件。onMeasure方法该方法对控件的宽和高进行测量。CalendarView覆盖了View类的onMeasure()方法,因为某个月的第一天可能是星期一到星期日的任何一个,而且每个月的天数不尽相同,因此日历控件的行数会有多变化,也导致控件的高度会有变化。因此需要根据当前的年月计算控件显示的高度(宽度设为屏幕宽度即可)。实现如下。@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(screenWidth, View.MeasureSpec.EXACTLY);
heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(measureHeight(), View.MeasureSpec.EXACTLY);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);}其中screenWidth是构造函数中已经获取的屏幕宽度,measureHeight()则是根据年月计算控件所需要的高度。实现如下,已经写了非常详细的注释。/** * calculate the total height of the widget */private int measureHeight(){
* the weekday of the first day of the month, Sunday's result is 1 and Monday 2 and Saturday 7, etc.
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
* the number of days of current month
int daysOfMonth = daysOfCurrentMonth();
* calculate the total lines, which equals to 1 (head of the calendar) + 1 (the first line) + n/7 + (n%7==0?0:1)
* and n means numberOfDaysExceptFirstLine
int numberOfDaysExceptFirstLine = -1;
if(dayOfWeek >= 2 && dayOfWeek <= 7){
numberOfDaysExceptFirstLine = daysOfMonth - (8 - dayOfWeek + 1);
}else if(dayOfWeek == 1){
numberOfDaysExceptFirstLine = daysOfMonth - 1;
int lines = 2 + numberOfDaysExceptFirstLine / 7 + (numberOfDaysExceptFirstLine % 7 == 0 ? 0 : 1);
return (int) (cellHeight * lines);}onDraw方法该方法实现对控件的绘制。其中drawCircle给定圆心和半径绘制圆,drawText是给定一个坐标x,y绘制文字。/** * render */@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); /**
* render the head
*/ float baseline = RenderUtil.getBaseline(0, cellHeight, weekTextPaint); for (int i = 0; i < 7; i++) { float weekTextX = RenderUtil.getStartX(cellWidth * i + cellWidth * 0.5f, weekTextPaint, weekText[i]); canvas.drawText(weekText[i], weekTextX, baseline, weekTextPaint); } if(mode == Constant.MODE_CALENDAR){ for (int i = curStartIndex; i < curEndIndex; i++) { drawText(canvas, i, textPaint, "" + date[i]); } }else if(mode == Constant.MODE_SHOW_DATA_OF_THIS_MONTH){ for (int i = curStartIndex; i < curEndIndex; i++) { if(i < todayIndex){ if(data[date[i]]){ drawCircle(canvas, i, bluePaint, cellHeight * 0.37f); drawCircle(canvas, i, whitePaint, cellHeight * 0.31f); drawCircle(canvas, i, blackPaint, cellHeight * 0.1f); }else{ drawCircle(canvas, i, grayPaint, cellHeight * 0.1f); } }else if(i == todayIndex){ if(data[date[i]]){ drawCircle(canvas, i, bluePaint, cellHeight * 0.37f); drawCircle(canvas, i, whitePaint, cellHeight * 0.31f); drawCircle(canvas, i, blackPaint, cellHeight * 0.1f); }else{ drawCircle(canvas, i, grayPaint, cellHeight * 0.37f); drawCircle(canvas, i, whitePaint, cellHeight * 0.31f); drawCircle(canvas, i, blackPaint, cellHeight * 0.1f); } }else{ drawText(canvas, i, textPaint, "" + date[i]); } } }}需要说明的是,绘制文字时的这个x表示开始位置的x坐标(文字最左端),这个y却不是文字最顶端的y坐标,而应传入文字的baseline。因此若想要将文字绘制在某个区域居中部分,需要经过一番计算。本项目将其封装在了RenderUtil类中。实现如下。/** * get the baseline to draw between top and bottom in the middle */public static float getBaseline(float top, float bottom, Paint paint){ Paint.FontMetrics fontMetrics = paint.getFontMetrics(); return (top + bottom - fontMetrics.bottom - fontMetrics.top) / 2;}/** * get the x position to draw around the middle */public static float getStartX(float middle, Paint paint, String text){ return middle - paint.measureText(text) * 0.5f;}自定义监听器控件需要自定义一些监听器,以在控件发生了某种行为或交互时提供一个外部接口来处理一些事情。本项目的CalendarView提供了两个接口,OnRefreshListener和OnItemClickListener,均为自定义的接口。onItemClick只传了day一个参数,年和月可通过CalendarView对象的getYear和getMonth方法获取。interface OnItemClickListener{ void onItemClick(int day);}interface OnRefreshListener{ void onRefresh();}先介绍一下两种mode,CalendarView提供了两种模式,第一种普通日历模式,日历每个位置简单显示了day这个数字,第二种本月计划完成情况模式,绘制了一些图形来表示本月的某一天是否完成了计划(模仿自悦跑圈,用一个圈表示本日跑了步)。OnRefreshListener用于刷新日历数据后进行回调。两种模式定义了不同的刷新方法,都对OnRefreshListener进行了回调。refresh0用于第一种模式,refresh1用于第二种模式。/** * used for MODE_CALENDAR * legal values of month: 1-12 */@Overridepublic void refresh0(int year, int month) { if(mode == Constant.MODE_CALENDAR){ selectedYear = year; selectedMonth = month; calendar.set(Calendar.YEAR, selectedYear); calendar.set(Calendar.MONTH, selectedMonth - 1); calendar.set(Calendar.DAY_OF_MONTH, 1); initial(); invalidate(); if(onRefreshListener != null){ onRefreshListener.onRefresh(); } }} /** * used for MODE_SHOW_DATA_OF_THIS_MONTH * the index 1 to 31(big month), 1 to 30(small month), 1 - 28(Feb of normal year), 1 - 29(Feb of leap year) * is better to be accessible in the parameter data, illegal indexes will be ignored with default false value */@Overridepublic void refresh1(boolean[] data) { /**
* the month and year may change (eg. Jan 31st becomes Feb 1st after refreshing)
*/ if(mode == Constant.MODE_SHOW_DATA_OF_THIS_MONTH){ calendar = Calendar.getInstance(); selectedYear = calendar.get(Calendar.YEAR); selectedMonth = calendar.get(Calendar.MONTH) + 1; calendar.set(Calendar.DAY_OF_MONTH, 1); for(int i = 1; i <= daysOfCurrentMonth(); i++){ if(i < data.length){ this.data[i] = data[i]; }else{ this.data[i] = false; } } initial(); invalidate(); if(onRefreshListener != null){ onRefreshListener.onRefresh(); } }}OnItemClickListener用于响应点击了日历上的某一天这个事件。点击的判断在onTouch方法中实现。实现如下。在同一位置依次接收到ACTION_DOWN和ACTION_UP两个事件才认为完成了点击。@Overridepublic boolean onTouch(View v, MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if(coordIsCalendarCell(y)){ int index = getIndexByCoordinate(x, y); if(isLegalIndex(index)) { actionDownIndex = index; } } break; case MotionEvent.ACTION_UP: if(coordIsCalendarCell(y)){ int actionUpIndex = getIndexByCoordinate(x, y); if(isLegalIndex(actionUpIndex)){ if(actionDownIndex == actionUpIndex){ actionDownIndex = -1; int day = date[actionUpIndex]; if(onItemClickListener != null){ onItemClickListener.onItemClick(day); } } } } break; } return true;}关于该日历控件日历控件demo效果图如下,分别为普通日历模式和本月计划完成情况模式。需要说明的是CalendarView控件部分只包括日历头与下面的日历,该控件上方的是其他控件,这里仅用作展示一种使用方法,你完全可以自定义这部分的样式。此外,日历头的文字支持多种选择,比如周一有四种表示:一、周一、星期一、Mon。此外还有其他一些控制样式的接口,详情见github项目主页。github项目主页: /laserwave/Android-CalendarView ABOUT US 开发 · 干货
· 生活|带你了解IT世界的根源投稿/合作wecat:wangzishuo200058
觉得不错,分享给更多人看到
爱开发 微信二维码
分享这篇文章
6月25日 22:23
爱开发 最新文章
爱开发 热门文章Android日历控件 - HU - ITeye技术网站
博客分类:
CalendarView控件需要API11及以上使用
&CalendarView
android:id="@+id/calendar_view"
android:layout_width="match_parent"
android:layout_height="match_parent" /&
CalendarView calendarView = (CalendarView) findViewById(R.id.calendar_view);
calendarView.setOnDateChangeListener(new OnDateChangeListener() {
public void onSelectedDayChange(CalendarView view, int year, int month, int dayOfMonth) {
String date = year + "年" + month + "月" + dayOfMonth + "日";
Toast.makeText(getApplicationContext(), date, Toast.LENGTH_LONG).show();
浏览: 11802 次
来自: 杭州
我想表达的是,里面的
监听 没有处理
点击 没有光标
layoutIndex 这是干嘛的
isMeasured 是个boolean??哪里初始化的。。。 ...
已解决,在配置文件 AndroidManifest.xml里面 ...
白青龙 写道运行不了啊,换了好几个url还是不行,一直在加载。 ...}

我要回帖

更多关于 日历demo 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信