65

I have a DatePickerDialog and I want view only Month and Year. How can I change this code?

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();
    }
};

Thanks

GramThanos
  • 3,572
  • 1
  • 22
  • 34
user3160725
  • 1,801
  • 3
  • 15
  • 14
  • Please see this link. This question has been asked before. http://stackoverflow.com/questions/10673842/android-hide-date-field-in-datepickerdialog – Ogen Jan 24 '14 at 00:27
  • Possible duplicate of [Android - Hide date field in datepickerdialog](http://stackoverflow.com/questions/10673842/android-hide-date-field-in-datepickerdialog) – GramThanos Apr 08 '17 at 09:38

11 Answers11

89

As i recently stumbled across this problem myself, i tested multiple solutions from this post and similar questions on Stackoverflow.

Unfortunately i found no working solution especially for Android 5+

I ended up with implementing my own simple DialogFragment embedding two NumberPickers. This should be compatible with all versions from 3.0 and upwards.

Here is the code:

  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();
  }
}

And the layout

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

    <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:layout_marginRight="20dp">

        </NumberPicker>

        <NumberPicker
            android:id="@+id/picker_year"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

        </NumberPicker>

    </LinearLayout>
</LinearLayout>

To show the layout use:

MonthYearPickerDialog pd = new MonthYearPickerDialog();
pd.setListener(this);
pd.show(getFragmentManager(), "MonthYearPickerDialog");
snersesyan
  • 1,647
  • 17
  • 26
Stephan Klein
  • 901
  • 1
  • 6
  • 6
  • Perfect for me. The only problem is that the default onDateSet is on this format: onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) | but on your custom dialog it's listener.onDateSet(null, 0, monthPicker.getValue(), yearPicker.getValue()); | So you're setting the year in "dayOfMonth" – Marcio Granzotto Nov 13 '15 at 15:56
  • Thanks! Working fine on Android 6.0. – Teo Inke Jul 08 '16 at 23:24
  • 3
    For API 28 you should use `getSupportFragmentManager()` instead of `getFragmentManager()`. – cakan Oct 19 '18 at 08:11
  • Not sure why, but I couldn't set `listener.onDateSet(null, yearPicker.getValue(), monthPicker.getValue(), 0);` I had to change the first parameter to `DatePicker(context)`. It kept showing me a _non-null value set to null_ error. Hope it helps – Prox Dec 17 '19 at 03:03
  • Worked for me. Thanks – Rohit Sharma Mar 06 '20 at 05:27
39

I don't recommend using Reflection to do this kind of thing.

There is a simpler and more pretty way to do so:

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

Be aware that .getDatePicker() method from DatePickerDialog works on API LEVEL >= 11.

In addition it does not work on API LEVEL >= 21.

Elhanan Mishraky
  • 2,736
  • 24
  • 26
28

Try the following code. It will show a DatePicker with only the year and month (without day)

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;
    }

This method returns a date picker dialog. So , in your button's onClick method add the following code to display your dialog.

createDialogWithoutDateField().show();
ihsan
  • 699
  • 2
  • 9
  • 26
mohammed momn
  • 3,230
  • 1
  • 20
  • 16
  • Look you my edit answer i test code and making some changing on it and it working with me well try it and feed me back – mohammed momn Jan 24 '14 at 00:20
  • Thank you very much. Please can see my other question?[http://stackoverflow.com/questions/21343408/android-sqlite-insert-multiple-records] – user3160725 Jan 24 '14 at 22:16
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/46049/discussion-between-mohammed-momn-and-user3160725) – mohammed momn Jan 24 '14 at 22:17
  • you are welcome , I already post answer for second question :) . could you mark my answer as accepted ? – mohammed momn Jan 24 '14 at 22:18
  • how to display date picker dailog inbetween two individual dates only there is no option to cross those dates android.i have start date and end dates either two separate or same months need to display datepicker in those days selection android – Harsha Jul 27 '16 at 13:01
  • 5
    Reflection invokes methods which are available in the class. This method could disappear into thin air in the next version of Android. Reflection is not good choice. – Samet ÖZTOPRAK Nov 28 '17 at 08:25
  • 2
    Reflection, or modifying the layout to hide the column is always a hacky solution and is prone to break over the long term. Instead one should really make their own component. See Stephan's answer to this question: https://stackoverflow.com/a/31653048/1026805 – Sri Harsha Chilakapati Jun 22 '18 at 13:51
  • This way shouldn't be the normal way to make As the property's name or inheritances of DatePicker are differ on differ versions. So that it will faild to do on some phones. – Chinese Cat Aug 24 '19 at 08:33
  • I used the same code it worked on portrait mode(Nougat) and the same screeen in a much bigger Tab(Marshmellow) in landscape is showing dates also how to handle it? Functionality is fine as we are only copying month and year it is fine but i dont want dates to be visible also. Please help – GiridharaSPK Oct 31 '19 at 06:26
  • But it's still showing day picker as well. – Adam Noor Apr 19 '21 at 12:11
13

More Advance form of Stephan Klein Answer .

As I have a requirement to make Year optional. And I have also handled date like february 28 and also handle leap year.

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;
    }
}

And I call it like

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_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">



    <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:layout_marginRight="20dp" />


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

        <NumberPicker
            android:id="@+id/picker_year"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>
</LinearLayout>
Zar E Ahmer
  • 33,936
  • 20
  • 234
  • 300
10

Late to party. But if someone looking for Kotlin version, I re-write @Stephan Klein 's anwser, change it to Kotlin, with Data-Binding style, month display, and a date input.

So, if you're looking for an Month-Year picker, you can create 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()
    }
}

With its 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_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="horizontal">

        <NumberPicker
            android:id="@+id/pickerYear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="20dp" />

        <NumberPicker
            android:id="@+id/pickerMonth"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>
</layout>

To use it, call:

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

It'll look like this:

Month-Year Picker Dialog

CAUTION When Used in Fragment

Since Kotlin apply will shadow keyword this, and MonthYearPickerDialog is also a Fragment, you must make sure you call the correct FragmentManager in show() method. Otherwise a FATAL IllegalStateException: not associated with a fragment manager. might raise.

For Example, if you want to call this in MyFragment, use @ to specify which "this" is:

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")
}

Upvote if the answer helps :)

Samuel T. Chou
  • 521
  • 6
  • 31
4

The answer by 'Xar E Ahmer' is very easy to follow and as per requirement. I have used the same with following modifications as per my requirement.

  • Kotlin conversion of 'Xar E Ahmer' Answer .
  • Few error handling case added.
  • More handing of February 28/29 as per leap year.
  • Every year checkbox to exclude year ( simplified for user ).

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_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

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

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="horizontal">

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

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

        <NumberPicker
            android:id="@+id/datepicker_year"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>
</LinearLayout>

Usage example with different test cases in 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);

For the users, who wanted 'date' object as returned value:-

we can create date object from the returned day, Month and Year values as per following ( please correct any syntax error )

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);
SHS
  • 1,414
  • 4
  • 26
  • 43
2

It Works For me... Try This

    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();
            }
        });
1

It's very simple and easy just add this line in your code.

For Day

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

For Month

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

For Year

datePickerDialog.datePicker.findViewById<View (resources.getIdentifier("year","id","android")).visibility = View.GONE
Adam Noor
  • 101
  • 3
0

This is an old question, but now you can just use "BetterPickers":

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

And use ExpirationPicker.

Hope this solves it for some other lost souls who searched Google far and wide.

Andreas Rudolph
  • 1,226
  • 19
  • 28
  • 2
    I checked that `ExpirationPicker` and the problem is that it's only to select upcoming years and months. I mean, we can't select "April of 1970". Just future dates. So, this answer doesn't answer the question... – Roc Boronat Jun 26 '17 at 17:11
0

There is a custom jetpack compose solution. You can select only month, only year or both. https://github.com/DogusTeknoloji/compose-date-picker

onur taskin
  • 929
  • 1
  • 14
  • 33
-1

This Works for me fine :

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();
Malik Abu Qaoud
  • 208
  • 1
  • 9