15

任何人都可以告诉如何仅在 android 的日期选择器中显示年份

谢谢

4

7 回答 7

12

首先,创建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();

在此处输入图像描述

在此处输入图像描述

于 2018-11-14T12:43:26.490 回答
6

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 时)。

于 2012-05-29T09:38:16.640 回答
1

您可以像这样从自定义日期选择器中隐藏日期和月份:

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);
    }
于 2020-02-12T08:36:40.777 回答
1

我修改了@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 的答案中获取布局文件和样式。

于 2020-02-12T08:22:14.590 回答
0

我只是有同样的问题,我发现的所有解决方案都不适用于新的 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);
于 2020-09-30T09:27:58.637 回答
0
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>
于 2020-11-11T08:15:53.977 回答
0

我还修改了@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。

于 2021-05-31T14:11:42.977 回答