Closed mofada closed 5 years ago
No, I don't, I use other .
I could achieve. I have created my own version of time picker with my layout but using library components. In my case I need month-day-year.
import android.content.Context
import android.text.format.DateFormat
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import com.github.florent37.singledateandtimepicker.DateHelper
import com.github.florent37.singledateandtimepicker.widget.WheelAmPmPicker
import com.github.florent37.singledateandtimepicker.widget.WheelDayOfMonthPicker
import com.github.florent37.singledateandtimepicker.widget.WheelDayPicker
import com.github.florent37.singledateandtimepicker.widget.WheelHourPicker
import com.github.florent37.singledateandtimepicker.widget.WheelMinutePicker
import com.github.florent37.singledateandtimepicker.widget.WheelMonthPicker
import com.github.florent37.singledateandtimepicker.widget.WheelPicker
import com.github.florent37.singledateandtimepicker.widget.WheelYearPicker
import org.allinahealth.cv.R
import java.text.SimpleDateFormat
import java.util.ArrayList
import java.util.Calendar
import java.util.Date
import java.util.Locale
class CustomSingleDateAndTimePicker : LinearLayout {
companion object {
const val IS_CYCLIC_DEFAULT = true
const val IS_CURVED_DEFAULT = false
const val MUST_BE_ON_FUTUR_DEFAULT = false
const val DELAY_BEFORE_CHECK_PAST = 200
const val VISIBLE_ITEM_COUNT_DEFAULT = 7
const val PM_HOUR_ADDITION = 12
const val FORMAT_24_HOUR = "EEE d MMM H:mm"
const val FORMAT_12_HOUR = "EEE d MMM h:mm a"
}
private var yearsPicker: WheelYearPicker
private var monthPicker: WheelMonthPicker
private var daysOfMonthPicker: WheelDayOfMonthPicker
private var daysPicker: WheelDayPicker
private var minutesPicker: WheelMinutePicker
private var hoursPicker: WheelHourPicker
private var amPmPicker: WheelAmPmPicker
private val pickers = ArrayList<WheelPicker<*>>()
private val listeners = ArrayList<OnDateChangedListener>()
private var dtSelector: View
private var mustBeOnFuture: Boolean = false
private var minDate: Date? = null
private var maxDate: Date? = null
private var defaultDate: Date
private var displayYears = false
private var displayMonth = false
private var displayDaysOfMonth = false
private var displayDays = true
private var displayMinutes = true
private var displayHours = true
private var isAmPm: Boolean = false
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
defaultDate = Date()
isAmPm = !DateFormat.is24HourFormat(context)
View.inflate(context, R.layout.single_day_picker, this)
yearsPicker = findViewById(R.id.yearPicker)
monthPicker = findViewById(R.id.monthPicker)
daysOfMonthPicker = findViewById(R.id.daysOfMonthPicker)
daysPicker = findViewById(R.id.daysPicker)
minutesPicker = findViewById(R.id.minutesPicker)
hoursPicker = findViewById(R.id.hoursPicker)
amPmPicker = findViewById(R.id.amPmPicker)
dtSelector = findViewById(R.id.dtSelector)
pickers.addAll(listOf(daysPicker, minutesPicker, hoursPicker, amPmPicker, daysOfMonthPicker, monthPicker, yearsPicker))
init(context, attrs)
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
yearsPicker.setOnYearSelectedListener { picker, position, year ->
updateListener()
checkMinMaxDate(picker)
if (displayDaysOfMonth) {
updateDaysOfMonth()
}
}
monthPicker.setOnMonthSelectedListener { picker, monthIndex, monthName ->
updateListener()
checkMinMaxDate(picker)
if (displayDaysOfMonth) {
updateDaysOfMonth()
}
}
daysOfMonthPicker
.setDayOfMonthSelectedListener { picker, dayIndex ->
updateListener()
checkMinMaxDate(picker)
}
daysOfMonthPicker
.setOnFinishedLoopListener {
if (displayMonth) {
monthPicker.scrollTo(monthPicker.currentItemPosition + 1)
updateDaysOfMonth()
}
}
daysPicker
.setOnDaySelectedListener { picker, position, name, date ->
updateListener()
checkMinMaxDate(picker)
}
minutesPicker
.setOnMinuteChangedListener { picker, minutes ->
updateListener()
checkMinMaxDate(picker)
}
.setOnFinishedLoopListener { hoursPicker.scrollTo(hoursPicker.currentItemPosition + 1) }
hoursPicker
.setOnFinishedLoopListener { daysPicker.scrollTo(daysPicker.currentItemPosition + 1) }
.setHourChangedListener { picker, hour ->
updateListener()
checkMinMaxDate(picker)
}
amPmPicker
.setAmPmListener { picker, isAm ->
updateListener()
checkMinMaxDate(picker)
}
setDefaultDate(this.defaultDate) // update displayed date
}
override fun setEnabled(enabled: Boolean) {
super.setEnabled(enabled)
for (picker in pickers) {
picker.isEnabled = enabled
}
}
fun setDisplayYears(displayYears: Boolean) {
this.displayYears = displayYears
yearsPicker.visibility = if (displayYears) View.VISIBLE else View.GONE
}
fun setDisplayMonths(displayMonths: Boolean) {
this.displayMonth = displayMonths
monthPicker.visibility = if (displayMonths) View.VISIBLE else View.GONE
checkSettings()
}
fun setDisplayDaysOfMonth(displayDaysOfMonth: Boolean) {
this.displayDaysOfMonth = displayDaysOfMonth
daysOfMonthPicker.visibility = if (displayDaysOfMonth) View.VISIBLE else View.GONE
if (displayDaysOfMonth) {
updateDaysOfMonth()
}
checkSettings()
}
fun setDisplayDays(displayDays: Boolean) {
this.displayDays = displayDays
daysPicker.visibility = if (displayDays) View.VISIBLE else View.GONE
checkSettings()
}
fun setDisplayMinutes(displayMinutes: Boolean) {
this.displayMinutes = displayMinutes
minutesPicker.visibility = if (displayMinutes) View.VISIBLE else View.GONE
}
fun setDisplayHours(displayHours: Boolean) {
this.displayHours = displayHours
hoursPicker.visibility = if (displayHours) View.VISIBLE else View.GONE
setIsAmPm(this.isAmPm)
hoursPicker.setIsAmPm(isAmPm)
}
fun setDisplayMonthNumbers(displayMonthNumbers: Boolean) {
this.monthPicker.setDisplayMonthNumbers(displayMonthNumbers)
this.monthPicker.updateAdapter()
}
fun setTodayText(todayText: String?) {
if (todayText != null && !todayText.isEmpty()) {
daysPicker.setTodayText(todayText)
}
}
fun setCurved(curved: Boolean) {
for (picker in pickers) {
picker.isCurved = curved
}
}
fun setCyclic(cyclic: Boolean) {
for (picker in pickers) {
picker.isCyclic = cyclic
}
}
fun setTextSize(textSize: Int) {
for (picker in pickers) {
picker.itemTextSize = textSize
}
}
fun setSelectedTextColor(selectedTextColor: Int) {
for (picker in pickers) {
picker.selectedItemTextColor = selectedTextColor
}
}
fun setTextColor(textColor: Int) {
for (picker in pickers) {
picker.itemTextColor = textColor
}
}
fun setSelectorColor(selectorColor: Int) {
dtSelector.setBackgroundColor(selectorColor)
}
fun setSelectorHeight(selectorHeight: Int) {
val dtSelectorLayoutParams = dtSelector.layoutParams
dtSelectorLayoutParams.height = selectorHeight
dtSelector.layoutParams = dtSelectorLayoutParams
}
fun setVisibleItemCount(visibleItemCount: Int) {
for (picker in pickers) {
picker.visibleItemCount = visibleItemCount
}
}
fun setIsAmPm(isAmPm: Boolean) {
this.isAmPm = isAmPm
amPmPicker.visibility = if (isAmPm && displayHours) View.VISIBLE else View.GONE
hoursPicker.setIsAmPm(isAmPm)
}
fun isAmPm(): Boolean {
return isAmPm
}
fun setDayFormatter(simpleDateFormat: SimpleDateFormat?) {
if (simpleDateFormat != null) {
this.daysPicker.setDayFormatter(simpleDateFormat)
}
}
fun getMinDate(): Date? {
return minDate
}
fun setMinDate(minDate: Date) {
this.minDate = minDate
setMinYear()
}
fun getMaxDate(): Date? {
return maxDate
}
fun setMaxDate(maxDate: Date) {
this.maxDate = maxDate
setMinYear()
}
fun setCustomLocale(locale: Locale) {
for (p in pickers) {
p.setCustomLocale(locale)
p.updateAdapter()
}
}
private fun checkMinMaxDate(picker: WheelPicker<*>) {
checkBeforeMinDate(picker)
checkAfterMaxDate(picker)
}
private fun checkBeforeMinDate(picker: WheelPicker<*>) {
picker.postDelayed({
if (minDate != null && isBeforeMinDate(getDate())) {
for (p in pickers) {
p.scrollTo(p.findIndexOfDate(minDate!!))
}
}
}, DELAY_BEFORE_CHECK_PAST.toLong())
}
private fun checkAfterMaxDate(picker: WheelPicker<*>) {
picker.postDelayed({
if (maxDate != null && isAfterMaxDate(getDate())) {
for (p in pickers) {
p.scrollTo(p.findIndexOfDate(maxDate!!))
}
}
}, DELAY_BEFORE_CHECK_PAST.toLong())
}
private fun isBeforeMinDate(date: Date): Boolean {
return DateHelper.getCalendarOfDate(date).before(DateHelper.getCalendarOfDate(minDate))
}
private fun isAfterMaxDate(date: Date): Boolean {
return DateHelper.getCalendarOfDate(date).after(DateHelper.getCalendarOfDate(maxDate))
}
fun addOnDateChangedListener(listener: OnDateChangedListener) {
this.listeners.add(listener)
}
fun removeOnDateChangedListener(listener: OnDateChangedListener) {
this.listeners.remove(listener)
}
fun checkPickersMinMax() {
for (picker in pickers) {
checkMinMaxDate(picker)
}
}
fun getDate(): Date {
var hour = hoursPicker.currentHour
if (isAmPm && amPmPicker.isPm) {
hour += PM_HOUR_ADDITION
}
val minute = minutesPicker.currentMinute
val calendar = Calendar.getInstance()
if (displayDays) {
val dayDate = daysPicker.currentDate
calendar.time = dayDate
} else {
if (displayMonth) {
calendar.set(Calendar.MONTH, monthPicker.currentMonth)
}
if (displayYears) {
calendar.set(Calendar.YEAR, yearsPicker.currentYear)
}
if (displayDaysOfMonth) {
val daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH)
if (daysOfMonthPicker.currentDay >= daysInMonth) {
calendar.set(Calendar.DAY_OF_MONTH, daysInMonth)
} else {
calendar.set(Calendar.DAY_OF_MONTH, daysOfMonthPicker.currentDay + 1)
}
}
}
calendar.set(Calendar.HOUR_OF_DAY, hour)
calendar.set(Calendar.MINUTE, minute)
return calendar.time
}
fun setStepMinutes(minutesStep: Int) {
minutesPicker.setStepMinutes(minutesStep)
}
fun setHoursStep(hoursStep: Int) {
hoursPicker.setHoursStep(hoursStep)
}
fun setDefaultDate(date: Date?) {
if (date != null) {
this.defaultDate = date
updateDaysOfMonth()
for (picker in pickers) {
picker.setDefaultDate(defaultDate)
}
}
}
fun selectDate(calendar: Calendar?) {
if (calendar == null) {
return
}
val date = calendar.time
for (picker in pickers) {
picker.selectDate(date)
}
if (displayDaysOfMonth) {
updateDaysOfMonth()
}
}
private fun updateListener() {
val date = getDate()
val format = if (isAmPm) FORMAT_12_HOUR else FORMAT_24_HOUR
val displayed = DateFormat.format(format, date).toString()
for (listener in listeners) {
listener.onDateChanged(displayed, date)
}
}
private fun updateDaysOfMonth() {
val date = getDate()
val calendar = Calendar.getInstance()
calendar.time = date
updateDaysOfMonth(calendar)
}
private fun updateDaysOfMonth(calendar: Calendar) {
val daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH)
daysOfMonthPicker.daysInMonth = daysInMonth
daysOfMonthPicker.updateAdapter()
}
fun setMustBeOnFuture(mustBeOnFuture: Boolean) {
this.mustBeOnFuture = mustBeOnFuture
if (mustBeOnFuture) {
minDate = Calendar.getInstance().time // minDate is Today
}
}
fun mustBeOnFuture(): Boolean {
return mustBeOnFuture
}
private fun setMinYear() {
if (displayYears && this.minDate != null && this.maxDate != null) {
val calendar = Calendar.getInstance()
calendar.time = this.minDate
yearsPicker.setMinYear(calendar.get(Calendar.YEAR))
calendar.time = this.maxDate
yearsPicker.setMaxYear(calendar.get(Calendar.YEAR))
}
}
private fun checkSettings() {
if (displayDays && (displayDaysOfMonth || displayMonth)) {
throw IllegalArgumentException("You can either display days with months or days and months separately")
}
}
private fun init(context: Context, attrs: AttributeSet?) {
attrs?.let {
val a = context.obtainStyledAttributes(attrs, R.styleable.SingleDateAndTimePicker)
val resources = resources
setTodayText(a.getString(R.styleable.SingleDateAndTimePicker_picker_todayText))
setTextColor(a.getColor(R.styleable.SingleDateAndTimePicker_picker_textColor, ContextCompat.getColor(context, R.color.picker_default_text_color)))
setSelectedTextColor(a.getColor(R.styleable.SingleDateAndTimePicker_picker_selectedTextColor, ContextCompat.getColor(context, R.color.picker_default_selected_text_color)))
setSelectorColor(a.getColor(R.styleable.SingleDateAndTimePicker_picker_selectorColor, ContextCompat.getColor(context, R.color.picker_default_selector_color)))
setSelectorHeight(a.getDimensionPixelSize(R.styleable.SingleDateAndTimePicker_picker_selectorHeight, resources.getDimensionPixelSize(R.dimen.wheelSelectorHeight)))
setTextSize(a.getDimensionPixelSize(R.styleable.SingleDateAndTimePicker_picker_textSize, resources.getDimensionPixelSize(R.dimen.WheelItemTextSize)))
setCurved(a.getBoolean(R.styleable.SingleDateAndTimePicker_picker_curved, IS_CURVED_DEFAULT))
setCyclic(a.getBoolean(R.styleable.SingleDateAndTimePicker_picker_cyclic, IS_CYCLIC_DEFAULT))
setMustBeOnFuture(a.getBoolean(R.styleable.SingleDateAndTimePicker_picker_mustBeOnFuture, MUST_BE_ON_FUTUR_DEFAULT))
setVisibleItemCount(a.getInt(R.styleable.SingleDateAndTimePicker_picker_visibleItemCount, VISIBLE_ITEM_COUNT_DEFAULT))
setDisplayDays(a.getBoolean(R.styleable.SingleDateAndTimePicker_picker_displayDays, displayDays))
setDisplayMinutes(a.getBoolean(R.styleable.SingleDateAndTimePicker_picker_displayMinutes, displayMinutes))
setDisplayHours(a.getBoolean(R.styleable.SingleDateAndTimePicker_picker_displayHours, displayHours))
setDisplayMonths(a.getBoolean(R.styleable.SingleDateAndTimePicker_picker_displayMonth, displayMonth))
setDisplayYears(a.getBoolean(R.styleable.SingleDateAndTimePicker_picker_displayYears, displayYears))
setDisplayDaysOfMonth(a.getBoolean(R.styleable.SingleDateAndTimePicker_picker_displayDaysOfMonth, displayDaysOfMonth))
setDisplayMonthNumbers(a.getBoolean(R.styleable.SingleDateAndTimePicker_picker_displayMonthNumbers, monthPicker.displayMonthNumbers()))
checkSettings()
setMinYear()
a.recycle()
if (displayDaysOfMonth) {
updateDaysOfMonth(Calendar.getInstance())
}
}
}
interface OnDateChangedListener {
fun onDateChanged(displayed: String, date: Date)
}
}
single_day_picker.xml
**<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:gravity="center"
android:orientation="horizontal">
<com.github.florent37.singledateandtimepicker.widget.WheelMonthPicker
android:id="@+id/monthPicker"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
app:wheel_atmospheric="true"
app:wheel_item_align="right" />
<com.github.florent37.singledateandtimepicker.widget.WheelDayOfMonthPicker
android:id="@+id/daysOfMonthPicker"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
app:wheel_atmospheric="true"
app:wheel_item_align="right" />
<com.github.florent37.singledateandtimepicker.widget.WheelDayPicker
android:id="@+id/daysPicker"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:wheel_atmospheric="true"
app:wheel_item_align="right" />
<com.github.florent37.singledateandtimepicker.widget.WheelYearPicker
android:id="@+id/yearPicker"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
app:wheel_atmospheric="true"
app:wheel_item_align="right" />
<com.github.florent37.singledateandtimepicker.widget.WheelHourPicker
android:id="@+id/hoursPicker"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
app:wheel_atmospheric="true"
app:wheel_item_align="center" />
<com.github.florent37.singledateandtimepicker.widget.WheelMinutePicker
android:id="@+id/minutesPicker"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:wheel_atmospheric="true"
app:wheel_item_align="center" />
<com.github.florent37.singledateandtimepicker.widget.WheelAmPmPicker
android:id="@+id/amPmPicker"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="30dp"
app:wheel_atmospheric="true"
app:wheel_item_align="center"
app:wheel_visible_item_count="2" />
</LinearLayout>
<View
android:id="@+id/dtSelector"
android:layout_width="match_parent"
android:layout_height="@dimen/wheelSelectorHeight"
android:layout_gravity="center_vertical"
android:alpha="0.2"
android:background="@color/picker_default_selector_color" />
**
The result.
Okay thank you
@agustinsivoplas Your answer helps me a lot, thank you man!
Do you have a solution for this?