16

Can anybody tell how to display year only in date picker in android

Thanks

user386430
  • 4,837
  • 13
  • 41
  • 45

8 Answers8

12

First, create MonthYearPickerDialog.java class extends with 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();
   }
 }

in styles.xml paste this code.

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

create 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>

In your main class (activity)

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

Finally , call wherever you want

createDialogWithoutDateField().show();

enter image description here

enter image description here

Agilanbu
  • 2,747
  • 2
  • 28
  • 33
6

You could also use some simple reflection to hide the day and month NumberPickers of a DatePicker widget. Do note that this may stop working if Google decides to rename the member field names. Also, this approach of course makes sense when using 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;
    }
}

Update: Added code illustrating how to make this approach work with Android 'Lollipop' 5.0 (API 21+).


Disclaimer: I cannot stress enough that this is hacky solution that may stop working with any framework update (as it did when Android 3.0 was first introduced, and again with Android 5.0).

MH.
  • 45,303
  • 10
  • 103
  • 116
  • @MangeshGhotage: The original answer stopped working when Lollipop (API 21 / Android 5.0) was introduced, as the internal structure changed in such a way that the relevant fields are now wrapped inside a `DatePickerDelegate` instance. I've updated the answer to reflect this. – MH. Oct 22 '15 at 19:38
1

I have modified @agilanbu 's answer and it can be used as :

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

You can get the layout file and styles in @agilanbu 's answer.

Serg
  • 2,346
  • 3
  • 29
  • 38
ROHIT LIEN
  • 497
  • 3
  • 8
1

you can hide day and month from custom datepicker like this:

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);
    }
ganjaam
  • 1,030
  • 3
  • 17
  • 29
0

I just have the same problem and all solution I found doesn't works with new Android Versions because I can't get the Field of the Reflection of DatePicker

Anyway I solve by doing a Dialog to pick a number, if you need the code:

SingleNumberPickerDialog.java Code

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 Code:

<?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>

Usage sample (u need to implement the callback inside ur activity):

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);
Z3R0
  • 1,011
  • 10
  • 19
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>
  • 1
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Pouria Hemi Nov 11 '20 at 08:32
0

I also modified @agilanbu 's answer and updated @ROHIT LIEN's answer. NOTE: it only contains info about year:

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

The layout is the same although I added 2 buttons in the layout:

btnPositive btnNegative

and removed those from the style. This is in case you have custom design for your positive and negative buttons. + monthPicker number picker is removed.

NOTE: btnPositive and btnNegative are the IDs of buttons in the layout.

Ara Mkrtchyan
  • 497
  • 6
  • 12
0

1.Add a Class of YearMonth Selection

public class MonthYearPickerDialog extends DialogFragment {

    private DatePickerDialog.OnDateSetListener listener;

    public MonthYearPickerDialog(DatePickerDialog.OnDateSetListener listener) {
        this.listener = listener;
    }
    
    @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(2010);
        yearPicker.setMaxValue(2022);
        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();
    }
}
  1. Set Layout with name month_year_picker_dialog

     <androidx.constraintlayout.widget.ConstraintLayout 
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:tools="http://schemas.android.com/tools"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content">
     <LinearLayout
         android:layout_width="220dp"
         android:layout_height="300dp"
         android:layout_gravity="center"
         android:gravity="center"
         android:orientation="vertical"
         tools:ignore="MissingConstraints">
    
    
         <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>
    
     </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. Add theme

      <style name="AlertDialogStyle" parent="Theme.AppCompat.Light.Dialog">
         <item name="android:textColor">@color/app_color</item>  // you can change the color of the yearPiker dialog
         <item name="android:textColorPrimary">@color/app_color</item> // you can change the color of the yearPiker dialog
     </style>
    
  3. set the value of view as below

     MonthYearPickerDialog newFragment = new MonthYearPickerDialog((datePicker, i, i1, i2) -> textView.setText(String.valueOf(i)));
         newFragment.show(getSupportFragmentManager(), "DatePicker");
    
Zahra
  • 2,231
  • 3
  • 21
  • 41