任何人都可以告诉如何仅在 android 的日期选择器中显示年份
谢谢
首先,创建MonthYearPickerDialog.java类扩展 DialogFragment
public class MonthYearPickerDialog extends DialogFragment {
private static final int MAX_YEAR = 2099;
private DatePickerDialog.OnDateSetListener listener;
public void setListener(DatePickerDialog.OnDateSetListener listener) {
this.listener = listener;
}
@SuppressLint("ResourceAsColor")
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AlertDialogStyle);
LayoutInflater inflater = getActivity().getLayoutInflater();
Calendar cal = Calendar.getInstance();
View dialog = inflater.inflate(R.layout.month_year_picker_dialog, null);
final NumberPicker monthPicker = (NumberPicker) dialog.findViewById(R.id.picker_month);
final NumberPicker yearPicker = (NumberPicker) dialog.findViewById(R.id.picker_year);
monthPicker.setMinValue(1);
monthPicker.setMaxValue(12);
monthPicker.setValue(cal.get(Calendar.MONTH) + 1);
int year = cal.get(Calendar.YEAR);
yearPicker.setMinValue(1900);
yearPicker.setMaxValue(3500);
yearPicker.setValue(year);
builder.setView(dialog).setPositiveButton(Html.fromHtml("<font color='#FF4081'>Ok</font>"), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
listener.onDateSet(null, yearPicker.getValue(), monthPicker.getValue(), 0);
}
}).setNegativeButton(Html.fromHtml("<font color='#FF4081'>Cancel</font>"), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MonthYearPickerDialog.this.getDialog().cancel();
}
});
return builder.create();
}
}
在styles.xml 中粘贴此代码。
<style name="AlertDialogStyle" parent="Theme.AppCompat.Light.Dialog">
<item name="android:textColor">#FF4081</item> // you can change the color of the yearPiker dialog
<item name="android:textColorPrimary">#FF4081</item> // you can change the color of the yearPiker dialog
</style>
创建month_year_picker_dialog.xml
<?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="220dp"
android:layout_height="300dp"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="@color/colorAccent"
android:gravity="top">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:elevation="8dp"
android:gravity="center"
android:text="Year"
android:textColor="#ffffff"
android:textSize="22dp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<NumberPicker
android:id="@+id/picker_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:descendantFocusability="blocksDescendants"
android:visibility="gone"
tools:ignore="RtlCompat">
</NumberPicker>
<NumberPicker
android:id="@+id/picker_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
>
</NumberPicker>
</LinearLayout>
</LinearLayout>
</LinearLayout>
在您的主要课程中(活动)
private DatePickerDialog createDialogWithoutDateField() {
DatePickerDialog dpd = new DatePickerDialog(this, null, 2014, 1, 24);
try {
java.lang.reflect.Field[] datePickerDialogFields = dpd.getClass().getDeclaredFields();
for (java.lang.reflect.Field datePickerDialogField : datePickerDialogFields) {
if (datePickerDialogField.getName().equals("mDatePicker")) {
datePickerDialogField.setAccessible(true);
DatePicker datePicker = (DatePicker) datePickerDialogField.get(dpd);
java.lang.reflect.Field[] datePickerFields = datePickerDialogField.getType().getDeclaredFields();
for (java.lang.reflect.Field datePickerField : datePickerFields) {
Log.i("test", datePickerField.getName());
if ("mDaySpinner".equals(datePickerField.getName())) {
datePickerField.setAccessible(true);
Object dayPicker = datePickerField.get(datePicker);
((View) dayPicker).setVisibility(View.GONE);
}
}
}
}
}
catch (Exception ex) {
}
return dpd;
}
最后,随叫随到
createDialogWithoutDateField().show();
NumberPicker
您还可以使用一些简单的反射来隐藏小部件的日期和月份DatePicker
。请注意,如果 Google 决定重命名成员字段名称,这可能会停止工作。此外,这种方法在使用android:datePickerMode="spinner"
.
// inflate DatePicker, or e.g. get it from a DatePickerDialog:
DatePicker datepicker = ...
// pre-Honeycomb fields:
findAndHideField(datepicker, "mDayPicker");
findAndHideField(datepicker, "mMonthPicker");
// Honeycomb(+) fields:
findAndHideField(datepicker, "mDaySpinner");
findAndHideField(datepicker, "mMonthSpinner");
// Lollipop(+) fields (wrapped in a delegate):
final Object mDatePickerDelegate = findFieldInstance(picker, "mDelegate");
findAndHideField(mDatePickerDelegate, "mDaySpinner");
findAndHideField(mDatePickerDelegate, "mMonthSpinner");
/** find a member field by given name and hide it */
private static void findAndHideField(Object object, String name) {
try {
final Field field = object.getClass().getDeclaredField(name);
field.setAccessible(true);
final View fieldInstance = (View) field.get(object);
fieldInstance.setVisibility(View.GONE);
} catch (Exception e) {
e.printStackTrace();
}
}
/* find a member field by given name and return its instance value */
private static Object findFieldInstance(DatePicker datepicker, String name) {
try {
final Field field = DatePicker.class.getDeclaredField(name);
field.setAccessible(true);
return field.get(datepicker);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
更新:添加了说明如何使此方法与 Android 'Lollipop' 5.0 (API 21+) 一起使用的代码。
免责声明:我不能过分强调这是一个骇人听闻的解决方案,它可能会停止与任何框架更新一起工作(就像首次引入 Android 3.0 时所做的那样,并且再次引入 Android 5.0 时)。
您可以像这样从自定义日期选择器中隐藏日期和月份:
DatePicker datePicker = (DatePicker) datePickerDialogField.get(obj);
DatePicker monPickerPicker = (DatePicker) datePickerDialogField.get(obj);
Field datePickerFields[] = datePickerDialogField.getType().getDeclaredFields();
for (Field datePickerField: datePickerFields) {
//datePickerField
//mMonthSpinner
if (“mDayPicker”.equals(datePickerField.getName()) || “mDaySpinner”.equals(datePickerField
.getName())) {
datePickerField.setAccessible(true);
Object dayPicker = new Object();
dayPicker = datePickerField.get(datePicker);
((View) dayPicker).setVisibility(View.GONE);
}
if (“mMonthpicker”.equals(datePickerField.getName()) || “mMonthSpinner”.equals(datePickerField
.getName())) {
datePickerField.setAccessible(true);
Object dayPicker = new Object();
dayPicker = datePickerField.get(datePicker);
((View) dayPicker).setVisibility(View.GONE);
}
我修改了@agilanbu 的答案,它可以用作:
private fun createDialogWithoutDateField() {
val alertDialog: AlertDialog?
val builder = AlertDialog.Builder(activity, R.style.AlertDialogStyle)
val inflater = activity!!.layoutInflater
val cal = Calendar.getInstance()
val dialog = inflater.inflate(R.layout.month_year_picker_dialog, null)
val monthPicker = dialog.findViewById(R.id.picker_month) as NumberPicker
val yearPicker = dialog.findViewById(R.id.picker_year) as NumberPicker
monthPicker.minValue = 1
monthPicker.maxValue = 12
monthPicker.value = cal.get(Calendar.MONTH) + 1
val year = cal.get(Calendar.YEAR)
yearPicker.minValue = 1900
yearPicker.maxValue = 3500
yearPicker.value = year
builder.setView(dialog).setPositiveButton(Html.fromHtml("<font color='#FF4081'>Ok</font>")){dialogInterface, which ->
//Toast.makeText(applicationContext,"clicked yes",Toast.LENGTH_LONG).show()
val value = yearPicker.value
dialogInterface.cancel()
}
builder.setNegativeButton(Html.fromHtml("<font color='#FF4081'>Cancel</font>")){dialogInterface, which ->
dialogInterface.cancel()
}
alertDialog = builder.create()
// Set other dialog properties
alertDialog.setCancelable(true)
alertDialog.show()
}
您可以在@agilanbu 的答案中获取布局文件和样式。
我只是有同样的问题,我发现的所有解决方案都不适用于新的 Android 版本,因为我无法获得 DatePicker 的反射字段
无论如何,如果您需要代码,我会通过一个对话框来选择一个数字来解决:
SingleNumberPickerDialog.java 代码
public class SingleNumberPickerDialog extends DialogFragment {
public interface IOnNumberSelected {
void onNumberSelected(int num, int requestCode);
}
private static final String TAG = SingleNumberPickerDialog.class.getSimpleName();
private static final String KEY = TAG + ".key";
// Arguments Keys
private static final String KEY_LABEL = KEY + ".label";
private static final String KEY_START_VALUE = KEY + ".startValue";
private static final String KEY_MIN_VALUE = KEY + ".minValue";
private static final String KEY_MAX_VALUE = KEY + ".maxValue";
private static final String KEY_REQUEST_CODE = KEY + ".requestCode";
// Int Values
private static final int INT_UNDEFINED = -0x1;
@BindView(R2.id.tv_label)
protected TextView mtvLabel;
@BindView(R2.id.np_number)
protected NumberPicker mnpNumber;
private IOnNumberSelected mCallback;
private int mRequestCode;
public static SingleNumberPickerDialog newInstance(String label, int startValue, int minValue, int maxValue, int requestCode){
SingleNumberPickerDialog mInstance = new SingleNumberPickerDialog();
Bundle args = new Bundle();
args.putString(KEY_LABEL, label);
args.putInt(KEY_START_VALUE, startValue);
args.putInt(KEY_MIN_VALUE, minValue);
args.putInt(KEY_MAX_VALUE, maxValue);
args.putInt(KEY_REQUEST_CODE, requestCode);
mInstance.setArguments(args);
return mInstance;
}
/** Override Lifecycle Methods **/
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
mCallback = (IOnNumberSelected) context;
} catch (ClassCastException ccE){
Log.e(TAG, ccE);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.dialog_single_number_picker, container, false);
ButterKnife.bind(this, view);
initOnCreateView();
return view;
}
/** Actions Methods **/
@OnClick(R2.id.b_confirm)
void onClickConfirm(View view){
if(mCallback != null){
mCallback.onNumberSelected(mnpNumber.getValue(), mRequestCode);
}
}
/** Private Methods **/
private void initOnCreateView(){
if(getArguments() != null){
initLabel();
initStartValue();
initMinValue();
initMaxValue();
initRequestCode();
}
}
private void initLabel(){
if(getArguments().containsKey(KEY_LABEL)){
mtvLabel.setText(getArguments().getString(KEY_LABEL));
}
}
private void initStartValue(){
if(getArguments().containsKey(KEY_START_VALUE)){
mnpNumber.setValue(getArguments().getInt(KEY_START_VALUE));
}
}
private void initMinValue(){
if(getArguments().containsKey(KEY_MIN_VALUE)){
mnpNumber.setMinValue(getArguments().getInt(KEY_MIN_VALUE));
}
}
private void initMaxValue(){
if(getArguments().containsKey(KEY_MAX_VALUE)){
mnpNumber.setMaxValue(getArguments().getInt(KEY_MAX_VALUE));
}
}
private void initRequestCode(){
if(getArguments().containsKey(KEY_REQUEST_CODE)){
mRequestCode = getArguments().getInt(KEY_REQUEST_CODE);
}
}
}
dialog_single_number_picker.xml 代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:background="@color/black"
android:padding="@dimen/padding_3dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/white"
android:padding="@dimen/padding_22dp">
<TextView
android:id="@+id/tv_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:textColor="@color/black"
android:textSize="@dimen/text_size_20sp"
android:textStyle="bold"
android:padding="@dimen/padding_25dp"/>
<NumberPicker
android:id="@+id/np_number"
android:layout_width="wrap_content"
android:layout_height="@dimen/height_200dp"
android:layout_gravity="center"/>
<Button
android:id="@+id/b_confirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_confirm"
android:paddingStart="@dimen/padding_15dp"
android:paddingEnd="@dimen/padding_15dp"
style="@style/ButtonAccentWhiteStyle"/>
</LinearLayout>
</LinearLayout>
使用示例(您需要在您的活动中实现回调):
int year = DateUtils.getCurrentYear();
SingleNumberPickerDialog mDialog = SingleNumberPickerDialog.newInstance(getString(R.string.label_year), year, year - 50, year + 50, 0x0);
mDialog.setStyle(DialogFragment.STYLE_NO_FRAME, R.style.NoBackgroundDialogStyle);
mDialog.setCancelable(false);
mDialog.show(getSupportFragmentManager(), TAG_DIALOG_YEAR_PICKER);
private void showBirthDayPicker() {
int year = calendar.get(Calendar.YEAR);
final Dialog birthDayDialog = new Dialog(this);
birthDayDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
birthDayDialog.setContentView(R.layout.dialog_birthday);
Button okBtn = birthDayDialog.findViewById(R.id.btn_ok);
Button cancelBtn = birthDayDialog.findViewById(R.id.btn_cancel);
final NumberPicker np = birthDayDialog.findViewById(R.id.birthdayPicker);
np.setMinValue(year - 100);
np.setMaxValue(year - 15);
np.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
setDivider(np, android.R.color.white);
np.setWrapSelectorWheel(false);
np.setValue(year-20);
np.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker numberPicker, int i, int i1) {
}
});
okBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
edtBirthDay.setText(String.valueOf(np.getValue()));
birthDayDialog.dismiss();
}
});
cancelBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
birthDayDialog.dismiss();
}
});
birthDayDialog.show();
}
xml
`enter code here`<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:baselineAligned="false"
android:orientation="vertical" >
<TextView
android:id="@+id/birthday_dialog_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:gravity="center"
android:minHeight="42dp"
android:text="Year lahir"
android:textSize="14sp" />
<NumberPicker
android:id="@+id/birthdayPicker"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center" >
<Button
android:id="@+id/btn_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Cancel" />
<Button
android:id="@+id/btn_ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="OK" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
我还修改了@agilanbu 的答案并更新了@ROHIT LIEN 的答案。注意:它只包含有关年份的信息:
private fun createYearPicker() {
val builder = AlertDialog.Builder(requireContext(), R.style.AppAlertDialogTheme)
val cal = Calendar.getInstance()
val view = layoutInflater.inflate(R.layout.dialog_year_picker, null)
val yearPicker = view.yearPicker as NumberPicker
val year = cal.get(Calendar.YEAR)
yearPicker.minValue = 1900
yearPicker.maxValue = 2021
yearPicker.value = year
builder.setView(view)
val show = builder.show().apply { this.setCancelable(true) }
view.btnNegative.setOnClickListener {
show.dismiss()
}
view.btnPositive.setOnClickListener {
etvDate.setText(yearPicker.value.toString())
saveDate(yearPicker.value)
show.dismiss()
}
}
尽管我在布局中添加了 2 个按钮,但布局是相同的:
btn阳性 btn阴性
并将其从样式中删除。这是为了防止您为正面和负面按钮定制设计。+ monthPicker 数字选择器已删除。
注意: btnPositive 和 btnNegative 是布局中按钮的 ID。