Androidでは日付や時間をユーザー入力のために DatePicker や TimePicker を使うとユーザビリティが上がります。Kotlinではどのように設定するのでしょうか確認してみます。
API 29
DialogFragment
Pickerの実装についてはAndroid 3.0 以上で DialogFragment を使うことが推奨されています。また、Time Picker はDate Picker と同様に作成できます。
尚、Javaのケースは以下を参考に
DatePicker
解説では、Layout の android:onClick で Activity のメソッドが呼ばれ、Picker の DialogFragment が表示されます。
1 2 3 |
<Button ... android:onClick="showTimePickerDialog" /> |
では、設定したデータをどうやって取り出すのか?
Layout での android:onClick をやめてしまうという方法もあるようですが
Stackoverflowによると
Picker の DatePickerDialog.OnDateSetListener を使って、 MainActivity にデータを戻してやればいいようです
DatePick.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
package your.package.name import android.os.Bundle import android.app.DatePickerDialog import android.app.Dialog import android.content.Context import androidx.fragment.app.DialogFragment; import java.util.Calendar class DatePick : DialogFragment(), DatePickerDialog.OnDateSetListener { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val c = Calendar.getInstance() val year = c.get(Calendar.YEAR) val month = c.get(Calendar.MONTH) val day = c.get(Calendar.DAY_OF_MONTH) return DatePickerDialog( this.context as Context, activity as MainActivity?, year, month, day) } override fun onDateSet(view: android.widget.DatePicker, year: Int, monthOfYear: Int, dayOfMonth: Int) { } } |
元の設定:
return new DatePickerDialog(activity, this, year, month, day);
新しい設定:
return new DatePickerDialog(this.context as Context, activity asMainActivity?, year, month, day);
DatePickerDialog() の第2引数が自分自信 this になっているので
これを、MainActivity? にしてやります
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
package your.package.name import android.app.DatePickerDialog import androidx.fragment.app.FragmentActivity; import android.os.Bundle import android.view.View import android.widget.DatePicker // need to import for Kotlin Android Extensions import kotlinx.android.synthetic.main.activity_main.* import java.util.Locale class MainActivity : FragmentActivity(), DatePickerDialog.OnDateSetListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } override fun onDateSet(view: DatePicker, year: Int, monthOfYear: Int, dayOfMonth: Int) { val str = String.format(Locale.US, "%d/%d/%d", year, monthOfYear+1, dayOfMonth) textView.text = str } fun showDatePickerDialog(v: View) { val newFragment = DatePick() newFragment.show(supportFragmentManager, "datePicker") } } |
DialogFragment にあった
onDateSet() を持ってきてデータを受け取ります
レイアウトです
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="@string/no_date" android:textSize="50sp" android:textColor="#000" android:layout_margin="30dp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="showDatePickerDialog" android:layout_margin="30dp" android:text="@string/pick_date" /> </LinearLayout > |
リソース
strings.xml
1 2 3 4 5 |
<resources> <string name="button">YourAppName</string> <string name="no_date">No Data</string> <string name="pick_date">Pick Date</string> </resources> |
Time Picker
Time Pickerも同様に作成できます。
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package your.package.name import android.app.TimePickerDialog import android.os.Bundle import android.support.v4.app.FragmentActivity import android.view.View import android.widget.TimePicker // need to import for Kotlin Android Extensions import kotlinx.android.synthetic.main.activity_main.* import java.util.* class MainActivity : FragmentActivity(), TimePickerDialog.OnTimeSetListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } override fun onTimeSet(view: TimePicker, hourOfDay: Int, minute: Int) { val str = String.format(Locale.US, "%d:%d", hourOfDay, minute) // use the plug in of Kotlin Android Extensions textView.text = str } // called by Buttton tapping fun showTimePickerDialog(v: View) { val newFragment = TimePick() newFragment.show(supportFragmentManager, "timePicker") } } |
TimePick.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package your.package.name import android.app.Dialog import android.widget.TimePicker import android.app.TimePickerDialog import android.icu.util.Calendar import android.os.Bundle import android.support.v4.app.DialogFragment class TimePick : DialogFragment(), TimePickerDialog.OnTimeSetListener { // Bundle sould be nullable, Bundle? override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { // to initialize a Calender instance val c = Calendar.getInstance() // at the first, to get the system current hour and minute val hour = c.get(Calendar.HOUR_OF_DAY) val minute = c.get(Calendar.MINUTE) return TimePickerDialog( activity, // in order to return parameters to MainActivity activity as MainActivity?, hour, minute, true) } override fun onTimeSet(view: TimePicker, hourOfDay: Int, minute: Int) { // } } |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="@string/no_data" android:textSize="50sp" android:textColor="#000" android:layout_margin="30dp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="showTimePickerDialog" android:layout_margin="30dp" android:text="@string/pick_time" /> </LinearLayout > |
strings.xml
1 2 3 4 5 |
<resources> <string name="button">YourAppName</string> <string name="no_data">"No Data"</string> <string name="pick_time">Pick Time</string> </resources> |
Reference:
Picker API Developer’s Guide | Picker | Google Developers