Android DatePicker 更改为仅月和年

Posted

技术标签:

【中文标题】Android DatePicker 更改为仅月和年【英文标题】:Android DatePicker change to only Month and Year 【发布时间】:2014-01-23 23:53:43 【问题描述】:

我有一个 DatePickerDialog,我只想查看月份和年份。如何更改此代码?

public void chooseDate2(View v) 
    new DatePickerDialog(
        act.this,
        d1,
        dateAndTime1.get(Calendar.YEAR) + 2,
        dateAndTime1.get(Calendar.MONTH),
        dateAndTime1.get(Calendar.DAY_OF_MONTH)
    ).show();

private void updateLabel2() 
    scadenza.setText(fmtDateAndTime.format(dateAndTime1.getTime()));           

DatePickerDialog.OnDateSetListener d1=new DatePickerDialog.OnDateSetListener() 
    public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) 
        dateAndTime1.set(Calendar.YEAR, year);
        dateAndTime1.set(Calendar.MONTH, monthOfYear);
        dateAndTime1.set(Calendar.DAY_OF_MONTH, dayOfMonth);
        updateLabel2();
    
;

谢谢

【问题讨论】:

请看这个链接。这个问题以前有人问过。 ***.com/questions/10673842/… android - Hide date field in datepickerdialog的可能重复 【参考方案1】:

由于我最近自己偶然发现了这个问题,因此我测试了这篇文章中的多个解决方案以及 *** 上的类似问题。

不幸的是,我没有找到特别适用于 Android 5+ 的有效解决方案

我最终实现了我自己的嵌入两个 NumberPicker 的简单 DialogFragment。这应该与 3.0 及更高版本的所有版本兼容。

代码如下:

  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;
  

  @Override
  public Dialog onCreateDialog(Bundle savedInstanceState) 
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Get the layout inflater
    LayoutInflater inflater = getActivity().getLayoutInflater();

    Calendar cal = Calendar.getInstance();

    View dialog = inflater.inflate(R.layout.date_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(0);
    monthPicker.setMaxValue(11);
    monthPicker.setValue(cal.get(Calendar.MONTH));

    int year = cal.get(Calendar.YEAR);
    yearPicker.setMinValue(year);
    yearPicker.setMaxValue(MAX_YEAR);
    yearPicker.setValue(year);

    builder.setView(dialog)
        // Add action buttons
        .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() 
          @Override
          public void onClick(DialogInterface dialog, int id) 
            listener.onDateSet(null, yearPicker.getValue(), monthPicker.getValue(), 0);
          
        )
        .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() 
          public void onClick(DialogInterface dialog, int id) 
            MonthYearPickerDialog.this.getDialog().cancel();
          
        );
    return builder.create();
  

还有布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_
              android:layout_
              android:orientation="vertical">

    <LinearLayout
        android:layout_
        android:layout_
        android:layout_gravity="center"
        android:orientation="horizontal">

        <NumberPicker
            android:id="@+id/picker_month"
            android:layout_
            android:layout_
            android:layout_marginEnd="20dp"
            android:layout_marginRight="20dp">

        </NumberPicker>

        <NumberPicker
            android:id="@+id/picker_year"
            android:layout_
            android:layout_>

        </NumberPicker>

    </LinearLayout>
</LinearLayout>

要显示布局,请使用:

MonthYearPickerDialog pd = new MonthYearPickerDialog();
pd.setListener(this);
pd.show(getFragmentManager(), "MonthYearPickerDialog");

【讨论】:

非常适合我。唯一的问题是默认的 onDateSet 是这种格式: onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) |但在您的自定义对话框中,它是 listener.onDateSet(null, 0, monthPicker.getValue(), yearPicker.getValue()); |因此,您将年份设置为“dayOfMonth” 谢谢!在 Android 6.0 上运行良好。 对于 API 28,您应该使用 getSupportFragmentManager() 而不是 getFragmentManager() 不知道为什么,但我无法设置listener.onDateSet(null, yearPicker.getValue(), monthPicker.getValue(), 0); 我不得不将第一个参数更改为DatePicker(context)。它一直向我显示 non-null value set to null 错误。希望对你有帮助 为我工作。谢谢【参考方案2】:

我不推荐使用反射来做这种事情。

有一种更简单、更漂亮的方法:

((ViewGroup) datePickerDialog.getDatePicker()).findViewById(Resources.getSystem().getIdentifier("day", "id", "android")).setVisibility(View.GONE);

请注意,DatePickerDialog 中的 .getDatePicker() 方法适用于 API LEVEL &gt;= 11

此外,它不适用于 API LEVEL >= 21。

【讨论】:

对于我们这些不熟悉DatePickers 的人,您必须在使用此之前申请android:calendarViewShown="false" 它在 Android Studio 中不工作,但在 Eclipse 上工作正常,有什么原因吗?? @EvertonFernandesRosario API LEVEL >= 21 的任何解决方法.?? @EvertonFernandesRosario 这不适用于 nought(7.0)【参考方案3】:

试试下面的代码。它将显示一个DatePicker,只有年和月(没有日)

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;
    

此方法返回一个日期选择器对话框。因此,在您的按钮的onClick 方法中添加以下代码以显示您的对话框。

createDialogWithoutDateField().show();

【讨论】:

看我的编辑答案,我测试代码并对其进行一些更改,它与我合作得很好,尝试并反馈给我 非常感谢。请看我的其他问题?[***.com/questions/21343408/… 让我们continue this discussion in chat 反射调用类中可用的方法。这种方法可能会在下一个版本的 Android 中消失得无影无踪。反射不是好的选择。 反射,或修改布局以隐藏列始终是一个 hacky 解决方案,并且从长远来看很容易崩溃。相反,应该真正制作自己的组件。请参阅 Stephan 对此问题的回答:***.com/a/31653048/1026805【参考方案4】:

Stephan Klein 答案的更多高级形式。

因为我要求将 年份设为可选。我还处理了 2 月 28 日 之类的日期,还处理了 闰年

MonthYearPickerDialog

public class MonthYearPickerDialog extends DialogFragment 

    private DatePickerDialog.OnDateSetListener listener;
    private int daysOfMonth = 31;

    private NumberPicker monthPicker;
    private NumberPicker yearPicker;
    private NumberPicker dayPicker;

    private Calendar cal = Calendar.getInstance();

    public static final String MONTH_KEY = "monthValue";
    public static final String DAY_KEY = "dayValue";
    public static final String YEAR_KEY = "yearValue";

    int monthVal = -1 , dayVal = -1 , yearVal =-1 ;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        Bundle extras = getArguments();
        if(extras != null)
            monthVal = extras.getInt(MONTH_KEY , -1);
            dayVal = extras.getInt(DAY_KEY , -1);
            yearVal = extras.getInt(YEAR_KEY , -1);
        
    

    public static MonthYearPickerDialog newInstance(int monthIndex , int daysIndex , int yearIndex) 
        MonthYearPickerDialog f = new MonthYearPickerDialog();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putInt(MONTH_KEY, monthIndex);
        args.putInt(DAY_KEY, daysIndex);
        args.putInt(YEAR_KEY, yearIndex);
        f.setArguments(args);

        return f;
    

    public void setListener(DatePickerDialog.OnDateSetListener listener) 
        this.listener = listener;
    

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) 

        //getDialog().setTitle("Add Birthday");

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        // Get the layout inflater
        LayoutInflater inflater = getActivity().getLayoutInflater();

        View dialog = inflater.inflate(R.layout.month_year_picker, null);
        monthPicker = (NumberPicker) dialog.findViewById(R.id.picker_month);
        yearPicker = (NumberPicker) dialog.findViewById(R.id.picker_year);
        dayPicker = (NumberPicker) dialog.findViewById(R.id.picker_day);

        monthPicker.setMinValue(1);
        monthPicker.setMaxValue(12);


        if(monthVal != -1)// && (monthVal > 0 && monthVal < 13))
            monthPicker.setValue(monthVal);
        else
            monthPicker.setValue(cal.get(Calendar.MONTH) + 1);

        monthPicker.setDisplayedValues(new String[]"Jan","Feb","Mar","Apr","May","June","July",
                "Aug","Sep","Oct","Nov","Dec");


        dayPicker.setMinValue(1);
        dayPicker.setMaxValue(daysOfMonth);

        if(dayVal != -1)
            dayPicker.setValue(dayVal);
        else
            dayPicker.setValue(cal.get(Calendar.DAY_OF_MONTH));

        monthPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() 
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) 
                switch (newVal)
                    case 1:case 3:case 5:
                    case 7:case 8:case 10:
                    case 12:
                        daysOfMonth = 31;
                        dayPicker.setMaxValue(daysOfMonth);
                        break;
                    case 2:
                        daysOfMonth = 28;
                        dayPicker.setMaxValue(daysOfMonth);
                        break;

                    case 4:case 6:
                    case 9:case 11:
                        daysOfMonth = 30;
                        dayPicker.setMaxValue(daysOfMonth);
                        break;
                

            
        );

        int maxYear = cal.get(Calendar.YEAR);//2016
        final int minYear = 1916;//1997;
        int arraySize = maxYear - minYear;

        String[] tempArray = new String[arraySize];
        tempArray[0] = "---";
        int tempYear = minYear+1;

        for(int i=0 ; i < arraySize; i++)
            if(i != 0)
                tempArray[i] = " " + tempYear + "";
            
            tempYear++;
        
        Log.i("", "onCreateDialog: " + tempArray.length);
        yearPicker.setMinValue(minYear+1);
        yearPicker.setMaxValue(maxYear);
        yearPicker.setDisplayedValues(tempArray);

        if(yearVal != -1)
            yearPicker.setValue(yearVal);
        else
            yearPicker.setValue(tempYear -1);

        yearPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() 
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) 
                try 
                    if(isLeapYear(picker.getValue()))
                        daysOfMonth = 29;
                        dayPicker.setMaxValue(daysOfMonth);
                    
                catch (Exception e)
                    e.printStackTrace();
                
            
        );


        builder.setView(dialog)
                // Add action buttons
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() 
                    @Override
                    public void onClick(DialogInterface dialog, int id) 
                        int year = yearPicker.getValue();
                        if(year == (minYear+1))
                            year = 1904;
                        
                        listener.onDateSet(null, year, monthPicker.getValue(), dayPicker.getValue());
                    
                )
                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() 
                    public void onClick(DialogInterface dialog, int id) 
                        MonthYearPickerDialog.this.getDialog().cancel();
                    
                );

        return builder.create();
    

    public static boolean isLeapYear(int year) 
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365;
    

我这样称呼它

Calendar calendar = Calendar.getInstance();

        if(etBirthday.getText().length()> 0  )
            if(checkIsYearAvailable(etBirthday.getText().toString().trim()))
                calendar = DateTimeOp.getCalendarFromFormat(etBirthday.getText().toString().trim(), Constants.dateFormat21);
            else
                calendar = DateTimeOp.getCalendarFromFormat(etBirthday.getText().toString().trim() + ", 1917",Constants.dateFormat21);
        

        MonthYearPickerDialog pd = MonthYearPickerDialog.newInstance(calendar.get(Calendar.MONTH) + 1,
                calendar.get(Calendar.DAY_OF_MONTH),calendar.get(Calendar.YEAR));

        pd.setListener(new DatePickerDialog.OnDateSetListener() 
            @Override
            public void onDateSet(DatePicker view, int selectedYear, int selectedMonth, int selectedDay) 

                String formatedDate = "";

                if(selectedYear == 1904)
                
                    String currentDateFormat = selectedMonth + "/" + selectedDay;// + "/" + selectedYear;  //"MM/dd/yyyy"
                    formatedDate = DateTimeOp.oneFormatToAnother(currentDateFormat, Constants.dateFormat20, Constants.dateFormat24);
                
                else
                    String currentDateFormat = selectedMonth + "/" + selectedDay + "/" + selectedYear;  //"MM/dd/yyyy"
                    formatedDate = DateTimeOp.oneFormatToAnother(currentDateFormat, Constants.dateFormat0, Constants.dateFormat21);
                

                etBirthday.setText(formatedDate);
            
        );
        pd.show(getFragmentManager(), "MonthYearPickerDialog");

month_year_picker.xml

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical">



    <LinearLayout
        android:layout_
        android:layout_
        android:layout_gravity="center"
        android:orientation="horizontal">

        <NumberPicker
            android:id="@+id/picker_month"
            android:layout_
            android:layout_
            android:layout_marginEnd="20dp"
            android:layout_marginRight="20dp" />


        <NumberPicker
            android:id="@+id/picker_day"
            android:layout_
            android:layout_
            android:layout_marginEnd="20dp"
            android:layout_marginRight="20dp" />

        <NumberPicker
            android:id="@+id/picker_year"
            android:layout_
            android:layout_ />

    </LinearLayout>
</LinearLayout>

【讨论】:

也请分享month_year_picker布局。 @ShajeelAfzal 我已经添加了它 @Nepster 是否适用于 android lollipop 及以上版本? @Nepster 可以分享DateTimeOp类的代码吗?【参考方案5】:

聚会迟到了。但是如果有人在寻找 Kotlin 版本,我会重写 @Stephan Klein 的 anwser,将其更改为 Kotlin,具有数据绑定样式、月份显示和日期输入。

所以,如果您正在寻找月份-年份选择器,您可以创建 Class MonthYearPickerDialog

class MonthYearPickerDialog(val date: Date = Date()) : DialogFragment() 

    companion object 
        private const val MAX_YEAR = 2099
    

    private lateinit var binding: DialogMonthYearPickerBinding

    private var listener: OnDateSetListener? = null

    fun setListener(listener: OnDateSetListener?) 
        this.listener = listener
    

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog 
        binding = DialogMonthYearPickerBinding.inflate(requireActivity().layoutInflater)
        val cal: Calendar = Calendar.getInstance().apply  time = date 

        binding.pickerMonth.run 
            minValue = 0
            maxValue = 11
            value = cal.get(Calendar.MONTH)
            displayedValues = arrayOf("Jan","Feb","Mar","Apr","May","June","July",
                "Aug","Sep","Oct","Nov","Dec")
        

        binding.pickerYear.run 
            val year = cal.get(Calendar.YEAR)
            minValue = year
            maxValue = MAX_YEAR
            value = year
        

        return AlertDialog.Builder(requireContext())
            .setTitle("Please Select View Month")
            .setView(binding.root)
            .setPositiveButton("Ok")  _, _ -> listener?.onDateSet(null, binding.pickerYear.value, binding.pickerMonth.value, 1) 
            .setNegativeButton("Cancel")  _, _ -> dialog?.cancel() 
            .create()
    

使用它的 xml dialog_month_year_picker

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout
        android:layout_
        android:layout_
        android:gravity="center"
        android:orientation="horizontal">

        <NumberPicker
            android:id="@+id/pickerYear"
            android:layout_
            android:layout_
            android:layout_marginEnd="20dp" />

        <NumberPicker
            android:id="@+id/pickerMonth"
            android:layout_
            android:layout_ />

    </LinearLayout>
</layout>

要使用它,请调用:

MonthYearPickerDialog(date).apply 
    setListener  view, year, month, dayOfMonth ->
        Toast.makeText(requireContext(), "Set date: $year/$month/$dayOfMonth", Toast.LENGTH_LONG).show()
    
    show(supportFragmentManager, "MonthYearPickerDialog")

看起来像这样:

在 Fragment 中使用时的注意事项

由于 Kotlin apply 将隐藏关键字 this,并且 MonthYearPickerDialog 也是 Fragment,因此您必须确保在 show() 方法中调用正确的 FragmentManager。否则 FATAL IllegalStateException: not associated with a fragment manager. 可能会引发。

例如,如果你想在MyFragment中调用这个,使用@来指定哪个“this”是:

MonthYearPickerDialog(date).apply 
    setListener  view, year, month, dayOfMonth ->
        Toast.makeText(requireContext(), "Set date: $year/$month/$dayOfMonth", Toast.LENGTH_LONG).show()
    
    show(this@MyFragment.parentFragmentManager, "MonthYearPickerDialog")

如果答案有帮助,请点赞:)

【讨论】:

带有 标签的 root 不起作用,所以我删除了标签。 我建议将此添加到 NumberPicker XML android:descendantFocusability="blocksDescendants" @FaizanHaidarKhan 根和&lt;layout&gt; 是视图绑定结构的一部分。您可以将其与Binding 类一起删除,并用老式的findViewById 方法替换它们,就可以了;)【参考方案6】:

“Xar E Ahmer”的答案很容易理解,而且符合要求。根据我的要求,我使用了相同的内容并进行了以下修改。

“Xar E Ahmer”答案的 Kotlin 转换。 添加了一些错误处理案例。 闰年 2 月 28 日/29 日的更多交割。 每年复选框以排除年份(为用户简化)。

MonthYearPickerDialog.kt

package com.example.*******

import android.app.AlertDialog
import android.app.DatePickerDialog
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.CheckBox
import android.widget.CompoundButton
import android.widget.NumberPicker
import android.app.DialogFragment
import java.util.Calendar

class MonthYearPickerDialog : DialogFragment() 

    private var listener: DatePickerDialog.OnDateSetListener? = null
    private var daysOfMonth = 31

    private var monthPicker: NumberPicker? = null
    private var yearPicker: NumberPicker? = null
    private var dayPicker: NumberPicker? = null
    private var isEveryYearcheckBox: CheckBox? = null

    private val cal = Calendar.getInstance()

    internal var monthVal = -1
    internal var dayVal = -1
    internal var yearVal = -1
    internal var maxYearVal = -1
    internal var minYearVal = -1

    override fun onAttach(context: Context) 
        super.onAttach(context)
    

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)

        val extras = arguments
        if (extras != null) 
            monthVal = extras.getInt(MONTH_KEY, -1)
            dayVal = extras.getInt(DAY_KEY, -1)
            yearVal = extras.getInt(YEAR_KEY, -1)
            maxYearVal = extras.getInt(MAX_YEAR_KEY, -1)
            minYearVal = extras.getInt(MIN_YEAR_KEY, -1)
        
        maxYearVal = if (maxYearVal == -1) 2025 else maxYearVal
        minYearVal = if (minYearVal == -1) 1925 else minYearVal

        if (minYearVal > maxYearVal) 
            val tempVal = maxYearVal
            maxYearVal = minYearVal
            minYearVal = tempVal
        
    

    fun setListener(listener: DatePickerDialog.OnDateSetListener) 
        this.listener = listener
    

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog 

        val builder = AlertDialog.Builder(activity)
        // Get the layout inflater
        val inflater = activity.layoutInflater

        val dialog = inflater.inflate(R.layout.month_year_picker, null)
        monthPicker = dialog.findViewById<View>(R.id.datepicker_month) as NumberPicker
        yearPicker = dialog.findViewById<View>(R.id.datepicker_year) as NumberPicker
        dayPicker = dialog.findViewById<View>(R.id.datepicker_day) as NumberPicker

        isEveryYearcheckBox = dialog.findViewById<View>(R.id.datepicker_isyearcheckBox) as CheckBox
        isEveryYearcheckBox!!.setOnCheckedChangeListener  compoundButton, b ->
            if (b) 
                yearPicker!!.isEnabled = false
                yearPicker!!.value = minYearVal - 1
             else 
                yearPicker!!.isEnabled = true
                if (yearVal != -1 && yearVal != 1904)
                    yearPicker!!.value = yearVal
                else 
                    yearPicker!!.value = cal.get(Calendar.YEAR)
                
            
            if (monthPicker!!.value == 2) 
                daysOfMonth = 28
                if (isLeapYear(yearPicker!!.value)) 
                    daysOfMonth = 29
                
                dayPicker!!.maxValue = daysOfMonth
            
        

        monthPicker!!.minValue = 1
        monthPicker!!.maxValue = 12

        if (monthVal != -1)
            monthPicker!!.value = monthVal
        else
            monthPicker!!.value = cal.get(Calendar.MONTH) + 1

        monthPicker!!.displayedValues = arrayOf("Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec")

        dayPicker!!.minValue = 1
        dayPicker!!.maxValue = daysOfMonth

        if (dayVal != -1)
            dayPicker!!.value = dayVal
        else
            dayPicker!!.value = cal.get(Calendar.DAY_OF_MONTH)

        monthPicker!!.setOnValueChangedListener  picker, oldVal, newVal ->
            when (newVal) 
                1, 3, 5, 7, 8, 10, 12 -> 
                    daysOfMonth = 31
                    dayPicker!!.maxValue = daysOfMonth
                
                2 -> 
                    daysOfMonth = 28
                    if (isLeapYear(yearPicker!!.value)) 
                        daysOfMonth = 29
                    
                    dayPicker!!.maxValue = daysOfMonth
                

                4, 6, 9, 11 -> 
                    daysOfMonth = 30
                    dayPicker!!.maxValue = daysOfMonth
                
            
        

        val maxYear = maxYearVal 
        val minYear = minYearVal 
        val arraySize = maxYear - minYear + 2

        val tempArray = arrayOfNulls<String>(arraySize)
        tempArray[0] = "---"
        var tempYear = minYear - 1

        for (i in 0 until arraySize) 
            if (i != 0) 
                tempArray[i] = " $tempYear"
            
            tempYear++
        
        Log.i("", "onCreateDialog: " + tempArray.size)
        yearPicker!!.minValue = minYear - 1
        yearPicker!!.maxValue = maxYear
        yearPicker!!.displayedValues = tempArray

        if (yearVal != -1 && yearVal != 1904) 
            yearPicker!!.value = yearVal
         else 
            isEveryYearcheckBox!!.isChecked = false
            yearPicker!!.isEnabled = false
            yearPicker!!.value = minYear - 1
        
        if (monthPicker!!.value == 2) 
            daysOfMonth = 28
            if (isLeapYear(yearPicker!!.value)) 
                daysOfMonth = 29
            
            dayPicker!!.maxValue = daysOfMonth
        

        yearPicker!!.setOnValueChangedListener  picker, oldVal, newVal ->
            try 
                daysOfMonth = 28
                if (isLeapYear(picker.value)) 
                    daysOfMonth = 29
                
                dayPicker!!.maxValue = daysOfMonth
             catch (e: Exception) 
                e.printStackTrace()
            
        

        builder.setView(dialog)
                // Add action buttons
                .setPositiveButton(R.string.ok)  dialog, id ->
                    var year = yearPicker!!.value
                    if (year == minYear - 1) 
                        year = 1904
                    
                    listener!!.onDateSet(null, year, monthPicker!!.value, dayPicker!!.value)
                
                .setNegativeButton(R.string.cancel)  dialog, id -> this@MonthYearPickerDialog.dialog.cancel() 

        return builder.create()
    

    companion object 

        val MONTH_KEY = "monthValue"
        val DAY_KEY = "dayValue"
        val YEAR_KEY = "yearValue"
        val MAX_YEAR_KEY = "maxyearValue"
        val MIN_YEAR_KEY = "minyearValue"

        fun newInstance(monthIndex: Int, daysIndex: Int, yearIndex: Int, maxYearIndex: Int, minYearIndex: Int): MonthYearPickerDialog 

            val f = MonthYearPickerDialog()

            // Supply num input as an argument.
            val args = Bundle()
            args.putInt(MONTH_KEY, monthIndex)
            args.putInt(DAY_KEY, daysIndex)
            args.putInt(YEAR_KEY, yearIndex)
            args.putInt(MAX_YEAR_KEY, maxYearIndex)
            args.putInt(MIN_YEAR_KEY, minYearIndex)
            f.arguments = args

            return f
        

        fun isLeapYear(year: Int): Boolean 
            val cal = Calendar.getInstance()
            cal.set(Calendar.YEAR, year)
            return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365
        
    

month_year_picker.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical">

    <CheckBox
        android:id="@+id/datepicker_isyearcheckBox"
        android:layout_
        android:layout_
        android:checked="false"
        android:layout_gravity="center"
        android:paddingTop="20dp"
        android:paddingBottom="20dp"
        android:text="Every year" />

    <LinearLayout
        android:layout_
        android:layout_
        android:layout_gravity="center"
        android:orientation="horizontal">

        <NumberPicker
            android:id="@+id/datepicker_month"
            android:layout_
            android:layout_
            android:layout_marginEnd="20dp"
            android:layout_marginRight="20dp" />

        <NumberPicker
            android:id="@+id/datepicker_day"
            android:layout_
            android:layout_
            android:layout_marginEnd="20dp"
            android:layout_marginRight="20dp" />

        <NumberPicker
            android:id="@+id/datepicker_year"
            android:layout_
            android:layout_ />

    </LinearLayout>
</LinearLayout>

JAVA中不同测试用例的使用示例

Calendar calendar = Calendar.getInstance();
// current date 
MonthYearPickerDialog pd = MonthYearPickerDialog.Companion.newInstance(calendar.get(Calendar.MONTH) + 1,
        calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.YEAR), -1, -1);

// SSTODO for testing
// no year
//MonthYearPickerDialog pd = MonthYearPickerDialog.newInstance(calendar.get(Calendar.MONTH) + 1,
//        calendar.get(Calendar.DAY_OF_MONTH), -1, -1, -1);

// minimum year 2020
//MonthYearPickerDialog pd = MonthYearPickerDialog.newInstance(calendar.get(Calendar.MONTH) + 1,
//        calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.YEAR), -1, 2020);

// maximum year 2018
//MonthYearPickerDialog pd = MonthYearPickerDialog.newInstance(calendar.get(Calendar.MONTH) + 1,
//        calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.YEAR), 2018, -1);

// maximum year 2019, minimum year 2019
//MonthYearPickerDialog pd = MonthYearPickerDialog.newInstance(calendar.get(Calendar.MONTH) + 1,
//        calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.YEAR), 2019, 2019);

// maximum year 100, minimum year 5000
//MonthYearPickerDialog pd = MonthYearPickerDialog.newInstance(calendar.get(Calendar.MONTH) + 1,
//        calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.YEAR), 100, 5000);

// maximum year 100, minimum year 5000, year 99
//MonthYearPickerDialog pd = MonthYearPickerDialog.newInstance(calendar.get(Calendar.MONTH) + 1,
//        calendar.get(Calendar.DAY_OF_MONTH), 99, 100, 5000);

pd.setListener(new DatePickerDialog.OnDateSetListener() 
          @Override
          public void onDateSet(DatePicker view, int selectedYear, int selectedMonth, int selectedDay) 

              String formatedDate = "";
              String currentDateFormat = "";
              if(selectedYear == 1904)  // no year
              
                  currentDateFormat = selectedMonth + "/" + selectedDay; //"MM/dd"
              
              else 
                  currentDateFormat = selectedMonth + "/" + selectedDay + "/" + selectedYear;  //"MM/dd/yyyy"
              
              Toast.makeText(MainActivityTestOne.this, "Selected Date ( MM/dd  or. MM/dd/yyyy ) : " + currentDateFormat, Toast.LENGTH_LONG).show();
          
);
pd.show(getFragmentManager(), STRING_DATE_PICKER);

对于想要“日期”对象作为返回值的用户:-

我们可以根据以下返回的日、月和年值创建日期对象(请更正任何语法错误)

SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
String currentDateString = selectedDay + "-" selectedMonth + "-" + selectedYear; 
long millis = format.parse(currentDateString).getTime();

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis( millis );
int date = calendar.get(CALENDAR.DATE);

【讨论】:

【参考方案7】:

它对我有用...试试这个

    monthPicker.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                Calendar mcurrentDate = Calendar.getInstance();
              String myFormat = "MMMM yyyy";
              SimpleDateFormat sdf = new SimpleDateFormat(myFormat);
                DatePickerDialog monthDatePickerDialog = new DatePickerDialog(getActivity(),
                        AlertDialog.THEME_HOLO_LIGHT, new DatePickerDialog.OnDateSetListener() 
                    @Override
                    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) 
                        mcurrentDate.set(Calendar.YEAR, year);
                        mcurrentDate.set(Calendar.MONTH, month);
                        monthPicker.setText(sdf.format(mcurrentDate.getTime()));
                        mDay = dayOfMonth;
                        mMonth = month;
                        mYear = year;
                    
                , mYear, mMonth, mDay)
                    @Override
                    protected void onCreate(Bundle savedInstanceState) 
                        super.onCreate(savedInstanceState);
                        getDatePicker().findViewById(getResources().getIdentifier("day","id","android")).setVisibility(View.GONE);
                    
                ;
                monthDatePickerDialog.setTitle("Select month And Year");
                monthDatePickerDialog.show();
            
        );

【讨论】:

【参考方案8】:

这是一个老问题,但现在你可以使用“BetterPickers”:

https://github.com/code-troopers/android-betterpickers

并使用 ExpirationPicker。

希望这能为那些在谷歌上广泛搜索的其他一些迷失的灵魂解决这个问题。

【讨论】:

我检查了ExpirationPicker,问题是它只能选择即将到来的年份和月份。我的意思是,我们不能选择“1970 年 4 月”。只是未来的日期。所以,这个答案没有回答问题......【参考方案9】:

只需在代码中添加这一行即可。

一天

datePickerDialog.datePicker.findViewById<View (resources.getIdentifier("day","id","android")).visibility = View.GONE

月份

datePickerDialog.datePicker.findViewById<View (resources.getIdentifier("month","id","android")).visibility = View.GONE

一年

datePickerDialog.datePicker.findViewById<View (resources.getIdentifier("year","id","android")).visibility = View.GONE

【讨论】:

【参考方案10】:

有一个定制的喷气背包组合解决方案。您可以仅选择月份、仅年份或同时选择两者。 https://github.com/DogusTeknoloji/compose-date-picker

【讨论】:

【参考方案11】:

这对我来说很好:

DatePickerDialog monthDatePickerDialog = new DatePickerDialog(activity, 
AlertDialog.THEME_HOLO_LIGHT, new DatePickerDialog.OnDateSetListener() 
        @Override
        public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) 
            monthTextView.setText(year + "/" + (month + 1));
        
    , yearNow, monthNow, dayNow)
        @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            getDatePicker().findViewById(getResources().getIdentifier("day","id","android")).setVisibility(View.GONE);
        
    ;
    monthDatePickerDialog.setTitle("select_month");
    monthDatePickerDialog.show();

【讨论】:

这个在 Oxygen OS,一加 X 上提供 NPE,因为它找不到具有该 ID 的视图。

以上是关于Android DatePicker 更改为仅月和年的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Bootstrap Datepicker Anchor Position 更改为居中?

在 Datepicker 中将日期格式更改为 yyyy-mm-dd

typescript 将datepicker KendoUI更改为希伯来语

如何将datepicker日期格式更改为DD / MM / YYYY [复制]

将 C# webapp 更改为使用母版页后,DatePicker 不再工作

jQuery UI datepicker:如何将下拉列表中的月份名称从短名称更改为长名称?