Преглед изворни кода

Implemented Date/Time/DateTime Picker (#1748)

By @guger
guger пре 6 година
родитељ
комит
f37d3e5f24

+ 1 - 0
datetime/.gitignore

@@ -0,0 +1 @@
+/build

+ 41 - 0
datetime/build.gradle

@@ -0,0 +1,41 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply from: '../dependencies.gradle'
+
+ext.shard = 'datetime'
+apply from: '../bintrayconfig.gradle'
+
+android {
+    compileSdkVersion versions.compileSdk
+    buildToolsVersion versions.buildTools
+
+    defaultConfig {
+        minSdkVersion versions.minSdk
+        targetSdkVersion versions.compileSdk
+        versionCode versions.publishVersionCode
+        versionName versions.publishVersion
+    }
+
+    sourceSets {
+        main.res.srcDirs = [
+                'src/main/res',
+                'src/main/res-public'
+        ]
+    }
+}
+
+dependencies {
+    api 'androidx.appcompat:appcompat:' + versions.androidxCore
+    api 'androidx.annotation:annotation:' + versions.androidxAnnotation
+
+    implementation 'androidx.recyclerview:recyclerview:' + versions.androidxRecyclerView
+    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:' + versions.kotlin
+
+    implementation 'com.afollestad:viewpagerdots:' + versions.dotsIndicator
+
+    api 'org.threeten:threetenbp:' + versions.threetenbp
+
+    implementation project(':core')
+}
+
+apply from: '../spotless.gradle'

+ 1 - 0
datetime/src/main/AndroidManifest.xml

@@ -0,0 +1 @@
+<manifest package="com.afollestad.materialdialogs.datetime"/>

+ 38 - 0
datetime/src/main/java/com/afollestad/materialdialogs/datetime/DateTimePickerAdapter.kt

@@ -0,0 +1,38 @@
+/**
+ * Designed and developed by Aidan Follestad (@afollestad)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.afollestad.materialdialogs.datetime
+
+import android.view.View
+import android.view.ViewGroup
+import androidx.viewpager.widget.PagerAdapter
+
+internal class DateTimePickerAdapter : PagerAdapter() {
+
+  override fun instantiateItem(container: ViewGroup, position: Int): Any {
+    val resId = when (position) {
+      0 -> R.id.datetimeDatePicker
+      1 -> R.id.datetimeTimePicker
+      else -> throw IllegalStateException("Unexpected position: $position")
+    }
+    return container.findViewById(resId)
+  }
+
+  override fun getCount(): Int = 2
+
+  override fun isViewFromObject(view: View, `object`: Any): Boolean = view === `object` as View
+
+  override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) = Unit
+}

+ 154 - 0
datetime/src/main/java/com/afollestad/materialdialogs/datetime/DialogDateTimePickerExt.kt

@@ -0,0 +1,154 @@
+/**
+ * Designed and developed by Aidan Follestad (@afollestad)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.afollestad.materialdialogs.datetime
+
+import android.widget.DatePicker
+import android.widget.TimePicker
+import androidx.viewpager.widget.ViewPager
+import com.afollestad.materialdialogs.MaterialDialog
+import com.afollestad.materialdialogs.WhichButton.POSITIVE
+import com.afollestad.materialdialogs.actions.setActionButtonEnabled
+import com.afollestad.materialdialogs.customview.customView
+import com.afollestad.materialdialogs.datetime.utils.hour
+import com.afollestad.materialdialogs.datetime.utils.minute
+import com.afollestad.materialdialogs.utils.MDUtil.resolveColor
+import com.afollestad.viewpagerdots.DotsIndicator
+import org.threeten.bp.LocalDate
+import org.threeten.bp.LocalDateTime
+import org.threeten.bp.LocalTime
+import org.threeten.bp.ZoneId
+
+typealias DateCallback = ((dialog: MaterialDialog, date: LocalDate) -> Unit)?
+typealias TimeCallback = ((dialog: MaterialDialog, time: LocalTime) -> Unit)?
+typealias DateTimeCallback = ((dialog: MaterialDialog, datetime: LocalDateTime) -> Unit)?
+
+fun MaterialDialog.datePicker(
+  minDate: LocalDate? = null,
+  currentDate: LocalDate? = null,
+  dateCallback: DateCallback = null
+): MaterialDialog {
+  customView(R.layout.md_datetime_picker_date)
+
+  minDate?.let { getDatePicker().minDate = it.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() }
+  currentDate?.let { getDatePicker().init(it.year, it.monthValue.inc(), it.dayOfMonth, null) }
+
+  positiveButton(android.R.string.ok) {
+    dateCallback?.invoke(it, extractLocalDate(getDatePicker()))
+  }
+  negativeButton(android.R.string.cancel)
+
+  return this
+}
+
+fun MaterialDialog.timePicker(
+  currentTime: LocalTime? = null,
+  show24HoursView: Boolean = true,
+  timeCallback: TimeCallback = null
+): MaterialDialog {
+  customView(R.layout.md_datetime_picker_time)
+
+  currentTime?.let {
+    getTimePicker().apply {
+      hour(it.hour)
+      minute(it.minute)
+
+      setIs24HourView(show24HoursView)
+    }
+  }
+
+  positiveButton(android.R.string.ok) {
+    timeCallback?.invoke(it, extractLocalTime(getTimePicker()))
+  }
+  negativeButton(android.R.string.cancel)
+
+  return this
+}
+
+fun MaterialDialog.dateTimePicker(
+  minDateTime: LocalDateTime? = null,
+  currentDateTime: LocalDateTime? = null,
+  requireFutureDateTime: Boolean = false,
+  show24HoursView: Boolean = true,
+  dateTimeCallback: DateTimeCallback = null
+): MaterialDialog {
+  customView(R.layout.md_datetime_picker_pager, noVerticalPadding = true)
+
+  val viewPager = getPager()
+  viewPager.adapter = DateTimePickerAdapter()
+
+  getPageIndicator()?.run {
+    attachViewPager(viewPager)
+    setDotTint(resolveColor(windowContext, attr = android.R.attr.textColorPrimary))
+  }
+
+  minDateTime?.let { getDatePicker().minDate = it.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() }
+  currentDateTime.let {
+    getDatePicker().apply {
+      init(it?.year ?: year, it?.monthValue?.inc() ?: month, it?.dayOfMonth ?: dayOfMonth) { _, _, _, _ ->
+        setActionButtonEnabled(POSITIVE, !requireFutureDateTime || isFutureTime(this, getTimePicker()))
+      }
+    }
+    getTimePicker().apply {
+      if (it != null) {
+        hour(it.hour)
+        minute(it.minute)
+      }
+
+      setIs24HourView(show24HoursView)
+
+      setOnTimeChangedListener { _, _, _ ->
+        setActionButtonEnabled(POSITIVE, !requireFutureDateTime || isFutureTime(getDatePicker(), this))
+      }
+    }
+  }
+
+  setActionButtonEnabled(POSITIVE, !requireFutureDateTime || isFutureTime(getDatePicker(), getTimePicker()))
+  positiveButton(android.R.string.ok) {
+    dateTimeCallback?.invoke(it, extractLocalDateTime(getDatePicker(), getTimePicker()))
+  }
+  negativeButton(android.R.string.cancel)
+
+  return this
+}
+
+private fun isFutureTime(datePicker: DatePicker, timePicker: TimePicker): Boolean {
+  val dateTime = LocalDateTime.now()
+
+  val date = extractLocalDateTime(datePicker, timePicker).toLocalDate()
+  val time = extractLocalDateTime(datePicker, timePicker).toLocalTime()
+
+  return date == dateTime.toLocalDate() && time.isAfter(dateTime.toLocalTime()) || date.isAfter(dateTime.toLocalDate())
+}
+
+private fun extractLocalDate(datePicker: DatePicker): LocalDate {
+  return LocalDate.of(datePicker.year, datePicker.month.inc(), datePicker.dayOfMonth)
+}
+
+private fun extractLocalTime(timePicker: TimePicker): LocalTime {
+  return LocalTime.of(timePicker.hour(), timePicker.minute())
+}
+
+private fun extractLocalDateTime(datePicker: DatePicker, timePicker: TimePicker): LocalDateTime {
+  return LocalDateTime.of(datePicker.year, datePicker.month.inc(), datePicker.dayOfMonth, timePicker.hour(), timePicker.minute())
+}
+
+private fun MaterialDialog.getDatePicker() = findViewById<DatePicker>(R.id.datetimeDatePicker)
+
+private fun MaterialDialog.getTimePicker() = findViewById<TimePicker>(R.id.datetimeTimePicker)
+
+private fun MaterialDialog.getPager() = findViewById<ViewPager>(R.id.dateTimePickerPager)
+
+private fun MaterialDialog.getPageIndicator() = findViewById<DotsIndicator?>(R.id.datetimePickerPagerDots)

+ 35 - 0
datetime/src/main/java/com/afollestad/materialdialogs/datetime/utils/ViewExt.kt

@@ -0,0 +1,35 @@
+/**
+ * Designed and developed by Aidan Follestad (@afollestad)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@file:Suppress("DEPRECATION")
+
+package com.afollestad.materialdialogs.datetime.utils
+
+import android.os.Build
+import android.widget.TimePicker
+
+private fun isNougat() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+
+fun TimePicker.hour(): Int = if (isNougat()) hour else currentHour
+
+fun TimePicker.minute(): Int = if (isNougat()) minute else currentMinute
+
+fun TimePicker.hour(value: Int) {
+  if (isNougat()) hour = value else currentHour = value
+}
+
+fun TimePicker.minute(value: Int) {
+  if (isNougat()) minute = value else currentMinute = value
+}

+ 66 - 0
datetime/src/main/java/com/afollestad/materialdialogs/datetime/view/WrapContentViewPager.kt

@@ -0,0 +1,66 @@
+/**
+ * Designed and developed by Aidan Follestad (@afollestad)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.afollestad.materialdialogs.datetime.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.view.View.MeasureSpec.EXACTLY
+import android.view.View.MeasureSpec.UNSPECIFIED
+import androidx.viewpager.widget.ViewPager
+
+internal class WrapContentViewPager(
+  context: Context,
+  attrs: AttributeSet? = null
+) : ViewPager(context, attrs) {
+
+  override fun onMeasure(
+    widthMeasureSpec: Int,
+    heightMeasureSpec: Int
+  ) {
+    var newHeightSpec = heightMeasureSpec
+
+    var maxChildHeight = 0
+    forEachChild { child ->
+      child.measure(
+        widthMeasureSpec,
+        MeasureSpec.makeMeasureSpec(0, UNSPECIFIED)
+      )
+
+      val h = child.measuredHeight
+      if (h > maxChildHeight) {
+        maxChildHeight = h
+      }
+    }
+
+    val maxAllowedHeightFromParent = MeasureSpec.getSize(heightMeasureSpec)
+    if (maxChildHeight > maxAllowedHeightFromParent) {
+      maxChildHeight = maxAllowedHeightFromParent
+    }
+    if (maxChildHeight != 0) {
+      newHeightSpec = MeasureSpec.makeMeasureSpec(maxChildHeight, EXACTLY)
+    }
+
+    super.onMeasure(widthMeasureSpec, newHeightSpec)
+  }
+
+  private fun forEachChild(each: (View) -> Unit) {
+    for (i in 0 until childCount) {
+      val child = getChildAt(i)
+      each(child)
+    }
+  }
+}

+ 5 - 0
datetime/src/main/res/layout/md_datetime_picker_date.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/datetimeDatePicker"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content" />

+ 22 - 0
datetime/src/main/res/layout/md_datetime_picker_pager.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <com.afollestad.viewpagerdots.DotsIndicator
+        android:id="@+id/datetimePickerPagerDots"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/datetime_picker_pageDots_height"
+        android:layout_marginBottom="@dimen/datetime_picker_pageDots_marginBottom" />
+
+    <com.afollestad.materialdialogs.datetime.view.WrapContentViewPager
+        android:id="@+id/dateTimePickerPager"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+        <include layout="@layout/md_datetime_picker_date" />
+
+        <include layout="@layout/md_datetime_picker_time" />
+    </com.afollestad.materialdialogs.datetime.view.WrapContentViewPager>
+</LinearLayout>

+ 5 - 0
datetime/src/main/res/layout/md_datetime_picker_time.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TimePicker xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/datetimeTimePicker"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" />

+ 5 - 0
datetime/src/main/res/values/dimens.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="datetime_picker_pageDots_height">24dp</dimen>
+    <dimen name="datetime_picker_pageDots_marginBottom">8dp</dimen>
+</resources>

+ 4 - 1
dependencies.gradle

@@ -25,5 +25,8 @@ ext.versions = [
 
     // afollestad
     assent              : '2.2.3',
-    dotsIndicator       : '1.0.0'
+    dotsIndicator       : '1.0.0',
+
+    // java.time backport
+    threetenbp          : '1.3.8'
 ]

+ 1 - 0
sample/build.gradle

@@ -21,6 +21,7 @@ dependencies {
   implementation project(':input')
   implementation project(':files')
   implementation project(':color')
+  implementation project(':datetime')
 
   implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:' + versions.kotlin
 

+ 93 - 63
sample/src/main/java/com/afollestad/materialdialogssample/MainActivity.kt

@@ -41,6 +41,9 @@ import com.afollestad.materialdialogs.color.ColorPalette
 import com.afollestad.materialdialogs.color.colorChooser
 import com.afollestad.materialdialogs.customview.customView
 import com.afollestad.materialdialogs.customview.getCustomView
+import com.afollestad.materialdialogs.datetime.datePicker
+import com.afollestad.materialdialogs.datetime.dateTimePicker
+import com.afollestad.materialdialogs.datetime.timePicker
 import com.afollestad.materialdialogs.files.fileChooser
 import com.afollestad.materialdialogs.files.folderChooser
 import com.afollestad.materialdialogs.input.input
@@ -102,6 +105,9 @@ import kotlinx.android.synthetic.main.activity_main.single_choice_buttons_titled
 import kotlinx.android.synthetic.main.activity_main.single_choice_disabled_items
 import kotlinx.android.synthetic.main.activity_main.single_choice_long_items
 import kotlinx.android.synthetic.main.activity_main.single_choice_titled
+import kotlinx.android.synthetic.main.activity_main.date_picker
+import kotlinx.android.synthetic.main.activity_main.time_picker
+import kotlinx.android.synthetic.main.activity_main.datetime_picker
 
 /** @author Aidan Follestad (afollestad) */
 class MainActivity : AppCompatActivity() {
@@ -122,11 +128,11 @@ class MainActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
     prefs = getSharedPreferences(KEY_PREFS, MODE_PRIVATE)
     setTheme(
-        when (prefs.getString(KEY_THEME, LIGHT)) {
-          DARK -> R.style.AppTheme_Dark
-          CUSTOM -> R.style.AppTheme_Custom
-          else -> R.style.AppTheme
-        }
+      when (prefs.getString(KEY_THEME, LIGHT)) {
+        DARK -> R.style.AppTheme_Dark
+        CUSTOM -> R.style.AppTheme_Custom
+        else -> R.style.AppTheme
+      }
     )
     debugMode = prefs.boolean(KEY_DEBUG_MODE, false)
 
@@ -180,9 +186,9 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.app_name)
         message(
-            R.string.htmlContent,
-            html = true,
-            lineHeightMultiplier = 1.4f
+          R.string.htmlContent,
+          html = true,
+          lineHeightMultiplier = 1.4f
         )
         positiveButton(R.string.agree)
         negativeButton(R.string.disagree)
@@ -434,7 +440,7 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.socialNetworks)
         listItemsSingleChoice(
-            R.array.socialNetworks, initialSelection = 1, disabledIndices = intArrayOf(1, 3)
+          R.array.socialNetworks, initialSelection = 1, disabledIndices = intArrayOf(1, 3)
         ) { _, index, text ->
           toast("Selected item $text at index $index")
         }
@@ -447,7 +453,7 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.socialNetworks)
         listItemsMultiChoice(
-            R.array.socialNetworks, initialSelection = intArrayOf(1, 3)
+          R.array.socialNetworks, initialSelection = intArrayOf(1, 3)
         ) { _, indices, text ->
           toast("Selected items ${text.joinToString()} at indices ${indices.joinToString()}")
         }
@@ -459,7 +465,7 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.socialNetworks)
         listItemsMultiChoice(
-            R.array.socialNetworks, initialSelection = intArrayOf(1, 3)
+          R.array.socialNetworks, initialSelection = intArrayOf(1, 3)
         ) { _, indices, text ->
           toast("Selected items ${text.joinToString()} at indices ${indices.joinToString()}")
         }
@@ -472,7 +478,7 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.socialNetworks)
         listItemsMultiChoice(
-            R.array.socialNetworks_longItems, initialSelection = intArrayOf(0, 2)
+          R.array.socialNetworks_longItems, initialSelection = intArrayOf(0, 2)
         ) { _, indices, text ->
           toast("Selected items ${text.joinToString()} at indices ${indices.joinToString()}")
         }
@@ -485,9 +491,9 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.socialNetworks)
         listItemsMultiChoice(
-            R.array.socialNetworks,
-            initialSelection = intArrayOf(2, 3),
-            disabledIndices = intArrayOf(1, 3)
+          R.array.socialNetworks,
+          initialSelection = intArrayOf(2, 3),
+          disabledIndices = intArrayOf(1, 3)
         ) { _, indices, text ->
           toast("Selected items ${text.joinToString()} at indices ${indices.joinToString()}")
         }
@@ -566,8 +572,8 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.useGoogleLocationServices)
         input(
-            hint = "Type something",
-            inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_WORDS
+          hint = "Type something",
+          inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_WORDS
         ) { _, text ->
           toast("Input: $text")
         }
@@ -582,9 +588,9 @@ class MainActivity : AppCompatActivity() {
         title(R.string.useGoogleLocationServices)
         message(R.string.useGoogleLocationServicesPrompt)
         input(
-            hint = "Type something",
-            prefill = "Pre-filled!",
-            inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_WORDS
+          hint = "Type something",
+          prefill = "Pre-filled!",
+          inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_WORDS
         ) { _, text ->
           toast("Input: $text")
         }
@@ -598,9 +604,9 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.useGoogleLocationServices)
         input(
-            hint = "Type something",
-            inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_WORDS,
-            maxLength = 8
+          hint = "Type something",
+          inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_WORDS,
+          maxLength = 8
         ) { _, text ->
           toast("Input: $text")
         }
@@ -614,8 +620,8 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.useGoogleLocationServices)
         input(
-            hint = "Type something",
-            inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_WORDS
+          hint = "Type something",
+          inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_WORDS
         ) { _, text ->
           toast("Input: $text")
         }
@@ -636,8 +642,8 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.primary_colors)
         colorChooser(
-            ColorPalette.Primary,
-            ColorPalette.PrimarySub
+          ColorPalette.Primary,
+          ColorPalette.PrimarySub
         ) { _, color ->
           toast("Selected color: ${color.toHex()}")
         }
@@ -651,8 +657,8 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.accent_colors)
         colorChooser(
-            ColorPalette.Accent,
-            ColorPalette.AccentSub
+          ColorPalette.Accent,
+          ColorPalette.AccentSub
         ) { _, color ->
           toast("Selected color: ${color.toHex()}")
         }
@@ -665,10 +671,10 @@ class MainActivity : AppCompatActivity() {
     colorChooser_customColors.setOnClickListener {
       val topLevel = intArrayOf(Color.TRANSPARENT, Color.RED, Color.YELLOW, Color.BLUE)
       val subLevel = arrayOf(
-          intArrayOf(Color.WHITE, Color.TRANSPARENT, Color.BLACK),
-          intArrayOf(Color.LTGRAY, Color.GRAY, Color.DKGRAY),
-          intArrayOf(Color.GREEN),
-          intArrayOf(Color.MAGENTA, Color.CYAN)
+        intArrayOf(Color.WHITE, Color.TRANSPARENT, Color.BLACK),
+        intArrayOf(Color.LTGRAY, Color.GRAY, Color.DKGRAY),
+        intArrayOf(Color.GREEN),
+        intArrayOf(Color.MAGENTA, Color.CYAN)
       )
 
       MaterialDialog(this).show {
@@ -703,9 +709,9 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.custom_colors_rgb)
         colorChooser(
-            colors = ColorPalette.Primary,
-            subColors = ColorPalette.PrimarySub,
-            allowCustomArgb = true
+          colors = ColorPalette.Primary,
+          subColors = ColorPalette.PrimarySub,
+          allowCustomArgb = true
         ) { _, color ->
           toast("Selected color: ${color.toHex()}")
         }
@@ -719,10 +725,10 @@ class MainActivity : AppCompatActivity() {
       MaterialDialog(this).show {
         title(R.string.custom_colors_argb)
         colorChooser(
-            colors = ColorPalette.Primary,
-            subColors = ColorPalette.PrimarySub,
-            allowCustomArgb = true,
-            showAlphaSelector = true
+          colors = ColorPalette.Primary,
+          subColors = ColorPalette.PrimarySub,
+          allowCustomArgb = true,
+          showAlphaSelector = true
         ) { _, color ->
           toast("Selected color: ${color.toHex()}")
         }
@@ -741,6 +747,30 @@ class MainActivity : AppCompatActivity() {
     folder_chooser_buttons.setOnClickListener { showFolderChooserButtons() }
 
     folder_chooser_filter.setOnClickListener { showFolderChooserFilter() }
+
+    date_picker.setOnClickListener {
+      MaterialDialog(this).show {
+        title(text = "Select Date and Time")
+
+        datePicker()
+      }
+    }
+
+    time_picker.setOnClickListener {
+      MaterialDialog(this).show {
+        title(text = "Select Date and Time")
+
+        timePicker()
+      }
+    }
+
+    datetime_picker.setOnClickListener {
+      MaterialDialog(this).show {
+        title(text = "Select Date and Time")
+
+        dateTimePicker(requireFutureDateTime = true)
+      }
+    }
   }
 
   private fun showCustomViewDialog() {
@@ -762,9 +792,9 @@ class MainActivity : AppCompatActivity() {
     val showPasswordCheck: CheckBox = customView.findViewById(R.id.showPassword)
     showPasswordCheck.setOnCheckedChangeListener { _, isChecked ->
       passwordInput.inputType =
-          if (!isChecked) InputType.TYPE_TEXT_VARIATION_PASSWORD else InputType.TYPE_CLASS_TEXT
+        if (!isChecked) InputType.TYPE_TEXT_VARIATION_PASSWORD else InputType.TYPE_CLASS_TEXT
       passwordInput.transformationMethod =
-          if (!isChecked) PasswordTransformationMethod.getInstance() else null
+        if (!isChecked) PasswordTransformationMethod.getInstance() else null
     }
   }
 
@@ -777,23 +807,23 @@ class MainActivity : AppCompatActivity() {
     dialog.onShow {
       val webView: WebView = it.getCustomView().findViewById(R.id.web_view)
       webView.loadData(
-          "<h3>WebView Custom View</h3>\n" +
-              "\n" +
-              "<ol>\n" +
-              "    <li><b>NEW:</b> Hey!</li>\n" +
-              "    <li><b>IMPROVE:</b> Hello!</li>\n" +
-              "    <li><b>FIX:</b> Hi!</li>\n" +
-              "    <li><b>FIX:</b> Hey again!</li>\n" +
-              "    <li><b>FIX:</b> What?</li>\n" +
-              "    <li><b>FIX:</b> This is an example.</li>\n" +
-              "    <li><b>MISC:</b> How are you?</li>\n" +
-              "</ol>\n" +
-              "<p>Material guidelines for dialogs:\n" +
-              "    <a href='http://www.google.com/design/spec/components/dialogs.html'>" +
-              "http://www.google.com/design/spec/components/dialogs.html</a>.\n" +
-              "</p>",
-          "text/html",
-          "UTF-8"
+        "<h3>WebView Custom View</h3>\n" +
+          "\n" +
+          "<ol>\n" +
+          "    <li><b>NEW:</b> Hey!</li>\n" +
+          "    <li><b>IMPROVE:</b> Hello!</li>\n" +
+          "    <li><b>FIX:</b> Hi!</li>\n" +
+          "    <li><b>FIX:</b> Hey again!</li>\n" +
+          "    <li><b>FIX:</b> What?</li>\n" +
+          "    <li><b>FIX:</b> This is an example.</li>\n" +
+          "    <li><b>MISC:</b> How are you?</li>\n" +
+          "</ol>\n" +
+          "<p>Material guidelines for dialogs:\n" +
+          "    <a href='http://www.google.com/design/spec/components/dialogs.html'>" +
+          "http://www.google.com/design/spec/components/dialogs.html</a>.\n" +
+          "</p>",
+        "text/html",
+        "UTF-8"
       )
     }
   }
@@ -852,18 +882,18 @@ class MainActivity : AppCompatActivity() {
     val theme = prefs.getString(KEY_THEME, LIGHT)
     if (theme == LIGHT) {
       menu.findItem(R.id.light_theme)
-          .isChecked = true
+        .isChecked = true
     }
     if (theme == DARK) {
       menu.findItem(R.id.dark_theme)
-          .isChecked = true
+        .isChecked = true
     }
     if (theme == CUSTOM) {
       menu.findItem(R.id.custom_theme)
-          .isChecked = true
+        .isChecked = true
     }
     menu.findItem(R.id.debug_mode)
-        .isChecked = debugMode
+      .isChecked = debugMode
     return super.onCreateOptionsMenu(menu)
   }
 

+ 299 - 274
sample/src/main/res/layout/activity_main.xml

@@ -3,424 +3,449 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:padding="@dimen/activity_horizontal_margin"
+        tools:context=".MainActivity"
+        tools:ignore="HardcodedText"
     >
 
-  <LinearLayout
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:orientation="vertical"
-      android:padding="@dimen/activity_horizontal_margin"
-      tools:context=".MainActivity"
-      tools:ignore="HardcodedText"
-      >
+        <!-- Basic -->
 
-    <!-- Basic -->
-
-    <TextView
-        android:layout_marginTop="0dp"
-        android:text="Basic"
-        style="@style/SampleHeader"
+        <TextView
+            android:layout_marginTop="0dp"
+            android:text="Basic"
+            style="@style/SampleHeader"
         />
 
-    <Button
-        android:id="@+id/basic"
-        android:text="Basic"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/basic"
+            android:text="Basic"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/basic_titled"
-        android:text="Basic + Title"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/basic_titled"
+            android:text="Basic + Title"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/basic_buttons"
-        android:text="Basic + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/basic_buttons"
+            android:text="Basic + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/basic_stacked_buttons"
-        android:text="Basic + Stacked Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/basic_stacked_buttons"
+            android:text="Basic + Stacked Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/basic_titled_buttons"
-        android:text="Basic + Title + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/basic_titled_buttons"
+            android:text="Basic + Title + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/basic_html_content"
-        android:text="Basic + HTML Content"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/basic_html_content"
+            android:text="Basic + HTML Content"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/basic_long"
-        android:text="Basic Long"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/basic_long"
+            android:text="Basic Long"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/basic_long_titled_buttons"
-        android:text="Basic Long + Title + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/basic_long_titled_buttons"
+            android:text="Basic Long + Title + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/basic_icon"
-        android:text="Basic + Icon + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/basic_icon"
+            android:text="Basic + Icon + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/basic_checkbox_titled_buttons"
-        android:text="Basic + Title + Checkbox + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/basic_checkbox_titled_buttons"
+            android:text="Basic + Title + Checkbox + Buttons"
+            style="@style/SampleButton"
         />
 
-    <!-- Basic Lists -->
+        <!-- Basic Lists -->
 
-    <TextView
-        android:text="Lists"
-        style="@style/SampleHeader"
+        <TextView
+            android:text="Lists"
+            style="@style/SampleHeader"
         />
 
-    <Button
-        android:id="@+id/list"
-        android:text="List"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list"
+            android:text="List"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_buttons"
-        android:text="List + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_buttons"
+            android:text="List + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_titled"
-        android:text="List + Title"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_titled"
+            android:text="List + Title"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_titled_buttons"
-        android:text="List + Title + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_titled_buttons"
+            android:text="List + Title + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_titled_message_buttons"
-        android:text="List + Title + Message + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_titled_message_buttons"
+            android:text="List + Title + Message + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_long"
-        android:text="List Long"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_long"
+            android:text="List Long"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_long_buttons"
-        android:text="List Long + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_long_buttons"
+            android:text="List Long + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_long_titled"
-        android:text="List Long + Title"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_long_titled"
+            android:text="List Long + Title"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_long_titled_buttons"
-        android:text="List Long + Title + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_long_titled_buttons"
+            android:text="List Long + Title + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_long_items"
-        android:text="List, Long Items"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_long_items"
+            android:text="List, Long Items"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_long_items_buttons"
-        android:text="List, Long Items + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_long_items_buttons"
+            android:text="List, Long Items + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_long_items_titled"
-        android:text="List, Long Items + Title"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_long_items_titled"
+            android:text="List, Long Items + Title"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_long_items_titled_buttons"
+        <Button
+            android:id="@+id/list_long_items_titled_buttons"
 
-        android:text="List, Long Items + Title + Buttons"
-        style="@style/SampleButton"
+            android:text="List, Long Items + Title + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_checkPrompt"
-        android:text="List + Title + Checkbox Prompt"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_checkPrompt"
+            android:text="List + Title + Checkbox Prompt"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/list_checkPrompt_buttons"
-        android:text="List + Title + Checkbox Prompt + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/list_checkPrompt_buttons"
+            android:text="List + Title + Checkbox Prompt + Buttons"
+            style="@style/SampleButton"
         />
 
-    <!-- Single Choice Lists -->
+        <!-- Single Choice Lists -->
 
-    <TextView
-        android:text="Single Choice Lists"
-        style="@style/SampleHeader"
+        <TextView
+            android:text="Single Choice Lists"
+            style="@style/SampleHeader"
         />
 
-    <Button
-        android:id="@+id/single_choice_titled"
-        android:text="Single Choice + Title"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/single_choice_titled"
+            android:text="Single Choice + Title"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/single_choice_buttons_titled"
-        android:text="Single Choice + Title + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/single_choice_buttons_titled"
+            android:text="Single Choice + Title + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/single_choice_long_items"
-        android:text="Single Choice, Long Items"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/single_choice_long_items"
+            android:text="Single Choice, Long Items"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/single_choice_disabled_items"
-        android:text="Single Choice, Disabled Items"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/single_choice_disabled_items"
+            android:text="Single Choice, Disabled Items"
+            style="@style/SampleButton"
         />
 
-    <!-- Multiple Choice Lists -->
+        <!-- Multiple Choice Lists -->
 
-    <TextView
-        android:text="Multiple Choice Lists"
-        style="@style/SampleHeader"
+        <TextView
+            android:text="Multiple Choice Lists"
+            style="@style/SampleHeader"
         />
 
-    <Button
-        android:id="@+id/multiple_choice"
-        android:text="Multiple Choice"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/multiple_choice"
+            android:text="Multiple Choice"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/multiple_choice_buttons"
-        android:text="Multiple Choice + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/multiple_choice_buttons"
+            android:text="Multiple Choice + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/multiple_choice_long_items"
-        android:text="Multiple Choice, Long Items"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/multiple_choice_long_items"
+            android:text="Multiple Choice, Long Items"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/multiple_choice_disabled_items"
-        android:text="Multiple Choice, Disabled Items"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/multiple_choice_disabled_items"
+            android:text="Multiple Choice, Disabled Items"
+            style="@style/SampleButton"
         />
 
-    <!-- Action Buttons -->
+        <!-- Action Buttons -->
 
-    <TextView
-        android:text="Action Buttons"
-        style="@style/SampleHeader"
+        <TextView
+            android:text="Action Buttons"
+            style="@style/SampleHeader"
         />
 
-    <Button
-        android:id="@+id/buttons_stacked"
-        android:text="Stacked Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/buttons_stacked"
+            android:text="Stacked Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/buttons_stacked_checkboxPrompt"
-        android:text="Stacked Buttons + Checkbox Prompt"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/buttons_stacked_checkboxPrompt"
+            android:text="Stacked Buttons + Checkbox Prompt"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/buttons_neutral"
-        android:text="Neutral Button"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/buttons_neutral"
+            android:text="Neutral Button"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/buttons_callbacks"
-        android:text="Button Callbacks"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/buttons_callbacks"
+            android:text="Button Callbacks"
+            style="@style/SampleButton"
         />
 
-    <TextView
-        android:text="Miscellaneous"
-        style="@style/SampleHeader"
+        <TextView
+            android:text="Miscellaneous"
+            style="@style/SampleHeader"
         />
 
-    <Button
-        android:id="@+id/misc_dialog_callbacks"
-        android:text="Dialog Callbacks"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/misc_dialog_callbacks"
+            android:text="Dialog Callbacks"
+            style="@style/SampleButton"
         />
 
-    <!-- Input -->
+        <!-- Input -->
 
-    <TextView
-        android:text="Text Input"
-        style="@style/SampleHeader"
+        <TextView
+            android:text="Text Input"
+            style="@style/SampleHeader"
         />
 
-    <Button
-        android:id="@+id/input"
-        android:text="Input"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/input"
+            android:text="Input"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/input_message"
-        android:text="Input + Message"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/input_message"
+            android:text="Input + Message"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/input_counter"
-        android:text="Input + Counter"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/input_counter"
+            android:text="Input + Counter"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/input_check_prompt"
-        android:text="Input + Checkbox Prompt"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/input_check_prompt"
+            android:text="Input + Checkbox Prompt"
+            style="@style/SampleButton"
         />
 
-    <!-- Custom Views -->
+        <!-- Custom Views -->
 
-    <TextView
-        android:text="Custom Views"
-        style="@style/SampleHeader"
+        <TextView
+            android:text="Custom Views"
+            style="@style/SampleHeader"
         />
 
-    <Button
-        android:id="@+id/custom_view"
-        android:text="Custom View"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/custom_view"
+            android:text="Custom View"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/custom_view_webview"
-        android:text="Custom View, Web View"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/custom_view_webview"
+            android:text="Custom View, Web View"
+            style="@style/SampleButton"
         />
 
-    <!-- Color Chooser -->
+        <!-- Color Chooser -->
+
+        <TextView
+            android:text="Color"
+            style="@style/SampleHeader"
+        />
+
+        <Button
+            android:id="@+id/colorChooser_primary"
+            android:text="Color Chooser, Primary"
+            style="@style/SampleButton"
+        />
 
-    <TextView
-        android:text="Color"
-        style="@style/SampleHeader"
+        <Button
+            android:id="@+id/colorChooser_accent"
+            android:text="Color Chooser, Accent"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/colorChooser_primary"
-        android:text="Color Chooser, Primary"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/colorChooser_customColors"
+            android:text="Color Chooser, Custom"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/colorChooser_accent"
-        android:text="Color Chooser, Accent"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/colorChooser_customColorsNoSub"
+            android:text="Color Chooser, Custom + No Sub"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/colorChooser_customColors"
-        android:text="Color Chooser, Custom"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/colorChooser_primary_customRgb"
+            android:text="Color Chooser, Primary + Custom RGB"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/colorChooser_customColorsNoSub"
-        android:text="Color Chooser, Custom + No Sub"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/colorChooser_primary_customArgb"
+            android:text="Color Chooser, Primary + Custom ARGB"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/colorChooser_primary_customRgb"
-        android:text="Color Chooser, Primary + Custom RGB"
-        style="@style/SampleButton"
+        <!-- File Choosers -->
+
+        <TextView
+            android:text="File Choosers"
+            style="@style/SampleHeader"
         />
 
-    <Button
-        android:id="@+id/colorChooser_primary_customArgb"
-        android:text="Color Chooser, Primary + Custom ARGB"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/file_chooser"
+            android:text="File Chooser"
+            style="@style/SampleButton"
         />
 
-    <!-- File Choosers -->
+        <Button
+            android:id="@+id/file_chooser_buttons"
+            android:text="File Chooser + Buttons"
+            style="@style/SampleButton"
+        />
 
-    <TextView
-        android:text="File Choosers"
-        style="@style/SampleHeader"
+        <Button
+            android:id="@+id/file_chooser_filter"
+            android:text="File Chooser + Filter"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/file_chooser"
-        android:text="File Chooser"
-        style="@style/SampleButton"
+        <!-- Folder Choosers -->
+
+        <TextView
+            android:text="Folder Choosers"
+            style="@style/SampleHeader"
         />
 
-    <Button
-        android:id="@+id/file_chooser_buttons"
-        android:text="File Chooser + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/folder_chooser_buttons"
+            android:text="Folder Chooser + Buttons"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/file_chooser_filter"
-        android:text="File Chooser + Filter"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/folder_chooser_filter"
+            android:text="Folder Chooser + Filter"
+            style="@style/SampleButton"
         />
 
-    <!-- Folder Choosers -->
+        <!-- DateTime Pickers -->
+
+        <TextView
+            android:text="DateTime Pickers"
+            style="@style/SampleHeader"
+        />
 
-    <TextView
-        android:text="Folder Choosers"
-        style="@style/SampleHeader"
+        <Button
+            android:id="@+id/date_picker"
+            android:text="Date Picker"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/folder_chooser_buttons"
-        android:text="Folder Chooser + Buttons"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/time_picker"
+            android:text="Time Picker"
+            style="@style/SampleButton"
         />
 
-    <Button
-        android:id="@+id/folder_chooser_filter"
-        android:text="Folder Chooser + Filter"
-        style="@style/SampleButton"
+        <Button
+            android:id="@+id/datetime_picker"
+            android:text="DateTime Picker"
+            style="@style/SampleButton"
         />
 
-  </LinearLayout>
+    </LinearLayout>
 
 </ScrollView>

+ 1 - 1
settings.gradle

@@ -1 +1 @@
-include ':core', ':sample', ':files', ':color', ':input', ':lifecycle'
+include ':core', ':sample', ':files', ':color', ':input', ':lifecycle', ':datetime'