基于wheelView的自定义日期选择器

项目要求效果图:

要求 “6月20 星期五” 这一项作为一个整体可以滑动,”7时”、”48分”分别作为一个滑动整体。

系统自带的DatePicker、TimePicker大家都知道,只有这种效果:

百度了很多,试了NumberPicker等都不行,本来打算自己写。网友推荐了一个开源组件WheelView,下下来试了试,发现他已经定义的很完善了,在他的基础上拓展很容易。

现将基于wheelView自定义日期选择器记录如下:

一.首先要了解WheelView为我们提供了什么:

除了我写的”DateObject”与”StringWheelAdapter”,其余都是WheelView提供的,

1. WheelView.java : 可滚动的组件,

主要方法:
setAdapter(new StringWheelAdapter(dateList, 7)); //设置Adapter
setVisibleItems(3); //设置显示几行数据
setCyclic(true); //设置是否循环显示数据
addChangingListener(onDaysChangedListener) //设置滑动监听器

2. WheelAdapter.java : 滑动组件的适配器的接口,子类适配器用于装载数据

public interface WheelAdapter {/*** Gets items count* @return the count of wheel items*/public int getItemsCount();/*** Gets a wheel item by index.* * @param index the item index* @return the wheel item text or null*/public String getItem(int index);/*** Gets maximum item length. It is used to determine the wheel width. * If -1 is returned there will be used the default wheel width.* * @return the maximum item length or -1*/public int getMaximumLength();
}

3. OnWheelChangedListener.java : 滑动监听器接口

public interface OnWheelChangedListener {/*** Callback method to be invoked when current item changed* @param wheel the wheel view whose state has changed* @param oldValue the old value of current item* @param newValue the new value of current item*/void onChanged(WheelView wheel, int oldValue, int newValue);
}

4.OnWheelScrollListener.java :滚动监听器接口(暂时没用到)

5.NumericWheelAdapter.java : 当滚动内容为纯数字时调用的适配器

6.DateObject.java : 日期实体类,用于存储、获取选择的数据

package kankan.wheel.widget;import java.util.Calendar;public class DateObject extends Object{private int year ;private int month;private int day;private int week;private int hour;private int minute;private String listItem;/*** 日期对象的4个参数构造器,用于设置日期* @param year* @param month* @param day* @author sxzhang*/public DateObject(int year2, int month2, int day2,int week2) {super();this.year = year2;int maxDayOfMonth = Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH);if(day2 > maxDayOfMonth){this.month = month2 + 1;this.day = day2 % maxDayOfMonth;}else{this.month = month2;this.day = day2;}this.week = week2 % 7 == 0 ? 7 : week2 % 7;if(day == Calendar.getInstance().get(Calendar.DAY_OF_MONTH)){this.listItem = String.format("%02d", this.month) +"月" + String.format("%02d", this.day)  + "日      "+ "  今天  ";}else{this.listItem = String.format("%02d", this.month) +"月" + String.format("%02d", this.day)  + "日      "+ getDayOfWeekCN(week);}}/*** 日期对象的2个参数构造器,用于设置时间* @param hour2* @param minute2* @param isHourType true:传入的是hour; false: 传入的是minute* @author sxzhang*/public DateObject(int hour2,int minute2,boolean isHourType) {super();if(isHourType == true && hour2 != -1){      //设置小时if(hour2 > 24){this.hour = hour2 % 24;}elsethis.hour = hour2;this.listItem =  this.hour + "时";}else if(isHourType == false && minute2 != -1){ //设置分钟if(minute2 > 60)this.minute = minute2 % 60;elsethis.minute = minute2;this.listItem =  this.minute + "分";}}public int getHour() {return hour;}public void setHour(int hour) {this.hour = hour;}public int getMinute() {return minute;}public void setMinute(int minute) {this.minute = minute;}public int getWeek() {return week;}public void setWeek(int week) {this.week = week;}public int getYear() {return year;}public void setYear(int year) {this.year = year;}public int getMonth() {return month;}public void setMonth(int month) {this.month = month;}public int getDay() {return day;}public void setDay(int day) {this.day = day;}public String getListItem() {return listItem;}public void setListItem(String listItem) {this.listItem = listItem;}/*** 根据day_of_week得到汉字星期* @return*/public static String getDayOfWeekCN(int day_of_week){String result = null;switch(day_of_week){case 1:result = "星期日";break;case 2:result = "星期一";break;case 3:result = "星期二";break;case 4:result = "星期三";break;case 5:result = "星期四";break;case 6:result = "星期五";break;case 7:result = "星期六";break;  default:break;}return result;}
}

7.StringWheelAdapter.java :一会儿将定义的滚动内容为字符串的适配器,当内容为字符串时我们就可以随意拓展滑动部分的内容

package kankan.wheel.widget;import java.util.ArrayList;/*** The simple String Array wheel adapter* */
public class StringWheelAdapter implements WheelAdapter {/** The default items length */public static final int DEFAULT_LENGTH = -1;// itemsprivate ArrayList<DateObject> list;// lengthprivate int length;/*** Constructor* @param items the items* @param length the max items length*/public StringWheelAdapter(ArrayList<DateObject> list, int length) {this.list = list;this.length = length;}@Overridepublic String getItem(int index) {if (index >= 0 && index < list.size()) {return list.get(index).getListItem();}return null;}@Overridepublic int getItemsCount() {return list.size();}@Overridepublic int getMaximumLength() {return length;}}

二.了解以后就可以使用他定义我们需要的了。

1.首先要做的是这个效果的部分:

我们将其命名为DatePicker:

package com.sxkeji.timeswitch.widget;import java.util.ArrayList;
import java.util.Calendar;import kankan.wheel.widget.DateObject;
import kankan.wheel.widget.OnWheelChangedListener;
import kankan.wheel.widget.StringWheelAdapter;
import kankan.wheel.widget.WheelView;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;/*** 自定义的日期选择器* @author sxzhang**/
public class DatePicker extends LinearLayout {private Calendar calendar = Calendar.getInstance(); private WheelView newDays;private ArrayList<DateObject> dateList ;private OnChangeListener onChangeListener; //onChangeListenerprivate final int MARGIN_RIGHT = 20;private DateObject dateObject;      //日期数据对象//Constructorspublic DatePicker(Context context) {super(context);init(context);}public DatePicker(Context context, AttributeSet attrs) {super(context, attrs);init(context);}/*** 初始化* @param context*/private void init(Context context){int year = calendar.get(Calendar.YEAR);int month = calendar.get(Calendar.MONTH) + 1;int day = calendar.get(Calendar.DAY_OF_MONTH);int week = calendar.get(Calendar.DAY_OF_WEEK);dateList = new ArrayList<DateObject>();for (int i = 0; i < 7; i++) {dateObject = new DateObject(year, month, day+i, week+i);dateList.add(dateObject);}newDays = new WheelView(context);LayoutParams newDays_param = new LayoutParams(300,LayoutParams.WRAP_CONTENT);newDays_param.setMargins(0, 0, MARGIN_RIGHT, 0);newDays.setLayoutParams(newDays_param);newDays.setAdapter(new StringWheelAdapter(dateList, 7));newDays.setVisibleItems(3);newDays.setCyclic(true);newDays.addChangingListener(onDaysChangedListener);     addView(newDays);}/*** 滑动改变监听器*/private OnWheelChangedListener onDaysChangedListener = new OnWheelChangedListener(){@Overridepublic void onChanged(WheelView mins, int oldValue, int newValue) {calendar.set(Calendar.DAY_OF_MONTH, newValue + 1);change();}};/*** 滑动改变监听器回调的接口*/public interface OnChangeListener {void onChange(int year, int month, int day, int day_of_week);}/*** 设置滑动改变监听器* @param onChangeListener*/public void setOnChangeListener(OnChangeListener onChangeListener){this.onChangeListener = onChangeListener;}/*** 滑动最终调用的方法*/private void change(){if(onChangeListener!=null){onChangeListener.onChange(dateList.get(newDays.getCurrentItem()).getYear(), dateList.get(newDays.getCurrentItem()).getMonth(), dateList.get(newDays.getCurrentItem()).getDay(), dateList.get(newDays.getCurrentItem()).getWeek());}}/*** 根据day_of_week得到汉字星期* @return*/public static String getDayOfWeekCN(int day_of_week){String result = null;switch(day_of_week){case 1:result = "星期日";break;case 2:result = "星期一";break;case 3:result = "星期二";break;case 4:result = "星期三";break;case 5:result = "星期四";break;case 6:result = "星期五";break;case 7:result = "星期六";break;  default:break;}return result;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}
}

2.然后要做的是这个效果的部分

我们命名为TimePicker:

package com.sxkeji.timeswitch.widget;import java.util.ArrayList;
import java.util.Calendar;import kankan.wheel.widget.DateObject;
import kankan.wheel.widget.OnWheelChangedListener;
import kankan.wheel.widget.StringWheelAdapter;
import kankan.wheel.widget.WheelView;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;/*** 自定义的时间选择器* @author sxzhang**/
public class TimePicker extends LinearLayout{private Calendar calendar = Calendar.getInstance(); private WheelView hours, mins; //Wheel pickerprivate OnChangeListener onChangeListener; //onChangeListenerprivate final int MARGIN_RIGHT = 15;        //调整文字右端距离private ArrayList<DateObject> hourList,minuteList;private DateObject dateObject;      //时间数据对象//Constructorspublic TimePicker(Context context) {super(context);init(context);}public TimePicker(Context context, AttributeSet attrs) {super(context, attrs);init(context);}/*** 初始化* @param context*/private void init(Context context){int hour = calendar.get(Calendar.HOUR_OF_DAY);int minute = calendar.get(Calendar.MINUTE);hourList = new ArrayList<DateObject>();minuteList = new ArrayList<DateObject>();for (int i = 0; i < 24; i++) {dateObject = new DateObject(hour+i,-1,true);hourList.add(dateObject);}for (int j = 0; j < 60; j++) {dateObject = new DateObject(-1,minute+j,false);minuteList.add(dateObject);}//小时选择器hours = new WheelView(context);LayoutParams lparams_hours = new LayoutParams(80,LayoutParams.WRAP_CONTENT);lparams_hours.setMargins(0, 0, MARGIN_RIGHT, 0);hours.setLayoutParams(lparams_hours);hours.setAdapter(new StringWheelAdapter(hourList, 24));hours.setVisibleItems(3);hours.setCyclic(true);hours.addChangingListener(onHoursChangedListener);      addView(hours);     //分钟选择器mins = new WheelView(context);mins.setLayoutParams(new LayoutParams(80,LayoutParams.WRAP_CONTENT));mins.setAdapter(new StringWheelAdapter(minuteList,60));mins.setVisibleItems(3);mins.setCyclic(true);mins.addChangingListener(onMinsChangedListener);        addView(mins);      }//listenersprivate OnWheelChangedListener onHoursChangedListener = new OnWheelChangedListener(){@Overridepublic void onChanged(WheelView hours, int oldValue, int newValue) {calendar.set(Calendar.HOUR_OF_DAY, newValue);change();}};private OnWheelChangedListener onMinsChangedListener = new OnWheelChangedListener(){@Overridepublic void onChanged(WheelView mins, int oldValue, int newValue) {calendar.set(Calendar.MINUTE, newValue);change();}};/*** 滑动改变监听器回调的接口*/public interface OnChangeListener {void onChange(int hour, int munite);}/*** 设置滑动改变监听器* @param onChangeListener*/public void setOnChangeListener(OnChangeListener onChangeListener){this.onChangeListener = onChangeListener;}/*** 滑动最终调用的方法*/private void change(){if(onChangeListener!=null){onChangeListener.onChange(getHourOfDay(), getMinute());}}/*** 获取小时* @return*/public int getHourOfDay(){return hourList.get(hours.getCurrentItem()).getHour();}/*** 获取分钟* @return*/public int getMinute(){return minuteList.get(mins.getCurrentItem()).getMinute();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}
}

3.z最后就可以直接使用了,我这里主界面是一个button,点击后弹出popupWindow显示日期选择器。布局文件及主Activity如下:

popupWindow布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" android:background="#FFF"><View android:layout_width="match_parent"android:layout_height="1dp"android:background="#f5f5f5"/><RelativeLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="10dp"><TextView
            android:id="@+id/tv_cancel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="取消"android:layout_marginLeft="10dp"android:layout_alignParentLeft="true"android:textColor="#000000"android:textSize="20sp" /><TextView
            android:id="@+id/tv_ok"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="确定"android:layout_marginRight="10dp"android:layout_alignParentRight="true"android:textColor="#000000"android:textSize="20sp" /></RelativeLayout><View android:layout_width="match_parent"android:layout_height="1dp"android:background="#f5f5f5"/><LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_marginTop="10dp"android:padding="20dp"><com.sxkeji.timeswitch.widget.DatePicker
            android:id="@+id/dp_test"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="3"android:gravity="center"android:layout_gravity="center_horizontal"/><com.sxkeji.timeswitch.widget.TimePicker
            android:id="@+id/tp_test"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="2"android:gravity="center"android:layout_gravity="center_horizontal"/></LinearLayout></LinearLayout>

主界面布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:background="#FFF"android:id="@+id/Rl_all"><LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:layout_alignParentBottom="true"android:padding="10dp"android:gravity="center"><View android:layout_width="match_parent"android:layout_height="1dp"android:background="#f5f5f5"/><Button android:id="@+id/btn_naozhong"android:layout_width="30dp"android:layout_height="30dp"android:background="@drawable/naozhong"/></LinearLayout>
</RelativeLayout>

Activity代码:

package com.sxkeji.timeswitch.activity;import java.util.Calendar;import org.unism.wang.R;import com.sxkeji.timeswitch.widget.DatePicker;
import com.sxkeji.timeswitch.widget.TimePicker;import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;/*** 主页面* @author sxzhang*/
public class MyPickerActivity extends Activity {private Calendar calendar;private DatePicker dp_test;private TimePicker tp_test;private TextView tv_ok,tv_cancel;   //确定、取消buttonprivate Button btn_naozhong;private PopupWindow pw;private String selectDate,selectTime;//选择时间与当前时间,用于判断用户选择的是否是以前的时间private int currentHour,currentMinute,currentDay,selectHour,selectMinute,selectDay;//整体布局private RelativeLayout Rl_all;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);Rl_all = (RelativeLayout) findViewById(R.id.Rl_all);btn_naozhong = (Button) findViewById(R.id.btn_naozhong);calendar = Calendar.getInstance();btn_naozhong.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {View view = View.inflate(MyPickerActivity.this, R.layout.dialog_select_time, null);selectDate = calendar.get(Calendar.YEAR) + "年" + calendar.get(Calendar.MONTH) + "月" + calendar.get(Calendar.DAY_OF_MONTH) + "日" + DatePicker.getDayOfWeekCN(calendar.get(Calendar.DAY_OF_WEEK));//选择时间与当前时间的初始化,用于判断用户选择的是否是以前的时间,如果是,弹出toss提示不能选择过去的时间selectDay = currentDay = calendar.get(Calendar.DAY_OF_MONTH);selectMinute = currentMinute = calendar.get(Calendar.MINUTE);selectHour = currentHour = calendar.get(Calendar.HOUR_OF_DAY);selectTime = currentHour + "点" + ((currentMinute < 10)?("0"+currentMinute):currentMinute) + "分";dp_test = (DatePicker)view.findViewById(R.id.dp_test);tp_test = (TimePicker)view.findViewById(R.id.tp_test);tv_ok = (TextView) view.findViewById(R.id.tv_ok);tv_cancel = (TextView) view.findViewById(R.id.tv_cancel);//设置滑动改变监听器dp_test.setOnChangeListener(dp_onchanghelistener);tp_test.setOnChangeListener(tp_onchanghelistener);pw = new PopupWindow(view, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, true);
//              //设置这2个使得点击pop以外区域可以去除pop
//              pw.setOutsideTouchable(true);
//              pw.setBackgroundDrawable(new BitmapDrawable());//出现在布局底端pw.showAtLocation(Rl_all, 0, 0,  Gravity.END);//点击确定tv_ok.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {if(selectDay == currentDay ){   //在当前日期情况下可能出现选中过去时间的情况if(selectHour < currentHour){Toast.makeText(getApplicationContext(), "不能选择过去的时间\n        请重新选择", 0).show();}else if( (selectHour == currentHour) && (selectMinute < currentMinute) ){Toast.makeText(getApplicationContext(), "不能选择过去的时间\n        请重新选择", 0).show();}else{Toast.makeText(getApplicationContext(), selectDate+selectTime, 0).show();pw.dismiss();}}else{Toast.makeText(getApplicationContext(), selectDate+selectTime, 0).show();pw.dismiss();}}});//点击取消tv_cancel.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {pw.dismiss();}});}});}//listenersDatePicker.OnChangeListener dp_onchanghelistener = new DatePicker.OnChangeListener() {@Overridepublic void onChange(int year, int month, int day, int day_of_week) {selectDay = day;selectDate = year + "年" + month + "月" + day + "日" + DatePicker.getDayOfWeekCN(day_of_week);}};TimePicker.OnChangeListener tp_onchanghelistener = new TimePicker.OnChangeListener() {@Overridepublic void onChange(int hour, int minute) {selectTime = hour + "点" + ((minute < 10)?("0"+minute):minute) + "分";selectHour = hour;selectMinute = minute;}};
}

最终效果图:

完整demo下载地址

Android基于wheelView的自定义日期选择器(可拓展样式)相关推荐

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

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

  2. 《Android开发卷——自定义日期选择器(三)》

                 继 <Android开发卷--自定义日期选择器(一)>:http://blog.csdn.net/chillax_li/article/details/19047 ...

  3. 《Android开发卷——自定义日期选择器(二)》

    (小米手机) (中兴手机) 在上一篇中,我介绍了一般公司都会自定义时间日期选择器,并结合自己所做的项目给大家参考. 工作实录之<Android开发卷--自定义日期选择器(一)>链接:htt ...

  4. html5 自定义 datepicker,如何使用 React 构建自定义日期选择器(3)

    本文作者:IMWeb howenhuo 未经同意,禁止转载 Datepicker 组件 构建 Datepicker 组件 要开始构建 Datepicker 组件,请将以下代码片段添加到 src/com ...

  5. Android自己定义DataTimePicker(日期选择器)

    Android自己定义DataTimePicker(日期选择器)  笔者有一段时间没有发表关于Android的文章了,关于Android自己定义组件笔者有好几篇想跟大家分享的,后期会记录在博客中.本篇 ...

  6. antd 日期时间选择_【UI设计】日期选择器的常见样式总结

    来源:海盐社(haiyans7) 作者:青山 在使用各种 APP 的过程中,我们经常会遇到选择日期的场景,比如记账的时候.安排行程的时候.购买车票以及预订酒店的时候.有时我们需要选择一个日期,有时则需 ...

  7. android简单易上手的日期选择器DatePicker

    今天尝试自己动手做一个日期选择器          1.在布局文件中添加DatePicker ... <DatePickerandroid:layout_width="match_pa ...

  8. 【iOS】自定义日期选择器

    自定义了一个日期选择器,与大家分享一下,期待宝贵建议. github下载地址:https://github.com/huahua0809/XHDatePicker 下面只是说明一下怎么用,具体实现请下 ...

  9. html原生时间选择框,HTML5日期选择器有任何样式选项吗?

    WebKit提供以下八个伪元素,用于自定义日期输入的文本框: ::-webkit-datetime-edit ::-webkit-datetime-edit-fields-wrapper ::-web ...

最新文章

  1. dmalloc 原文 翻译整理
  2. 1.3 Java类的属性:成员变量的定义和声明
  3. [导入]浅谈VB.NET中的接口
  4. OpenGL 漫反射辐照度 Diffuse irradiance
  5. yum源yum-fastestmirror
  6. Linux下SVN服务器的搭建
  7. MSSQL系列之十五 全文索引
  8. PRIMARY, INDEX, UNIQUE 这3种是一类
  9. Java面试之JVM参数调优
  10. 最爱的城市(dfs)
  11. 跨多个交换机VLAN的配置方案设计(H3C)
  12. 要买多少路由器? 水题.
  13. 三菱触摸屏通讯错误_三菱触摸屏(人机界面)常见问题解析
  14. oracle修改dbf文件,如何修改Oracle的dbf文件位置
  15. 获取计算机用户名称的方法,javascript读取用户名和计算机名
  16. 已知销售额怎么计算成本_计算成本根据销售额怎么样推算出成本,举例, – 手机爱问...
  17. 小程序快递单号查询接口物流助手对接指南
  18. android 微信架构,微信App支付技术架构全解析
  19. 5月27日 | 极客俱乐部:集成平台赋能业务流程再造与创新
  20. linux 主流浏览器,各主流浏览器(PC、移动端)userAgent属性信息介绍

热门文章

  1. 【数据结构】队列的 增,删,查,改 的实现
  2. 或许对你有帮助的一个独立游戏团队的2015创业总结
  3. 如何开始使用Word2Vec-然后使其工作
  4. noj21逆波兰表达式
  5. NTC温度传感器 (含arduino程序)(公式解算版)(终极)
  6. AlertDialog获取网上天气并显示各城市天气
  7. Buffer I/O error on dev故障数据库恢复---惜分飞
  8. 不root怎么将FDex2反编译的dex文件拷出来
  9. 小鼠脑立体定位图谱_探索从未止步!瑞沃德首款国产电动脑立体定位仪发布
  10. The Path to Learning WR Python FPE.10