尽管Android给我们提供了时间选择控件DatePicker和TimePicker(它们的使用方法可以参考我的这篇文章Android之日期时间选择控件DatePicker和TimePicker),但无奈我的项目主色调是土豪金和高级黑,原生的控件用在里面显得格格不入,特别是为了兼容低版本的系统之后显示的是2.x年代的风格,不但是简陋,简直是丑陋了。要解决这种问题,就只有走自定义控件这条道。但我目前还是不太熟悉自定义控件的写法,所以只好发挥拿来主义了。查看了一通之后,发现liuwan1992这位博主写的非常漂亮,我在他的基础上做了一些改动,使得整个控件更符合我的项目。

这是他的文章链接:Android 好看的自定义滚动式日期选择控件,关于控件的使用大家直接阅读他的文章即可。在此,感谢他的付出,本人只是巨人肩膀上的小白而已。

1、创建工程

你可以下载博主的源码,用Android Studio打开之后就直接动手修改,也可以像我这样新建一个工程,然后将需要用到的代码和文件从源码复制过来即可。

2、修改对话框外观

由于我需要用到我自己的颜色,所以在colors.xml中做了一些改动:

#3F51B5

#303F9F

#FF4081

#F0F0F0 //年、月、日等单位的字体颜色

#FFFFFF

#B0B0B0 //未被选中的数字颜色

#666666

#57C5E8

#b0000000 //作为背景的高级黑

#ffda53 //作为字体的土豪金

其中color_bg和color_gold分别是背景高级黑和字体土豪金。

资源文件准备好之后,就可以到对话框的布局custom_date_picker.xml中修改背景和字体颜色了。滚轮中选中和未选中的字体颜色则需要到DatePickerView中修改:

private void init() {

timer = new Timer();

mDataList = new ArrayList<>();

//第一个paint

mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

mPaint.setStyle(Style.FILL);

mPaint.setTextAlign(Align.CENTER);

//被选中的数字颜色

mPaint.setColor(ContextCompat.getColor(context, R.color.color_gold));

//第二个paint

nPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

nPaint.setStyle(Style.FILL);

nPaint.setTextAlign(Align.CENTER);

//未选中的数字颜色

nPaint.setColor(ContextCompat.getColor(context, R.color.color_text_unselected));

}

修改完的效果如下,项目需求如此,如果觉得辣眼睛的请多多谅解。

3、给控件增加标题

虽然选择的都是时间,但是如果我们在控件的标题中告诉用户当前要选择的是什么时间的话就更好一点。比如用户要确定一个时间段的话,我们就可以在弹出的控件上显示要选择的是“起始时间”还是“结束时间”。因此,我们可以在CustomDatePicker的构造函数中再增加一个参数:

public CustomDatePicker(Context context,String title, ResultHandler resultHandler, String startDate, String endDate) {

}

这样在创建控件时我们就可以把控件的标题传进去了。

4、点击控件以外的区域让控件消失

这个修改比较简单,我们的时间选择控件其实就是一个Dialog,只要将setCancelable方法设置为true就可以了。

5、修改选择顺序

这个控件的时间选择顺序默认是“年-月-日-时-分”,也就是选好了年才能选择月,选好了月才能选择日,从左到右。但是如果用户先确定了日,再去选择月的话,之后月份改变,日数就会重新从1开始。用户体验无疑是十分糟糕的,所以我们要把用户的每一步选择都保存下来,使控件可以从右到左选择时间。毫无疑问,这就需要到CustomDatePicker中改动了,因此,这一步的修改是最复杂也是最关键的。

5.1 保存用户选好的时间数据

打开CustomDatePicker文件,创建以下几个String变量:

private String currentMon, currentDay, currentHour, currentMin; //当前选中的月、日、时、分

年份位于最左端,“权限”是最高的,不会受其它数据的影响,可以不必保存。仔细想想,我们需要在两种情况下保存选中的日期数据:

用户滑动滚轮之后,保存选择的数据;

用户没有滑动滚轮,但是点击了对话框上的“确认”按钮

源码中,对于每个滚轮的滚动都写了监听方法,我们可以在每个监听方法中赋值:

private void addListener() {

year_pv.setOnSelectListener(new DatePickerView.onSelectListener() {

@Override

public void onSelect(String text) {

selectedCalender.set(Calendar.YEAR, Integer.parseInt(text));

monthChange();

}

});

month_pv.setOnSelectListener(new DatePickerView.onSelectListener() {

@Override

public void onSelect(String text) {

selectedCalender.set(Calendar.DAY_OF_MONTH, 1);

selectedCalender.set(Calendar.MONTH, Integer.parseInt(text) - 1);

currentMon = text; //保存选择的月份

dayChange();

}

});

day_pv.setOnSelectListener(new DatePickerView.onSelectListener() {

@Override

public void onSelect(String text) {

selectedCalender.set(Calendar.DAY_OF_MONTH, Integer.parseInt(text));

currentDay = text;//保存选择的日期

hourChange();

}

});

hour_pv.setOnSelectListener(new DatePickerView.onSelectListener() {

@Override

public void onSelect(String text) {

selectedCalender.set(Calendar.HOUR_OF_DAY, Integer.parseInt(text));

currentHour = text; //保存选择的小时

minuteChange();

}

});

minute_pv.setOnSelectListener(new DatePickerView.onSelectListener() {

@Override

public void onSelect(String text) {

selectedCalender.set(Calendar.MINUTE, Integer.parseInt(text));

currentMin = text; //保存选择的分钟

}

});

}

如果用户没有滑动滚轮,那么滚动监听事件就不会触发,这时就要到设置默认选中时间的方法setSelectedTime方法中去赋值了,比如分钟的赋值:

currentMin = timeStr[1]; //保存选择的分钟

其它的时间数据同理,代码太长,这里就不贴了,大家直接看Demo吧。

5.2 时间数据之间的联动逻辑

保存好数据之后还没有完,要知道,各个时间数据之间并不是可以任意选择的,它们之间是相互关联,相互制约的,特别是当你规定了最大时间不超过当前时间时。比如假设现在是2017年05月24日15:30,当我滑到2017年5月23日16:00,此时再将日改回24日时,时间显然是不能超过15:30的。这时就要做一些判断了。

以分钟的数值为例,如果当前的分钟数值小于60,而且之前选择的分钟数值比当前的分钟数值大,那么就要将分钟数值修改为当前的分钟时间,否则继续沿用之前的数值。

阅读源码可以看到,修改分钟数值的方法为minuteChange,将复位处理的代码注释之后,然后加上我们的逻辑判断。

// selectedCalender.set(Calendar.MINUTE, Integer.parseInt(minute.get(0)));

// minute_pv.setSelected(0);

if (minute.size() < 60 && minute.size() < Integer.valueOf(currentMin)) {

minute_pv.setSelected(minute.size() - 1);

selectedCalender.set(Calendar.MINUTE, minute.size());

//改变当前选择的分钟

currentMin = formatTimeUnit(minute.size());

} else {

minute_pv.setSelected(currentMin);

selectedCalender.set(Calendar.MINUTE, Integer.parseInt(currentMin));

}

小时的判断跟分钟的差不多,这里就贴代码了,但是月份的就有点特殊了,因为无论哪一天都是24小时,无论哪一小时都有60分钟,而每个月的天数却不尽相同,比如二月份就只有28或者29天。我们需要再创建一个int值变量lastMonthDays来记录上一个被选中的月份的天数。当前选中的月份天数比之前选中的月份天数少,而且之前选中的日的数值比当前选中的月份天数还有大时,那么日的数值就必须改为这个月的最后一天了。举个例子,比如将2017年3月31日中月份改为2月份,由于二月份只有28天,那么日的数值就不能停留在31了,而是跳转到28。

在dayChange方法中的代码修改如下:

// selectedCalender.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day.get(0)));

// day_pv.setSelected(0);

if (day.size() < lastMonthDays && Integer.valueOf(currentDay) > day.size()) {

day_pv.setSelected(day.size() - 1);

currentDay = formatTimeUnit(day.size());

} else {

day_pv.setSelected(currentDay);

}

selectedCalender.set(Calendar.DAY_OF_MONTH, Integer.parseInt(currentDay));

//重新赋值

lastMonthDays = day.size();

最后,当然也别忘了到setSelectedTime中给lastMonthDays设置默认值。

lastMonthDays = day.size();

6、将某一列的数值设为单独循环滚动

尽管源码中已经有setIsLoop方法可以设置为循环滚动,但是这个是将所有列都同时设置为循环滚动的,如果我们想单独将某一列设为循环滚动的话可以再增加几个方法:

public void setYearIsLoop(boolean isLoop) {

if (canAccess) {

this.year_pv.setIsLoop(isLoop);

}

}

public void setMonIsLoop(boolean isLoop) {

if (canAccess) {

this.month_pv.setIsLoop(isLoop);

}

}

public void setDayIsLoop(boolean isLoop) {

if (canAccess) {

this.day_pv.setIsLoop(isLoop);

}

}

public void setHourIsLoop(boolean isLoop) {

if (canAccess) {

this.hour_pv.setIsLoop(isLoop);

}

}

public void setMinIsLoop(boolean isLoop) {

if (canAccess) {

this.minute_pv.setIsLoop(isLoop);

}

}

7、去除对话框与屏幕之间的间距

这个问题我在Demo中没有发现,整合到工程中才遇到。弹出对话框时,左右和底部有一定的间距始终消除不了,但是在初始化对话框的方法initDialog方法中加了下面的代码就可以了:

window.setBackgroundDrawableResource(R.color.color_bg);

颜色的值可以是透明的,但个人觉得最后还是设置一个背景色。这个问题,目前我也没有找到原因……

8、总结

经过上面一番改动,我可以愉快地整合到我自己的项目中了,个人觉得这个控件挺美观实用的,欢迎大家支持原博主。如果大家有什么好的改动,也欢迎给我留言。下面附上源码:

android自定义滚轴选择器_Android自定义滚动式时间选择器(在他人基础上修改)...相关推荐

  1. android自定义滚轴选择器_Android自定义控件实战—滚动选择器PickerView

    手机里设置闹钟需要选择时间,那个选择时间的控件就是滚动选择器,前几天用手机刷了MIUI,发现自带的那个时间选择器效果挺好看的,于是就自己仿写了一个,权当练手.先来看效果: 效果还行吧?实现思路就是自定 ...

  2. Android 10.0 framework设备联网后系统时间没有自动同步更新的修改

    1.概述 在定制化10.0的产品开发中,在产品联网后系统都会自动同步时间,但在一些产品中,会出现即使联网了也不会同步时间的情况,开始以为是设备的网络问题,咨询同事和百度发现谷歌服务器会出现在大陆时间同 ...

  3. Android 选择器 PickerView实例,时间选择器、地址选择器、单项选择器、多项选择器自定义布局

    是采用的github开源库PickerView,省时省力.最终效果图见最后 首先添加依赖: //PickerView 选择器 implementation 'com.contrarywind:Andr ...

  4. android记账本折线图_Android自定义View - 仿支付宝月账单折线图

    前言 支付宝有个查看月账单的功能,最近一直在学习自定义View,于是就尝试着自己实现了一个类似的折线图. 下面是支付宝消费分析功能截图和自己实现的折线效果截图: 支付宝消费分析折线图.jpg 效果1. ...

  5. android app自动更新界面_Android自定义view之模仿登录界面文本输入框(华为云APP)...

    好久不见!!!!!,最近终于挤出时间来更新文章了,废话不多说,直接开始. 效果图如下: 01 分析 1.组合多个控件完成此输入框静态效果 2.hint值上浮下潜动画 3.一些功能 02 步骤 01 自 ...

  6. android 前台服务自定义布局不显示_Android自定义LinearLayout布局显示不完整的解决方法...

    发现问题 原需求,在一个伸缩列表中,自定义LinearLayout继承LinearLayout动态添加布局. 然而实现的时候:一共遍历了30条数据,却只显示了一条 断点查看代码:遍历addView() ...

  7. android 清空canvas部分内容_Android自定义View实现圆形头像效果

    在我们的APP中通常会遇到,展示圆形头像的需求,一般通过Glide就能实现,但是让我们做一个圆形头像,如果让我们自定义实现这种效果,该怎样做呢? 好,接下来本文通过三种方式来实现这种效果! 注意:这是 ...

  8. android 手写签批_Android自定义实现手写签名功能

    一.Android自定义View步骤 : 自定义属性: 选择和设置构造方法: 重写onMeasure()方法: 重写onDraw()方法: 重写onLayout()方法: 重写其他事件的方法(滑动监听 ...

  9. android 手写签批_Android自定义View——手写签批

    接到一个领导批示保留原笔迹的功能,类似于绘画板,用户打开后可以绘制,点击完成后以图片的形式保存在本地,并且显示绘制后图片,上传服务器,达到保留原笔迹的目的.可以运用于签字.审批等. 效果图: 手写签批 ...

最新文章

  1. STM8L编程环境官方库+STVD+COSMIC+ST-Link
  2. Java中集合中根据对象的某个属性去重
  3. 保存Delphi中的环境设置中的library path
  4. activiti异步执行_对基于消息队列的Activiti异步执行器进行基准测试
  5. mysql创建的数据库都在哪里看_mysql 怎么查看创建的数据库和表
  6. 再谈PHP、Python与Ruby
  7. jenkins pipline 用法收集
  8. Flex 布局实例教程
  9. 2021-09-03101. 对称二叉树
  10. Ubuntu彻底卸载MySQL
  11. 118页/8万字重磅(附下载)| 全球智能网联汽车产业深度报告:未来已来 掘金智能网联汽车时代【华西汽车 崔琰团队】
  12. power query时间函数(思维导图)
  13. 2022低压电工判断题及在线模拟考试
  14. mysql limit 索引失效_mysql索引失效
  15. c语言中合法的字符型常量是,字符串变量是什么意思
  16. gii无法访问 yii2_Gii的CURD生成无法访问?
  17. MATLAB求解导弹运动的一些基础方法
  18. 解密古代五大美男的凄惨结局
  19. 一文教你搞定PMOS管选型
  20. Chef 命令实例,你必须了解的100条

热门文章

  1. mysql内部_使用mysql中的内部加入
  2. 上网课的心得体会1000字_【家庭教育】家庭教育心得体会 ——济南市罗而小学家庭教育“好家风好家教”专栏(十一)...
  3. mysql的jdbc版本_【jdbc】Mysql 8版本jdbc设置
  4. vue 页面使用百度地图
  5. JSP EL表达式 格式化日期
  6. 计算机系统操作工培训视频,计算机系统操作工培训第三篇.ppt
  7. 支持三个cpu的服务器,基于第三代至强可扩展处理器,宁畅G40系列服务器正式发布...
  8. 喜马拉雅xm格式转化mp3_怎样让mp3录音转文字?
  9. mysql置疑原因_SQLSERVER数据库经常置疑的原因
  10. 分组数据方差公式_统计学公式