私はTimePickerを使用して、ユーザーが時間を選択できるようにしました。こことここも参照してください。しかし、ユーザーに2番目を選択させる方法も見つかりませんでした。これで、ユーザーは時と分を選択できますが、秒は選択できません。02:05:10の時間を設定したい場合は、どうすればよいですか?TimePickerを使用して秒を選択する方法は?
7 に答える
私はGitHubでオープンソースプロジェクトを公開しました。これには秒単位のTimePickerがあります。
https://github.com/IvanKovac/TimePickerWithSeconds
見てください。
迅速で汚い方法の1つは、2つのTimePickersを使用することです。1つは時間、分、もう1つは秒として使用します。最初の数分間で未使用の時間を非表示にします。これは24時間モードでのみ機能します。最初に秒単位のタイムピッカーを宣言する必要があるため、下に配置します。
<RelativeLayout
<TimePicker
android:id="@+id/timePicker_Sec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="76dp" />
<TimePicker
android:id="@+id/timePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/timePicker_Sec"
android:layout_marginLeft="0dp" />
</RelativeLayout>
最善の解決策は、Timeクラスと3つのNumberPickerを使用して、独自のTimePickerを作成することだと思います。
これを回避する最善の方法は、タイムピッカーの代わりに3つの別々の「ナンバーピッカー」を作成することです...私はそれらを線形レイアウト内に配置し、正常に機能しました。
次に、3つの別々の変数内に値を格納するだけです。int Hours、int Minutes、int Secondsを使用して、計算を行います。
これは、ウイルスを含む可能性のある外部ソースをダウンロードせずに回避する方法でした。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<NumberPicker
android:id="@+id/numpicker_hours"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</NumberPicker>
<NumberPicker
android:id="@+id/numpicker_minutes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp">
</NumberPicker>
<NumberPicker
android:id="@+id/numpicker_seconds"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</NumberPicker>
</LinearLayout>
これが秒付きのカスタムTimePickerDialogです。
MainActivity.java
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.NumberPicker;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
final TextView timeTV = findViewById(R.id.time_text_view);
timeTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
View view = View.inflate(MainActivity.this, R.layout.time_dialog, null);
final NumberPicker numberPickerHour = view.findViewById(R.id.numpicker_hours);
numberPickerHour.setMaxValue(23);
numberPickerHour.setValue(sharedPreferences.getInt("Hours", 0));
final NumberPicker numberPickerMinutes = view.findViewById(R.id.numpicker_minutes);
numberPickerMinutes.setMaxValue(59);
numberPickerMinutes.setValue(sharedPreferences.getInt("Minutes", 0));
final NumberPicker numberPickerSeconds = view.findViewById(R.id.numpicker_seconds);
numberPickerSeconds.setMaxValue(59);
numberPickerSeconds.setValue(sharedPreferences.getInt("Seconds", 0));
Button cancel = view.findViewById(R.id.cancel);
Button ok = view.findViewById(R.id.ok);
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setView(view);
final AlertDialog alertDialog = builder.create();
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertDialog.dismiss();
}
});
ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
timeTV.setText(numberPickerHour.getValue() + ":" + numberPickerMinutes.getValue() + ":" + numberPickerSeconds.getValue());
// timeTV.setText(String.format("%1$d:%2$02d:%3$02d", numberPickerHour.getValue(), numberPickerMinutes.getValue(), numberPickerSeconds.getValue()));
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("Hours", numberPickerHour.getValue());
editor.putInt("Minutes", numberPickerMinutes.getValue());
editor.putInt("Seconds", numberPickerSeconds.getValue());
editor.apply();
alertDialog.dismiss();
}
});
alertDialog.show();
}
});
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/time_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
time_dialog.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:gravity="center"
android:orientation="horizontal">
<NumberPicker
android:id="@+id/numpicker_hours"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<NumberPicker
android:id="@+id/numpicker_minutes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" />
<NumberPicker
android:id="@+id/numpicker_seconds"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#ffF0F0F0" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="Cancel"
android:textAllCaps="false" />
<View
android:id="@+id/view2"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#ffF0F0F0" />
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="OK"
android:textAllCaps="true" />
</LinearLayout>
</LinearLayout>
これを行うためにKotlin拡張関数を作成しました。それは厄介ですが、それは仕事を成し遂げます:
/**
* 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
}
res/values/ids.xml
プログラムで秒フィールドを参照できるように、このIDをに追加する必要もあります。R.id.second
<item name="second" type="id"/>
アイデアのためにこの投稿に叫ぶ:https ://stackoverflow.com/a/60601077/1709354
秒単位で独自のタイムピッカーを作成しました。ここで試すことができます。
他の機能をいくつか追加しました。
主なファイルは
my_time_picker_content.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クラス
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クラス
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")
}
}
}