需求:实现一年月日选择器,默认为当前日期,三者联动,并且在切换年月时,根据是否闰年或者月份天数动态改变日。多说无益,请看下图:

使用的第三方库(https://github.com/helloJp/WheelView)
此库可兼容到低版本,定制性很强,获取选中数据很方便。详情请戳链接,感谢helloJp的分享。

activity_main.xml放置一个封装好WheelView的自定义控件,没有什么自定义属性

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><test.oubowu.com.datepicker.DatePickerandroid:id="@+id/birthday_picker"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_centerInParent="true"android:layout_margin="5dp"android:gravity="center_horizontal" /></RelativeLayout>

date_picker.xml线性布局放置三个WheelView,分别对应年月日:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/rectangle_bg"android:padding="2dp"android:gravity="center_vertical"android:orientation="horizontal"><test.oubowu.com.datepicker.WheelView
        android:id="@+id/year"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"app:itemNumber="5"app:lineColor="@android:color/darker_gray"app:lineHeight="2dp"app:maskHight="32dp"app:noEmpty="true"app:normalTextColor="@color/material_green_300"app:normalTextSize="14sp"app:selectedTextColor="@color/material_light_blue_a700"app:selectedTextSize="22sp"app:unitHight="50dp"/><test.oubowu.com.datepicker.WheelView
        android:id="@+id/month"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"app:itemNumber="5"app:lineColor="@android:color/darker_gray"app:lineHeight="2dp"app:maskHight="32dp"app:noEmpty="true"app:normalTextColor="@color/material_light_blue_a100"app:normalTextSize="14sp"app:selectedTextColor="@color/material_red_300"app:selectedTextSize="22sp"app:unitHight="50dp"/><test.oubowu.com.datepicker.WheelView
        android:id="@+id/day"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"app:itemNumber="5"app:lineColor="@android:color/darker_gray"app:lineHeight="2dp"app:maskHight="32dp"app:noEmpty="true"app:normalTextColor="@color/material_orange_500"app:normalTextSize="14sp"app:selectedTextColor="@color/material_deep_purple_300"app:selectedTextSize="22sp"app:unitHight="50dp"/></LinearLayout>

自定义属性如下,定制性相当强:

Attributes
There are several attributes you can set:attr 属性 description 描述
lineColor   divider line color 分割线颜色
lineHeight  divider line height 分割线高度
itemNumber  wheelview show item count 此wheelView显示item的个数
maskHight   mask height 蒙版高度(normalText的位置)
noEmpty if set true select area can't be null(empty),or could be empty 设置true则选中不能为空,否则可以是空
normalTextColor unSelected Text color 未选中文本颜色
normalTextSize  unSelected Text size 未选中文本字体大小
selectedTextColor   selected Text color 选中文本颜色
selectedTextSize    selected Text size 选中文本字体大小
unitHight   item unit height 每个item单元的高度

主要看下DatePicker 代码是如何实现联动的:

public class DatePicker extends LinearLayout implements WheelView.OnSelectListener {public DatePicker(Context context) {this(context, null);}public DatePicker(Context context, AttributeSet attrs) {super(context, attrs);}/*** 获取选择的年** @return*/public String getYear() {return mWheelYear.getSelectedText();}/*** 获取选择的月** @return*/public String getMonth() {return mWheelMonth.getSelectedText();}/*** 获取选择的日** @return*/public String getDay() {return mWheelDay.getSelectedText();}private WheelView mWheelYear;private WheelView mWheelMonth;private WheelView mWheelDay;@Overrideprotected void onFinishInflate() {super.onFinishInflate();LayoutInflater.from(getContext()).inflate(R.layout.date_picker, this);mWheelYear = (WheelView) findViewById(R.id.year);mWheelMonth = (WheelView) findViewById(R.id.month);mWheelDay = (WheelView) findViewById(R.id.day);// 格式化当前时间,并转换为年月日整型数据SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());String[] split = sdf.format(new Date()).split("-");int currentYear = Integer.parseInt(split[0]);int currentMonth = Integer.parseInt(split[1]);int currentDay = Integer.parseInt(split[2]);// 设置默认年月日为当前日期mWheelYear.setData(getYearData(currentYear));mWheelYear.setDefault(0);mWheelMonth.setData(getMonthData());mWheelMonth.setDefault(currentMonth - 1);mWheelDay.setData(getDayData(getLastDay(currentYear, currentMonth)));mWheelDay.setDefault(currentDay - 1);mWheelYear.setOnSelectListener(this);mWheelMonth.setOnSelectListener(this);mWheelDay.setOnSelectListener(this);}/*** 年范围在:1900~今年** @param currentYear* @return*/private ArrayList<String> getYearData(int currentYear) {ArrayList<String> list = new ArrayList<>();for (int i = currentYear; i >= 1900; i--) {list.add(String.valueOf(i));}return list;}private ArrayList<String> getMonthData() {ArrayList<String> list = new ArrayList<>();for (int i = 1; i <= 12; i++) {list.add(String.valueOf(i));}return list;}/*** 日范围在1~lastDay** @param lastDay* @return*/private ArrayList<String> getDayData(int lastDay) {//ignore conditionArrayList<String> list = new ArrayList<>();for (int i = 1; i <= lastDay; i++) {list.add(String.valueOf(i));}return list;}/*** 判断是否闰年** @param year* @return*/private boolean isLeapYear(int year) {return (year % 100 == 0 && year % 400 == 0) || (year % 100 != 0 && year % 4 == 0);}/*** 获取特定年月对应的天数** @param year* @param month* @return*/private int getLastDay(int year, int month) {if (month == 2) {// 2月闰年的话返回29,防止28return isLeapYear(year) ? 29 : 28;}// 一三五七八十腊,三十一天永不差return month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12 ? 31 : 30;}@Overridepublic void endSelect(View view, int id, String text) {// 滚轮滑动停止后调用switch (view.getId()) {case R.id.year:case R.id.month:// 记录当前选择的天数int selectDay = Integer.parseInt(getDay());// 根据当前选择的年月获取对应的天数int lastDay = getLastDay(Integer.parseInt(getYear()), Integer.parseInt(getMonth()));// 设置天数mWheelDay.setData(getDayData(lastDay));// 如果选中的天数大于实际天数,那么将默认天数设为实际天数;否则还是设置默认天数为选中的天数if (selectDay > lastDay) {mWheelDay.setDefault(lastDay - 1);} else {mWheelDay.setDefault(selectDay - 1);}break;}}@Overridepublic void selecting(View view, int id, String text) {}}

DatePicker继承于线性布局,在onFinishInflate填充date_picker.xml布局,然后拿到三个wheelview,格式化时间,取出年月日。

WheelView的方法:

Method
1. setData(ArrayList data)set WheelView data
设置WheelView的数据2. resetData(ArrayList data)reset WheelView data ,if you has setData
重置 WheelView的数据,如果已经设置过的话3. int getSelected()get selected item index
获取选中项的index4. String getSelectedText()get selected item text
获取选中项的文本信息5. boolean isScrollingis WheelView is scrolling
获取WheelView是否在滚动中6. boolean isEnable()is WheelView is enable
获取wheelView是否可用7. void setEnable(boolean isEnable)set WheelView enable
设置WheelView是否可用8. void setDefault(int index)set default selected index
设置默认选中项的index9. int getListSize()get WheelView item count
获取WheelView的item项个数10. String getItemText(int index)get the text by index
获取index位置上的文本数据11. void setOnSelectListener(OnSelectListener onSelectListener)set listener on WheelView that can get info when WheelView is scrolling or stop scroll.
对WheelView设置监听,在 滑动过程 或者 滑动停止 返回数据信息。

年的话是以当前年作为最开始选中的,因为我实际用来做生日选择器的;月就是12个月没什么好说的。

mWheelYear.setData(getYearData(currentYear));
private ArrayList<String> getYearData(int currentYear) {ArrayList<String> list = new ArrayList<>();for (int i = currentYear; i >= 1900; i--) {list.add(String.valueOf(i));}return list;}

日的话稍微复杂点,因为月份不同日数不同,闰年二月天数多一天,所以做多判断。
getLastDay(currentYear, currentMonth)就是根据年月算出日数

mWheelDay.setData(getDayData(getLastDay(currentYear, currentMonth)));private ArrayList<String> getDayData(int lastDay) {//ignore conditionArrayList<String> list = new ArrayList<>();for (int i = 1; i <= lastDay; i++) {list.add(String.valueOf(i));}return list;}private int getLastDay(int year, int month) {if (month == 2) {// 2月闰年的话返回29,防止28return isLeapYear(year) ? 29 : 28;}// 一三五七八十腊,三十一天永不差return month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12 ? 31 : 30;}private boolean isLeapYear(int year) {return (year % 100 == 0 && year % 400 == 0) || (year % 100 != 0 && year % 4 == 0);}

我们要联动的话就需要监听三个WheelView的滚动停止对应的数据了,WheelView提供setOnSelectListener给我们监听,这里只需在停止的时候拿到数据做联动即可。
为了直观一点,我们选中的天数会根据年月的不同计算出的实际天数做对比,若选中的天数大于实际天数,会回退到实际天数。

@Overridepublic void endSelect(View view, int id, String text) {// 滚轮滑动停止后调用switch (view.getId()) {case R.id.year:case R.id.month:// 记录当前选择的天数int selectDay = Integer.parseInt(getDay());// 根据当前选择的年月获取对应的天数int lastDay = getLastDay(Integer.parseInt(getYear()), Integer.parseInt(getMonth()));// 设置天数mWheelDay.setData(getDayData(lastDay));// 如果选中的天数大于实际天数,那么将默认天数设为实际天数;否则还是设置默认天数为选中的天数if (selectDay > lastDay) {mWheelDay.setDefault(lastDay - 1);} else {mWheelDay.setDefault(selectDay - 1);}break;}}

实在是简单实用,比官方的好用何止一丢丢。
Demo下载链接如下:
http://download.csdn.net/detail/oushangfeng123/9034101

使用第三方WheelView制作日期选择器相关推荐

  1. android自定义滚动日期,Android基于wheelView实现自定义日期选择器

    本文实例为大家分享了Android实现自定义日期选择器的具体代码,供大家参考,具体内容如下 项目要求效果图: 要求 "6月20 星期五" 这一项作为一个整体可以滑动,"7 ...

  2. Android基于wheelView的自定义日期选择器(可拓展样式)

    基于wheelView的自定义日期选择器 项目要求效果图: 要求 "6月20 星期五" 这一项作为一个整体可以滑动,"7时"."48分"分别 ...

  3. android日期选择滚轮框架,GitHub - liwenzhi/wheelview: 滚轮效果的View,日期选择器

    #wheelview滚动效果的View 这段时间需要用到一个时间选择器,但是不能使用日期对话框, 因为它是筛选条件框架下的,只能是View!这个WheelView改造后可以达到要求! 这个wheelv ...

  4. Angular中修改第三方组件的样式 - zorro日期选择器右端不对齐的BUG

    在一列上同时使用zorro的日期选择器和input组件会出现右端不对齐的BUG(nzSpan设置为一样) 上图中3个表单项:单据日期.开票.交货方式,nzSpan数值是一样的,可以看到日期选择器和下面 ...

  5. 如何使用Dojo的DatePicker控件制作联动日期选择器

    在开发系统的调查功能时,需要设计一个可以联动的开始日期/结束日期选择器用来设定用户的调查的起始/结束日期.对于这个联动的日期选择器,我们的设计要求是这样的: 在新增调查时,该调查的开始日期默认为今天, ...

  6. Android Compose日期选择器

    由于官方还没有推出日期选择器,我们只能自己制作,或者通过AndoirdView和DatePickerDialog. 下面是我自己制作的一个Compose日期选择器,以下都只能用作学习,还达不到项目使用 ...

  7. flutter 类似日期选择器控件_一切皆组件的Flutter,安能辨我是雄雌

    从一开始接触Flutter,相信读者都会铭记一句话,那就是--一切皆组件.今天我们就来体会一下这句话的神奇魔力,我们先从实际的产品需求说起. 我们先来看一个简化的运行图: 我们要实现如上图所示的日期选 ...

  8. Android年月日选择,Android日期选择器实现年月日三级联动

    最近项目里面用到了一个日期选择器,实现现在主流的WheelView滑动选择,整理了下,做了个Demo.废话不多说,直接上代码. 主布局:activity_main.xml xmlns:tools=&q ...

  9. 基于bootstrap模态框的日期选择器

    近来由于工作需求,以bootstrap模态框+DIV+CSS+JS做了一个适用于移动端的日期选择器,能够满足多样的需求,目前处于第一个版本,后续可能会继续更新.废话不多说,直接进入制作过程. 首先,需 ...

最新文章

  1. SSAS系列——【03】多维数据(多维数据集对象)
  2. Android Virtual Device(AVD)屏幕大小调整
  3. Kafka分布式环境搭建
  4. EDM邮件营销时应该远离的8大不良做法
  5. 虚拟服务器(dmz),dmz虚拟主机(dmz主机和虚拟服务器区别)
  6. 华为p10 鸿蒙,全面上线!华为鸿蒙新消息传来,这是要彻底替换安卓
  7. ABAP内表数据和JSON格式互转
  8. Study Struts Commons Validator
  9. PyTorch 中如何指定GPU
  10. 【GStreamer开发】GStreamer基础教程05——集成GUI工具
  11. 安全HCIP之eSight
  12. Spring Guide:Securing a Web Application(中文大概意思)
  13. Excel自动填充功能
  14. Centos7.6安装Bugzilla5.0.4
  15. Evasion Attack in Adversarial Machine Learning
  16. [转贴]杨式太极拳八十五式通释—2—王志远
  17. 【Git学习】如何删除Git中的大文件
  18. POJ Treasure Exploration 【DAG交叉最小路径覆盖】
  19. 腾讯云被索赔一亿,否认对她拍进行技术打压
  20. 在ASP.NET Core (.NET 6)中构建可视化医生预约调度系统

热门文章

  1. 为什么implement Serializable 以及如何使用idea自动生成serialVersionUID
  2. 日常记录生活中的那些小小事01
  3. 如何备份卡巴斯基的病毒库文件
  4. 求购X-Argus,X-Gorgon,X-Khronos,X-Ladon python版 xa、xg、xk、xl
  5. 华丽成长为IT高富帅、IT白富美(七)
  6. android,进入页面textview默认获得焦点问题,如何取消焦点
  7. note : 有些道理的话
  8. 初次运行gan,运行vanilla_gan过程中踩的坑
  9. Varnish正向代理
  10. H3C ER3100路由器由于FAST路由器的ARP欺骗导致的断网的处理方法