Освой Android играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Элемент DatePicker позволяет пользователю выбрать дату (число, месяц, год). Данный виджет используют как правило на отдельном экране. Также существует похожее по функционалу диалоговое окно DatePickerDialog.
DatePicker находился в разделе Date & Time в Android Studio 3.01. Сейчас на панели инструментов данного компонента нет, поэтому придётся добавлять вручную.
Нужно помнить, что внутренняя нумерация месяцев в Android начинается с 0, поэтому январь = 0, февраль = 1 и т.д. Поэтому как правило, в коде следует прибавлять единицу к значению месяца при работе с датой или наоборот - отнимать единицу, если данные поступают снаружи (например, из текстового поля).
Добавим на экран текстовую метку, кнопку и виджет даты:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_centerHorizontal="true"
android:layout_marginTop="47dp"
android:text="New Button"/>
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/button"
android:layout_centerHorizontal="true"
android:layout_marginTop="48dp"/>
</RelativeLayout>
Пользователь может выбрать любую дату на виджете, а обычный щелчок на кнопке позволит отобразить выбранную дату в текстовой метке. Длительное нажатие на кнопку устанавливает текущую дату на виджете и в текстовой метке.
Настройка даты на самом виджете происходит через метод init(). Изменение даты можно прослушивать через OnDateChangedListener():
package ru.alexanderklimov.datepicker;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Calendar;
public class MainActivity extends AppCompatActivity {
private DatePicker mDatePicker;
private TextView mInfoTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInfoTextView = (TextView) findViewById(R.id.textView);
mDatePicker = (DatePicker) findViewById(R.id.datePicker);
Calendar today = Calendar.getInstance();
mDatePicker.init(today.get(Calendar.YEAR), today.get(Calendar.MONTH),
today.get(Calendar.DAY_OF_MONTH), new DatePicker.OnDateChangedListener() {
@Override
public void onDateChanged(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
Toast.makeText(getApplicationContext(),
"onDateChanged", Toast.LENGTH_SHORT).show();
mInfoTextView.setText("Год: " + year + "\n" + "Месяц: "
+ (monthOfYear + 1) + "\n" + "День: " + dayOfMonth);
}
});
Button changingDateButton = (Button) findViewById(R.id.button);
changingDateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mInfoTextView.setText(new StringBuilder()
// Месяц отсчитывается с 0, поэтому добавляем 1
.append(mDatePicker.getDayOfMonth()).append(".")
.append(mDatePicker.getMonth() + 1).append(".")
.append(mDatePicker.getYear()));
}
});
changingDateButton.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
setCurrentDateOnView();
return true;
}
});
}
// устанавливаем текущую дату
public void setCurrentDateOnView() {
final Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
// set current date into textview
mInfoTextView.setText(new StringBuilder()
// Месяц отсчитывается с 0, поэтому добавляем 1
.append(day).append(".").append(month + 1).append(".")
.append(year));
// Устанавливаем текущую дату для DatePicker
mDatePicker.init(year, month, day, null);
}
}
По умолчанию DatePicker состоит из двух элементов - Spinner и CalendarView. Вы можете настроить внешний вид компонента, если укажете через XML-атрибуты android:calendarViewShown и android:spinnersShown, какой элемент не нужно выводить. Также можно это сделать программно через методы setCalendarViewShown() и setSpinnersShown() (API level 11).
Напишем пример программного управления внешним видом DatePicker:
<?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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<RadioGroup
android:id="@+id/optGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/optCalendar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="CalendarView"/>
<RadioButton
android:id="@+id/optSpinners"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Spinners"/>
<RadioButton
android:id="@+id/optBoth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Both"/>
</RadioGroup>
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:calendarViewShown="true"
android:spinnersShown="false"/>
</LinearLayout>
Код для активности:
package ru.alexanderklimov.datepicker;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.DatePicker;
import android.widget.RadioButton;
import android.widget.RadioGroup;
public class MainActivity extends AppCompatActivity {
private DatePicker mDatePicker;
private RadioButton mCalendarRadionButton;
private RadioButton mSpinnerRadioButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDatePicker = (DatePicker) findViewById(R.id.datePicker);
RadioGroup radioGroup = (RadioGroup) findViewById(R.id.optGroup);
mCalendarRadionButton = (RadioButton) findViewById(R.id.optCalendar);
mSpinnerRadioButton = (RadioButton) findViewById(R.id.optSpinners);
mDatePicker = (DatePicker) findViewById(R.id.datePicker);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (mCalendarRadionButton.isChecked()) {
mDatePicker.setCalendarViewShown(true);
mDatePicker.setSpinnersShown(false);
} else if (mSpinnerRadioButton.isChecked()) {
mDatePicker.setCalendarViewShown(false);
mDatePicker.setSpinnersShown(true);
} else {
mDatePicker.setCalendarViewShown(true);
mDatePicker.setSpinnersShown(true);
}
}
});
}
}
В Android 5.0 (API 21) внешний вид компонента изменился. Поэтому неплохо бы проверить, всё ли работает в старом коде.
Скриншот взят из статьи Криминальное чтиво.