package com.parttime.widget;
import android.content.Context;
import android.util.Log;
import com.parttime.widget.wheel.WheelView;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
/**
* 公共时间选择器
* 支持年、月、日、时、分自由组合选择。
* 可对年份上下限和分钟间隔进行设定。
*
* Created by wyw on 2015/6/3.
*/
public class TimeWheelDialog extends WheelDialog {
private enum FlagType {
YEAR, MONTH, DATE, HOUR, MINUTE;
}
/**
* 可选年
*/
public static final int FLAG_YEAR = 1 << 5;
/**
* 可选月
*/
public static final int FLAG_MONTH = 1 << 4;
/**
* 可选日
*/
public static final int FLAG_DATE = 1 << 3;
/**
* 可选小时
*/
public static final int FLAG_HOUR = 1 << 2;
/**
* 可选分钟
*/
public static final int FLAG_MINUTE = 1 << 1;
private boolean showYear;
private boolean showMonth;
private boolean showDate;
private boolean showHour;
private boolean showMinute;
private Calendar current;
private List<String> yearList = new ArrayList<>();
private List<String> monthList = new ArrayList<>();
private List<String> dateList = new ArrayList<>();
private List<String> hourList = new ArrayList<>();
private List<String> minuteList = new ArrayList<>();
private List<FlagType> posTypeMap = new ArrayList<>();
private List<Integer> currentPosMap = new ArrayList<>();
private int beginYear;
private int endYear;
/**
* 分钟的时间间隔(只有当FLAG_MINUTE有值时有效,默认为1分钟)
*/
private int timespan = 1;
private TimeWheelDialog(Context context, String[]... txts) {
super(context, txts);
}
/**
* 构造函数(分钟间隔默认为1,不循环显示,年份范围默认是当前年前后50年)
*
* @param context
* @param flags 时间选择器类型,多个FLAG用|相隔(如选择时分,FLAG_HOUR|FLAG_MINUTE)
* @param currentCalendar 当前时间的Calendar
*/
public TimeWheelDialog(Context context, int flags, Calendar currentCalendar) {
this(context, flags, currentCalendar, false);
}
/**
* 构造函数(分钟间隔默认为1,年份范围默认是当前年前后50年)
*
* @param context
* @param flags 时间选择器类型,多个FLAG用|相隔(如选择时分,FLAG_HOUR|FLAG_MINUTE)
* @param currentCalendar 当前时间的Calendar
* @param isCycle 是否循环显示
*/
public TimeWheelDialog(Context context, int flags, Calendar currentCalendar, boolean isCycle) {
this(context, flags, currentCalendar, isCycle, 1);
}
/**
* 构造函数(年份范围默认是当前年前后50年)
*
* @param context
* @param flags 时间选择器类型,多个FLAG用|相隔(如选择时分,FLAG_HOUR|FLAG_MINUTE)
* @param currentCalendar 当前时间的Calendar
* @param isCycle 是否可以循环显示
* @param timespan 分钟间隔
*/
public TimeWheelDialog(Context context, int flags, Calendar currentCalendar, boolean isCycle, int timespan) {
this(context, flags, currentCalendar, isCycle, timespan, 0, 0);
}
/**
* 构造函数
*
* @param context
* @param flags 时间选择器类型,多个FLAG用|相隔(如选择时分,FLAG_HOUR|FLAG_MINUTE)
* @param currentCalendar 当前时间的Calendar
* @param isCycle 是否可以循环显示
* @param timespan 分钟间隔
* @param beginYear 起始年(设置了FLAG_YEAR 有效)
* @param endYear 终止年(设置了FLAG_YEAR 有效)
*/
public TimeWheelDialog(Context context, int flags, Calendar currentCalendar, boolean isCycle, int timespan, int beginYear, int endYear) {
this(context, new String[]{});
setCycle(isCycle);
this.timespan = timespan;
initShow(flags);
current = currentCalendar;
if (beginYear == 0) {
beginYear = Calendar.getInstance(currentCalendar.getTimeZone()).get(Calendar.YEAR) - 50;
}
this.beginYear = beginYear;
if (endYear == 0) {
endYear = Calendar.getInstance(currentCalendar.getTimeZone()).get(Calendar.YEAR) + 49;
}
this.endYear = endYear;
resetWheels();
}
private void initShow(int flags) {
showYear = false;
if ((flags & FLAG_YEAR) == FLAG_YEAR) {
showYear = true;
}
showMonth = false;
if ((flags & FLAG_MONTH) == FLAG_MONTH) {
showMonth = true;
}
showDate = false;
if ((flags & FLAG_DATE) == FLAG_DATE) {
showDate = true;
}
showHour = false;
if ((flags & FLAG_HOUR) == FLAG_HOUR) {
showHour = true;
}
showMinute = false;
if ((flags & FLAG_MINUTE) == FLAG_MINUTE) {
showMinute = true;
}
}
private void resetWheels() {
currentPosMap.clear();
posTypeMap.clear();
List<String[]> dataList = new ArrayList<>();
if (showYear) {
int currentYear = current.get(Calendar.YEAR);
yearList = new ArrayList<>();
for (int i = beginYear; i <= endYear; ++i) {
if (i == currentYear) {
currentPosMap.add(i - beginYear);
}
yearList.add(String.valueOf(i));
}
posTypeMap.add(FlagType.YEAR);
String[] yearArray = new String[yearList.size()];
yearList.toArray(yearArray);
dataList.add(yearArray);
}
if (showMonth) {
int currentMonth = current.get(Calendar.MONTH) + 1;
monthList = new ArrayList<>();
for (int i = 1; i <= 12; ++i) {
if (i == currentMonth) {
currentPosMap.add(i - 1);
}
monthList.add(String.valueOf(i));
}
posTypeMap.add(FlagType.MONTH);
String[] monthArray = new String[monthList.size()];
monthList.toArray(monthArray);
dataList.add(monthArray);
}
if (showDate) {
int currentDate = current.get(Calendar.DATE);
int dayOfMonth = getDateInMonth(current);
dateList = new ArrayList<>();
for (int i = 1; i <= dayOfMonth; ++i) {
if (i == currentDate) {
currentPosMap.add(i - 1);
}
dateList.add(String.valueOf(i));
}
posTypeMap.add(FlagType.DATE);
String[] dateArray = new String[dateList.size()];
dateList.toArray(dateArray);
dataList.add(dateArray);
}
if (showHour) {
int currentHour = current.get(Calendar.HOUR_OF_DAY);
hourList = new ArrayList<>();
for (int i = 0; i <= 23; ++i) {
if (i == currentHour) {
currentPosMap.add(i);
}
hourList.add(String.valueOf(i));
}
posTypeMap.add(FlagType.HOUR);
String[] hourArray = new String[hourList.size()];
hourList.toArray(hourArray);
dataList.add(hourArray);
}
if (showMinute) {
int currentMinute = current.get(Calendar.MINUTE);
currentMinute = (int) (this.timespan * Math.round((double) currentMinute / this.timespan));
current.set(Calendar.MINUTE, currentMinute);
minuteList = new ArrayList<>();
for (int i = 0; i < 60 / this.timespan; ++i) {
int tick = this.timespan * i;
if (currentMinute == tick) {
currentPosMap.add(i);
}
minuteList.add(String.valueOf(tick));
}
posTypeMap.add(FlagType.MINUTE);
String[] minuteArray = new String[minuteList.size()];
minuteList.toArray(minuteArray);
dataList.add(minuteArray);
}
String[][] marrayData = new String[dataList.size()][];
FlagType[] posTypeArray = new FlagType[posTypeMap.size()];
posTypeMap.toArray(posTypeArray);
int[] currentPosArray = new int[currentPosMap.size()];
for (int i = 0; i < currentPosMap.size(); i++) {
currentPosArray[i] = currentPosMap.get(i);
}
attachWheels(posTypeArray, dataList.toArray(marrayData));
setCurrentPosition(currentPosArray);
for (WheelView wheel : wheels) {
wheel.addChangingListener(this);
}
}
private void resetDateWheel() {
if (showDate) {
List<FlagType> posTypeMap = new ArrayList<>();
List<Integer> currentPosMap = new ArrayList<>();
List<String[]> dataList = new ArrayList<>();
int currentDate = current.get(Calendar.DATE);
int dayOfMonth = getDateInMonth(current);
dateList = new ArrayList<>();
for (int i = 1; i <= dayOfMonth; ++i) {
if (i == currentDate) {
currentPosMap.add(i - 1);
}
dateList.add(String.valueOf(i));
}
posTypeMap.add(FlagType.DATE);
String[] dateArray = new String[dateList.size()];
dateList.toArray(dateArray);
dataList.add(dateArray);
String[][] marrayData = new String[dataList.size()][];
FlagType[] posTypeArray = new FlagType[posTypeMap.size()];
posTypeMap.toArray(posTypeArray);
int currentPos = 0;
for (int i = 0; i < currentPosMap.size(); i++) {
currentPos = currentPosMap.get(i);
}
resetWheels(posTypeArray, dataList.toArray(marrayData));
for(int i = 0; i < wheels.length; ++i){
if (wheels[i].getTag() == FlagType.DATE) {
wheels[i].setCurrentItem(currentPos, false);
}
}
}
}
@Override
protected void onOk() {
int count = wheels.length;
int[] pos = new int[count];
for(int i = 0 ; i < count; ++i){
pos[i] = wheels[i].getCurrentItem();
}
if(onSubmitListener != null){
onSubmitListener.onSubmit(pos);
} else {
dismiss();
}
// dismiss();
}
@Override
public void onChanged(WheelView wheel, int oldValue, int newValue) {
super.onChanged(wheel, oldValue, newValue);
FlagType flagType = (FlagType) wheel.getTag();
Log.i("TimeWheelDialog", "flagType: " + flagType + "; oldValue: " + oldValue + "; newValue: " + newValue);
try {
switch (flagType) {
case YEAR:
int rollValue = Integer.valueOf(yearList.get(newValue)) - Integer.valueOf(yearList.get(oldValue));
current.roll(Calendar.YEAR, rollValue);
resetDateWheel();
break;
case MONTH:
rollValue = Integer.valueOf(monthList.get(newValue)) - Integer.valueOf(monthList.get(oldValue));
current.roll(Calendar.MONTH, rollValue);
resetDateWheel();
break;
case DATE:
oldValue = oldValue >= dateList.size() ? dateList.size() - 1 : oldValue;
rollValue = Integer.valueOf(dateList.get(newValue)) - Integer.valueOf(dateList.get(oldValue));
current.roll(Calendar.DATE, rollValue);
break;
case HOUR:
rollValue = Integer.valueOf(hourList.get(newValue)) - Integer.valueOf(hourList.get(oldValue));
current.roll(Calendar.HOUR_OF_DAY, rollValue);
break;
case MINUTE:
rollValue = Integer.valueOf(minuteList.get(newValue)) - Integer.valueOf(minuteList.get(oldValue));
current.roll(Calendar.MINUTE, rollValue);
break;
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
private int getDateInMonth(Calendar c) {
Calendar temp = Calendar.getInstance(c.getTimeZone());
temp.setTimeInMillis(c.getTimeInMillis());
temp.set(Calendar.DATE, 1);
temp.roll(Calendar.DATE, -1);
return temp.get(Calendar.DATE);
}
/**
* 获取当前时间
*
* @return
*/
public Calendar getTime() {
return current;
}
}