ภาพรวม
DatePicker เป็น Widget สำหรับเลือกวันที่ (วัน/เดือน/ปี) มี 2 โหมด: Calendar View (API 11+) และ Spinner Mode (Classic) ใช้ OnDateChangedListener ฟังเหตุการณ์เมื่อผู้ใช้เปลี่ยนวันที่
XML Attributes สำคัญ
| Attribute | คำอธิบาย |
|---|---|
| android:calendarViewShown | true/false แสดง Calendar View (API 11+) |
| android:spinnersShown | true/false แสดง Spinner (Classic) |
| android:startYear / endYear | จำกัดช่วงปี (Calendar Mode) |
| android:minDate / maxDate | จำกัดวันที่ขั้นต่ำ/สูงสุด (millis since epoch) |
| android:dateTextAppearance | Style สำหรับข้อความวันที่ |
ตัวอย่างพื้นฐาน: Calendar Mode + Listener
1. Layout (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:calendarViewShown="true"
android:spinnersShown="false"
android:startYear="2020"
android:endYear="2030" />
<TextView
android:id="@+id/tvSelectedDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/datePicker"
android:layout_centerHorizontal="true"
android:layout_marginTop="24dp"
android:text="วันที่ที่เลือก: -"
android:textSize="18sp" />
</RelativeLayout>
2. MainActivity.java
package com.example.myapplication;
import android.os.Bundle;
import android.widget.DatePicker;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
private DatePicker datePicker;
private TextView tvSelectedDate;
private Calendar selectedDate = Calendar.getInstance();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
datePicker = findViewById(R.id.datePicker);
tvSelectedDate = findViewById(R.id.tvSelectedDate);
// ตั้งค่าวันที่เริ่มต้น (วันนี้)
updateDisplay();
// Listener: เรียกเมื่อผู้ใช้เปลี่ยนวันที่ (Calendar Mode)
datePicker.setOnDateChangedListener((view, year, monthOfYear, dayOfMonth) -> {
selectedDate.set(year, monthOfYear, dayOfMonth);
updateDisplay();
// Toast แจ้งเตือน (Optional)
String msg = String.format(Locale.getDefault(),
"เปลี่ยนวันที่เป็น: %02d/%02d/%d", dayOfMonth, monthOfYear + 1, year);
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
});
}
private void updateDisplay() {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy (EEEE)", Locale.getDefault());
tvSelectedDate.setText("วันที่ที่เลือก: " + sdf.format(selectedDate.getTime()));
}
}
ตัวอย่างขั้นสูง: Spinner Mode + Validation
<DatePicker
android:id="@+id/datePickerSpinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:calendarViewShown="false"
android:spinnersShown="true"
android:minDate="@{@long/minDateMillis}" // Data Binding
android:maxDate="@{@long/maxDateMillis}" />
// ใน Code: ตั้งค่า min/max Date ด้วยโค้ด
Calendar minCal = Calendar.getInstance();
minCal.add(Calendar.YEAR, -100); // 100 ปีก่อน
datePicker.setMinDate(minCal.getTimeInMillis());
Calendar maxCal = Calendar.getInstance();
maxCal.add(Calendar.YEAR, 10); // 10 ปีข้างหน้า
datePicker.setMaxDate(maxCal.getTimeInMillis());
DatePickerDialog (Dialog แบบ Floating - แนะนำสำหรับ Form)
แทนที่จะวาง DatePicker ใน Layout ตรงๆ มักนิยมใช้ Dialog:
// ใน onClick ของ EditText หรือ Button
DatePickerDialog dialog = new DatePickerDialog(
this,
(view, year, month, dayOfMonth) -> {
Calendar cal = Calendar.getInstance();
cal.set(year, month, dayOfMonth);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());
editText.setText(sdf.format(cal.getTime()));
},
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
);
dialog.show();
// ตั้งค่า Min/Max Date สำหรับ Dialog (API 24+)
dialog.getDatePicker().setMinDate(minDateMillis);
dialog.getDatePicker().setMaxDate(maxDateMillis);
Material Date Picker (Modern - แนะนำใหม่)
Material Components มี Date Picker ใหม่ที่สวยงาม รองรับ Range Selection:
// build.gradle implementation 'com.google.android.material:material:1.11.0' // ใช้งาน MaterialDatePickerpicker = MaterialDatePicker.Builder.datePicker() .setTitleText("เลือกวันที่") .setSelection(MaterialDatePicker.todayInUtcMilliseconds()) .build(); picker.addOnPositiveButtonClickListener(selection -> { String date = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()) .format(new Date(selection)); textView.setText(date); }); picker.show(getSupportFragmentManager(), "DATE_PICKER");
การจัดการ Locale และ Timezone
- DatePicker ใช้ Locale ของ Device อัตโนมัติ
- Calendar.MONTH เริ่มจาก 0 (January = 0) → ต้อง +1 เมื่อแสดงผล
- ใช้
Locale.getDefault()หรือ Locale เฉพาะ (new Locale("th", "TH")) สำหรับการ Format - สำหรับ Timezone: ใช้ Calendar/Date ปกติ (Local Time) หรือ Instant/ZonedDateTime (Java 8+ API 26+)
สรุป
- DatePicker: Widget ใน Layout, 2 โหมด (Calendar/Spinner)
- OnDateChangedListener: ฟังการเปลี่ยนแปลง (Calendar Mode)
- DatePickerDialog: Dialog แบบ Floating, ใช้ใน Form (แนะนำ)
- MaterialDatePicker: UI ทันสมัย, รองรับ Range, Themeable (แนะนำโปรเจกต์ใหม่)
- จำกัดวันที่ได้ด้วย minDate/maxDate หรือ startYear/endYear