Skip to content

Instantly share code, notes, and snippets.

@Augusent
Last active May 17, 2017 18:28
Show Gist options
  • Save Augusent/fb6f7a4c99f39288e08d31d8a635471a to your computer and use it in GitHub Desktop.
Save Augusent/fb6f7a4c99f39288e08d31d8a635471a to your computer and use it in GitHub Desktop.
/* 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