Last active
May 17, 2017 18:28
-
-
Save Augusent/fb6f7a4c99f39288e08d31d8a635471a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Attributes | |
<declare-styleable name="DateTimePickerView"> | |
<attr name="timeHourOfDay" format="integer"/> | |
<attr name="timeMinute" format="integer"/> | |
<attr name="timeFormat" format="string"/> | |
<attr name="timeType" format="enum"> | |
<enum name="time" value="0"/> | |
<enum name="date" value="1"/> | |
</attr> | |
<attr name="timePlaceholder" format="string"/> | |
</declare-styleable> | |
*/ | |
@BindingMethods({ | |
@BindingMethod(type = DateTimePickerView.class, attribute = "timeHourOfDay", method = "setHourOfDay"), | |
@BindingMethod(type = DateTimePickerView.class, attribute = "timeMinute", method = "setMinute"), | |
@BindingMethod(type = DateTimePickerView.class, attribute = "timeDate", method = "setDate") | |
}) | |
@InverseBindingMethods({ | |
@InverseBindingMethod(type = DateTimePickerView.class, attribute = "timeHourOfDay", method = "getHourOfDay"), | |
@InverseBindingMethod(type = DateTimePickerView.class, attribute = "timeMinute", method = "getMinute"), | |
@InverseBindingMethod(type = DateTimePickerView.class, attribute = "timeDate", method = "getDate") | |
}) | |
public class DateTimePickerView extends TextView implements View.OnClickListener, TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener { | |
private static final int TYPE_TIME = 0; | |
private static final int TYPE_DATE = 1; | |
private int hourOfDay; | |
private int minute; | |
private String timeFormat; | |
private String placeholder; | |
private Calendar date; | |
private int type; | |
private SimpleDateFormat simpleDateFormat; | |
private OnTimeChangedListener timeChangedListener; | |
private OnDateChangedListener dateChangedListener; | |
public DateTimePickerView(Context context) { | |
super(context); | |
init(context, null); | |
} | |
public DateTimePickerView(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
init(context, attrs); | |
} | |
@BindingAdapter(value = {"app:timeHourOfDayAttrChanged", "app:timeMinuteAttrChanged", "bind:timeDateAttrChanged"}, requireAll = false) | |
public static void time(DateTimePickerView view, | |
InverseBindingListener hourChanged, | |
InverseBindingListener minChanged, | |
InverseBindingListener dateChanged) { | |
view.setTimeChangedListener((h, m) -> { | |
hourChanged.onChange(); | |
minChanged.onChange(); | |
}); | |
view.setDateChangedListener(date -> dateChanged.onChange()); | |
} | |
private void init(Context context, AttributeSet attrs) { | |
if (attrs != null) { | |
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DateTimePickerView); | |
hourOfDay = a.getInteger(R.styleable.DateTimePickerView_timeHourOfDay, -1); | |
minute = a.getInteger(R.styleable.DateTimePickerView_timeMinute, -1); | |
timeFormat = a.getString(R.styleable.DateTimePickerView_timeFormat); | |
type = a.getInt(R.styleable.DateTimePickerView_timeType, TYPE_TIME); | |
placeholder = a.getString(R.styleable.DateTimePickerView_timePlaceholder); | |
a.recycle(); | |
} | |
if (hourOfDay > 23) { | |
throw new IllegalArgumentException("Hour must be from 0 to 23"); | |
} | |
if (minute > 59) { | |
throw new IllegalArgumentException("Minute must be from 0 to 59"); | |
} | |
if (timeFormat != null) { | |
simpleDateFormat = new SimpleDateFormat(timeFormat, Locale.getDefault()); | |
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); | |
} | |
setText(getTime()); | |
setOnClickListener(this); | |
} | |
public int getHourOfDay() { | |
return hourOfDay; | |
} | |
public void setHourOfDay(int hourOfDay) { | |
this.hourOfDay = hourOfDay; | |
setText(getTime()); | |
} | |
public int getMinute() { | |
return minute; | |
} | |
public void setMinute(int minute) { | |
this.minute = minute; | |
setText(getTime()); | |
} | |
public Date getDate() { | |
return date == null ? null : date.getTime(); | |
} | |
public void setDate(@Nullable Date date) { | |
if (date == null) { | |
setText(getTime()); | |
return; | |
} | |
if (this.date == null) { | |
this.date = Calendar.getInstance(); | |
} | |
this.date.setTime(date); | |
setText(getTime()); | |
} | |
public String getTime() { | |
if (this.type == TYPE_TIME) { | |
if (hourOfDay < 0 || minute < 0) return placeholder; | |
final Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT")); | |
date.set(Calendar.HOUR_OF_DAY, hourOfDay); | |
date.set(Calendar.MINUTE, minute); | |
return simpleDateFormat == null | |
? DateUtils.getFormattedTimeOfDay(date.getTime()) | |
: simpleDateFormat.format(date.getTime()); | |
} else if (this.type == TYPE_DATE) { | |
if (date == null) return placeholder; | |
return simpleDateFormat == null | |
? DateUtils.getFormattedDate(date.getTime()) | |
: simpleDateFormat.format(date.getTime()); | |
} else throw new IllegalStateException("Wrong type"); | |
} | |
@Override | |
public void onClick(View v) { | |
switch (type) { | |
case TYPE_TIME: | |
new TimePickerDialog(v.getContext(), this, | |
hourOfDay < 0 ? 12 : hourOfDay, | |
minute < 0 ? 0 : minute, true) | |
.show(); | |
break; | |
case TYPE_DATE: | |
date = date == null ? Calendar.getInstance() : date; | |
new DatePickerDialog(v.getContext(), this, | |
date.get(Calendar.YEAR), | |
date.get(Calendar.MONTH), | |
date.get(Calendar.DAY_OF_MONTH)) | |
.show(); | |
break; | |
default: | |
throw new IllegalStateException("Wrong type. Type should be time or date"); | |
} | |
} | |
@Override | |
public void onTimeSet(TimePicker view, int hourOfDay, int minute) { | |
this.hourOfDay = hourOfDay; | |
this.minute = minute; | |
setText(getTime()); | |
if (timeChangedListener != null) { | |
timeChangedListener.onTimeChanged(hourOfDay, minute); | |
} | |
} | |
@Override | |
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) { | |
this.date.set(Calendar.YEAR, year); | |
this.date.set(Calendar.MONTH, month); | |
this.date.set(Calendar.DAY_OF_MONTH, dayOfMonth); | |
setText(getTime()); | |
if (dateChangedListener != null) { | |
dateChangedListener.onDateChanged(this.date.getTime()); | |
} | |
} | |
public void setTimeChangedListener(OnTimeChangedListener timeChangedListener) { | |
this.timeChangedListener = timeChangedListener; | |
} | |
public void setDateChangedListener(OnDateChangedListener dateChangedListener) { | |
this.dateChangedListener = dateChangedListener; | |
} | |
public String getPlaceholder() { | |
return placeholder; | |
} | |
public void setPlaceholder(String placeholder) { | |
this.placeholder = placeholder; | |
setText(getTime()); | |
} | |
public interface OnTimeChangedListener { | |
void onTimeChanged(int hourOfDay, int minute); | |
} | |
public interface OnDateChangedListener { | |
void onDateChanged(Date date); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment