Ich habe TimePicker verwendet, damit der Benutzer die Zeit wählen kann, siehe ici y auch hier . Aber ich habe keine Möglichkeit gefunden, den Benutzer dazu zu bringen, auch die zweite Option zu wählen. Jetzt kann der Benutzer die Stunde und die Minute auswählen, aber nicht die Sekunde. Wenn ich eine Zeit für 02:05:10 einstellen möchte, was muss ich dann tun? Wie kann man eine Sekunde mit TimePicker auswählen?
Antworten
Zu viele Anzeigen?Ich habe meine eigene Zeitauswahl mit Sekunden erstellt. Sie können ihn ausprobieren aquí .
Ich habe einige andere Funktionalitäten hinzugefügt.
Die wichtigsten Dateien sind
mein_zeit_picker_inhalt.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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="wrap_content">
<LinearLayout
android:id="@+id/hours_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="16dp"
android:orientation="vertical"
android:layout_marginVertical="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/minutes_container"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hours"
android:layout_gravity="center_horizontal"
android:layout_marginVertical="8dp"/>
<NumberPicker
android:id="@+id/hours"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants" />
</LinearLayout>
<LinearLayout
android:id="@+id/minutes_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginVertical="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/seconds_container"
app:layout_constraintStart_toEndOf="@+id/hours_container">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Minutes"
android:layout_gravity="center_horizontal"
android:layout_marginVertical="8dp"/>
<NumberPicker
android:id="@+id/minutes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants" />
</LinearLayout>
<LinearLayout
android:id="@+id/seconds_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginVertical="8dp"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/minutes_container">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Seconds"
android:layout_gravity="center_horizontal"
android:layout_marginVertical="8dp"/>
<NumberPicker
android:id="@+id/seconds"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MyTimePicker-Klasse
package com.themarto.mytimepicker
import android.app.AlertDialog
import android.app.Dialog
import android.os.Bundle
import android.view.View
import android.widget.LinearLayout
import android.widget.NumberPicker
import androidx.fragment.app.DialogFragment
/**
* Time Picker that shows a Dialog to select
* hours, minutes and seconds. You can choose
* to use only minutes and seconds by setting
* to false the property "includeHours".
*/
class MyTimePicker() : DialogFragment() {
private lateinit var timePickerLayout: View
private lateinit var hourPicker: NumberPicker
private lateinit var minPicker: NumberPicker
private lateinit var secPicker: NumberPicker
private var onTimeSetOption:
(hour: Int, minute: Int, second: Int) -> Unit = {_, _, _ -> }
private var timeSetText: String = "Ok"
private var onCancelOption: () -> Unit = {}
private var cancelText: String = "Cancel"
/**
* Which value will appear a the start of
* the Dialog for the Hour picker.
* Default value is 0.
*/
var initialHour: Int = 0
/**
* Which value will appear a the start of
* the Dialog for the Minute picker.
* Default value is 0.
*/
var initialMinute: Int = 0
/**
* Which value will appear a the start of
* the Dialog for the Second picker.
* Default value is 0.
*/
var initialSeconds: Int = 0
/**
* Max value for the Hour picker.
* Default value is 23.
*/
var maxValueHour: Int = 23
/**
* Max value for the Minute picker.
* Default value is 59.
*/
var maxValueMinute: Int = 59
/**
* Max value for the Second picker.
* Default value is 59.
*/
var maxValueSeconds: Int = 59
/**
* Min value for the Hour picker.
* Default value is 0.
*/
var minValueHour: Int = 0
/**
* Min value for the Minute picker.
* Default value is 0.
*/
var minValueMinute: Int = 0
/**
* Min value for the Second picker.
* Default value is 0.
*/
var minValueSecond: Int = 0
/**
* Default value is true.
* If set to false the hour picker is not
* visible in the Dialog
*/
var includeHours: Boolean = true
private var title: String? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
// Use the Builder class for convenient dialog construction
val builder = AlertDialog.Builder(it)
timePickerLayout = requireActivity()
.layoutInflater.inflate(R.layout.my_time_picker_content, null)
setupTimePickerLayout()
builder.setView(timePickerLayout)
title?.let { title ->
builder.setTitle(title)
}
builder.setPositiveButton(timeSetText) { _, _ ->
var hour = hourPicker.value
if (!includeHours) hour = 0
onTimeSetOption(hour, minPicker.value, secPicker.value)
}
.setNegativeButton(cancelText) { _, _ ->
onCancelOption
}
// Create the AlertDialog object and return it
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
/**
* Set the title displayed in the Dialog
*/
fun setTitle(title: String) {
this.title = title
}
/**
* Set a listener to be invoked when the Set Time button of the dialog is pressed.
* If have set includeHours to false, the hour parameter here will be always 0.
* @param text text to display in the Set Time button.
*/
fun setOnTimeSetOption (text: String, onTimeSet: (hour: Int, minute: Int, second: Int) -> Unit) {
onTimeSetOption = onTimeSet
timeSetText = text
}
/**
* Set a listener to be invoked when the Cancel button of the dialog is pressed.
* @param text text to display in the Cancel button.
*/
fun setOnCancelOption (text: String, onCancelOption: () -> Unit) {
this.onCancelOption = onCancelOption
cancelText = text
}
private fun setupTimePickerLayout() {
bindViews()
setupMaxValues()
setupMinValues()
setupInitialValues()
if (!includeHours) {
timePickerLayout.findViewById<LinearLayout>(R.id.hours_container)
.visibility = View.GONE
}
}
private fun bindViews() {
hourPicker = timePickerLayout.findViewById<NumberPicker>(R.id.hours)
minPicker = timePickerLayout.findViewById<NumberPicker>(R.id.minutes)
secPicker = timePickerLayout.findViewById<NumberPicker>(R.id.seconds)
}
private fun setupMaxValues () {
hourPicker.maxValue = maxValueHour
minPicker.maxValue = maxValueMinute
secPicker.maxValue = maxValueSeconds
}
private fun setupMinValues () {
hourPicker.minValue = minValueHour
minPicker.minValue = minValueMinute
secPicker.minValue = minValueSecond
}
private fun setupInitialValues () {
hourPicker.value = initialHour
minPicker.value = initialMinute
secPicker.value = initialSeconds
}
}
MainActivity-Klasse
package com.themarto.mytimepicker
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
class MainActivity : AppCompatActivity() {
private lateinit var timeText: TextView
private lateinit var showDialogBtn: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
timeText = findViewById(R.id.timeText)
showDialogBtn = findViewById(R.id.showDialogButton)
showDialogBtn.setOnClickListener {
val timePicker = MyTimePicker()
timePicker.setTitle("Select time")
//timePicker.includeHours = false
timePicker.setOnTimeSetOption("Set time") {hour, minute, second ->
timeText.text = "$hour : $minute : $second"
}
/* To show the dialog you have to supply the "fragment manager"
and a tag (whatever you want)
*/
timePicker.show(supportFragmentManager, "time_picker")
}
}
}
Ich habe eine Kotlin-Erweiterungsfunktion geschrieben, um dies zu tun. Es ist chaotisch, aber es erledigt die Aufgabe:
/**
* Adds seconds number picker into the [TimePicker] format programmatically.
* */
fun TimePicker.addSeconds() {
val system = Resources.getSystem()
val idHour = system.getIdentifier("hour", "id", "android")
val idMinute = system.getIdentifier("minute", "id", "android")
val idAmPm = system.getIdentifier("amPm", "id", "android")
val idLayout = system.getIdentifier("timePickerLayout", "id", "android")
val spinnerHour = findViewById<View>(idHour) as NumberPicker
val spinnerMinute = findViewById<View>(idMinute) as NumberPicker
val spinnerAmPm = findViewById<View>(idAmPm) as NumberPicker
val outerLayout = findViewById<View>(idLayout) as LinearLayout
val layout = outerLayout.getChildAt(0) as LinearLayout
layout.removeAllViews()
(spinnerAmPm.parent as ViewGroup).removeView(spinnerAmPm)
layout.addView(spinnerHour)
setImeOptions(spinnerHour, 0)
layout.addView(spinnerMinute)
setImeOptions(spinnerMinute, 1)
val spinnerSecond = createSecondPicker(spinnerHour.context)
layout.addView(spinnerSecond)
setImeOptions(spinnerAmPm, 2)
val params = spinnerHour.layoutParams
spinnerSecond.layoutParams = params
layout.addView(spinnerAmPm)
setImeOptions(spinnerAmPm, 3)
}
private fun createSecondPicker(context: Context): NumberPicker {
val spinnerSecond = NumberPicker(context)
spinnerSecond.id = R.id.second
spinnerSecond.setFormatter { i -> String.format("%02d", i) }
spinnerSecond.minValue = 0
spinnerSecond.maxValue = 59
return spinnerSecond
}
Sie müssen diese ID auch in res/values/ids.xml
so dass Sie programmatisch auf das Sekundenfeld verweisen können, indem Sie R.id.second
<item name="second" type="id"/>
Ein Lob an diesen Beitrag für die Idee: https://stackoverflow.com/a/60601077/1709354
- See previous answers
- Weitere Antworten anzeigen