热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android基于wheelView实现自定义日期选择器

这篇文章主要为大家详细介绍了Android基于wheelView实现自定义日期选择器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Android实现自定义日期选择器的具体代码,供大家参考,具体内容如下

项目要求效果图:

要求 “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;
  }else
  this.hour = hour2;
  this.listItem = this.hour + "时";
 }else if(isHourType == false && minute2 != -1){ //设置分钟
  if(minute2 > 60)
  this.minute = minute2 % 60;
  else
  this.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;

 // items
 private ArrayList list;

 // length
 private int length;

 /**
 * Constructor
 * @param items the items
 * @param length the max items length
 */
 public StringWheelAdapter(ArrayList list, int length) {
 this.list = list;
 this.length = length;
 }


 @Override
 public String getItem(int index) {
 if (index >= 0 && index 

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

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 dateList ;
 private OnChangeListener onChangeListener; //onChangeListener
 private final int MARGIN_RIGHT = 20;
 private DateObject dateObject; //日期数据对象
 //Constructors
 public 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();
 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(){
 @Override
 public 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;
 }


 @Override
 protected 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 picker
 private OnChangeListener onChangeListener; //onChangeListener
 private final int MARGIN_RIGHT = 15; //调整文字右端距离
 private ArrayList hourList,minuteList;
 private DateObject dateObject; //时间数据对象
 //Constructors
 public 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();
 minuteList = new ArrayList();

 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); 
 }

 

 //listeners
 private OnWheelChangedListener OnHoursChangedListener= new OnWheelChangedListener(){
 @Override
 public void onChanged(WheelView hours, int oldValue, int newValue) {
  calendar.set(Calendar.HOUR_OF_DAY, newValue);
  change();
 }
 };
 private OnWheelChangedListener OnMinsChangedListener= new OnWheelChangedListener(){
 @Override
 public 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();
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 }
}

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

popupWindow布局文件:

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 
 
 

 

 
 
 
  

 
 


主界面布局文件:

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 
 
 

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; //确定、取消button
 private Button btn_naozhong;
 private PopupWindow pw;
 private String selectDate,selectTime;
 //选择时间与当前时间,用于判断用户选择的是否是以前的时间
 private int currentHour,currentMinute,currentDay,selectHour,selectMinute,selectDay;
 //整体布局
 private RelativeLayout Rl_all;
 @Override
 protected 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() {
  @Override
  public 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)&#63;("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() {
   @Override
   public void onClick(View arg0) {
   if(selectDay == currentDay ){ //在当前日期情况下可能出现选中过去时间的情况
    if(selectHour 

最终效果图:

源码下载:Android实现自定义日期选择器

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 本文是关于自学Android的笔记,包括查看类的源码的方法,活动注册的必要性以及布局练习的重要性。通过学习本文,读者可以了解到在自学Android过程中的一些关键点和注意事项。 ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
  • 本文介绍了互联网思维中的三个段子,涵盖了餐饮行业、淘品牌和创业企业的案例。通过这些案例,探讨了互联网思维的九大分类和十九条法则。其中包括雕爷牛腩餐厅的成功经验,三只松鼠淘品牌的包装策略以及一家创业企业的销售额增长情况。这些案例展示了互联网思维在不同领域的应用和成功之道。 ... [详细]
  • 基于移动平台的会展导游系统APP设计与实现的技术介绍与需求分析
    本文介绍了基于移动平台的会展导游系统APP的设计与实现过程。首先,对会展经济和移动互联网的概念进行了简要介绍,并阐述了将会展引入移动互联网的意义。接着,对基础技术进行了介绍,包括百度云开发环境、安卓系统和近场通讯技术。然后,进行了用户需求分析和系统需求分析,并提出了系统界面运行流畅和第三方授权等需求。最后,对系统的概要设计进行了详细阐述,包括系统前端设计和交互与原型设计。本文对基于移动平台的会展导游系统APP的设计与实现提供了技术支持和需求分析。 ... [详细]
author-avatar
mobiledu2502929447
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有