19 Stimmen

Wie man eine Sekunde mit TimePicker, Android, auswählt

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?

1voto

Martin Olariaga Punkte 169

Ich habe meine eigene Zeitauswahl mit Sekunden erstellt. Sie können ihn ausprobieren aquí .

Time picker with seconds

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")
        }
    }
}

0voto

Nate Punkte 121

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X