it.andreale.mdatetimepicker.date.DatePickerDialog.java Source code

Java tutorial

Introduction

Here is the source code for it.andreale.mdatetimepicker.date.DatePickerDialog.java

Source

/*
 * ******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 AndreAle94
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
    
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * *****************************************************************************
 */
package it.andreale.mdatetimepicker.date;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.widget.Button;

import java.util.Calendar;
import java.util.Date;

import it.andreale.mdatetimepicker.DialogUtils;
import it.andreale.mdatetimepicker.R;

/**
 * Created by AndreAle94
 */
public class DatePickerDialog extends DialogFragment implements DatePickerController, View.OnClickListener {

    private final static int DEFAULT_ACCENT_COLOR = Color.parseColor("#009688");
    private final static int DEFAULT_START_YEAR = 1900;
    private final static int DEFAULT_END_YEAR = 2100;
    private final static int DEFAULT_PICKER_MODE = DateHeaderView.MODE_DAY_PICKER;
    private final static int DEFAULT_FIRST_DAY_OF_WEEK = Calendar.SUNDAY;
    private final static String DEFAULT_HEADER_DATE_FORMAT = "EEE, MMM dd";
    private final static int BACKGROUND_LIGHT = Color.parseColor("#FAFAFA");
    private final static int BACKGROUND_DARK = Color.parseColor("#424242");

    private final static String SAVED_HEADER_COLOR = "dpd:headerColor";
    private final static String SAVED_SELECTION_COLOR = "dpd:selectionColor";
    private final static String SAVED_POSITIVE_COLOR = "dpd:positiveColor";
    private final static String SAVED_NEGATIVE_COLOR = "dpd:negativeColor";
    private final static String SAVED_POSITIVE_TEXT = "dpd:positiveText";
    private final static String SAVED_NEGATIVE_TEXT = "dpd:negativeText";
    private final static String SAVED_TODAY_COLOR = "dpd:todayColor";
    private final static String SAVED_DARK_MODE = "dpd:darkMode";
    private final static String SAVED_DEFAULT_MODE = "dpd:defaultMode";
    private final static String SAVED_PICKER_MODE = "dpd:pickerMode";
    private final static String SAVED_START_YEAR = "dpd:startYear";
    private final static String SAVED_END_YEAR = "dpd:endYear";
    private final static String SAVED_CALENDAR = "dpd:internalCalendar";
    private final static String SAVED_HEADER_DATE_FORMAT = "dpd:headerFormat";

    private int mHeaderColor;
    private int mSelectionColor;
    private int mPositiveColor;
    private int mNegativeColor;
    private boolean mDarkTheme;
    private int mTodayColor;

    private String mPositiveText;
    private String mNegativeText;
    private int mYearStart;
    private int mYearEnd;
    private Calendar mCalendar;
    private int mDefaultPickerMode;
    private String mHeaderDateFormat;
    private int mFirstDayOfWeek;
    private boolean mBuilderFlag;

    // components
    private DateHeaderView mHeaderView;
    private YearPickerView mYearPickerView;
    private DayPickerView mDayPickerView;

    private Button mPositiveButton;
    private Button mNegativeButton;

    // callback
    private OnDateSetListener mDateSetListener;

    public DatePickerDialog() {
        mBuilderFlag = false;
    }

    private static DatePickerDialog newInstance() {
        return new DatePickerDialog();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(SAVED_HEADER_COLOR, mHeaderColor);
        outState.putInt(SAVED_SELECTION_COLOR, mSelectionColor);
        outState.putInt(SAVED_POSITIVE_COLOR, mPositiveColor);
        outState.putInt(SAVED_NEGATIVE_COLOR, mNegativeColor);
        outState.putInt(SAVED_TODAY_COLOR, mTodayColor);
        outState.putBoolean(SAVED_DARK_MODE, mDarkTheme);
        outState.putString(SAVED_HEADER_DATE_FORMAT, mHeaderDateFormat);
        outState.putInt(SAVED_PICKER_MODE, mHeaderView.getPickerMode());
        outState.putInt(SAVED_START_YEAR, mYearStart);
        outState.putInt(SAVED_END_YEAR, mYearEnd);
        outState.putString(SAVED_POSITIVE_TEXT, mPositiveText);
        outState.putString(SAVED_NEGATIVE_TEXT, mNegativeText);
        outState.putSerializable(SAVED_CALENDAR, mCalendar);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (activity instanceof OnDateSetListener) {
            mDateSetListener = (OnDateSetListener) activity;
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mDateSetListener = null;
    }

    @NonNull
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // restore old state if not null
        if (savedInstanceState != null) {
            mHeaderColor = savedInstanceState.getInt(SAVED_HEADER_COLOR, DEFAULT_ACCENT_COLOR);
            mSelectionColor = savedInstanceState.getInt(SAVED_SELECTION_COLOR, DEFAULT_ACCENT_COLOR);
            mPositiveColor = savedInstanceState.getInt(SAVED_POSITIVE_COLOR, DEFAULT_ACCENT_COLOR);
            mNegativeColor = savedInstanceState.getInt(SAVED_NEGATIVE_COLOR, DEFAULT_ACCENT_COLOR);
            mTodayColor = savedInstanceState.getInt(SAVED_TODAY_COLOR, DEFAULT_ACCENT_COLOR);
            mDarkTheme = savedInstanceState.getBoolean(SAVED_DARK_MODE, false);
            mDefaultPickerMode = savedInstanceState.getInt(SAVED_DEFAULT_MODE, DEFAULT_PICKER_MODE);
            mYearStart = savedInstanceState.getInt(SAVED_START_YEAR, DEFAULT_START_YEAR);
            mYearEnd = savedInstanceState.getInt(SAVED_END_YEAR, DEFAULT_END_YEAR);
            mCalendar = (Calendar) savedInstanceState.getSerializable(SAVED_CALENDAR);
            mHeaderDateFormat = savedInstanceState.getString(SAVED_HEADER_DATE_FORMAT, DEFAULT_HEADER_DATE_FORMAT);
            mPositiveText = savedInstanceState.getString(SAVED_POSITIVE_TEXT, getString(android.R.string.ok));
            mNegativeText = savedInstanceState.getString(SAVED_NEGATIVE_TEXT, getString(android.R.string.cancel));
            mBuilderFlag = true;
            if (mCalendar != null) {
                mFirstDayOfWeek = mCalendar.getFirstDayOfWeek();
            } else {
                mFirstDayOfWeek = DEFAULT_FIRST_DAY_OF_WEEK;
            }
        } else {
            mDefaultPickerMode = DEFAULT_PICKER_MODE;
            mCalendar.setFirstDayOfWeek(mFirstDayOfWeek);
            // check builder flag
            if (!mBuilderFlag) {
                throw new IllegalStateException("You must initialize DatePickerDialog throw Builder class");
            }
        }
        // inflate view
        View view = inflatePickerView(savedInstanceState);
        // style views
        mHeaderView.setBackgroundColor(mHeaderColor);
        view.setBackgroundColor(mDarkTheme ? BACKGROUND_DARK : BACKGROUND_LIGHT);
        // create dialog
        Dialog dialog = new Dialog(getActivity());
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setContentView(view);
        return dialog;
    }

    protected View inflatePickerView(Bundle savedInstanceState) {
        // inflate view
        LayoutInflater inflater = LayoutInflater.from(getActivity());
        View view = inflater.inflate(R.layout.md_date_picker_dialog, null);
        mHeaderView = (DateHeaderView) view.findViewById(R.id.date_header_view);
        mYearPickerView = (YearPickerView) view.findViewById(R.id.date_year_picker_view);
        mDayPickerView = (DayPickerView) view.findViewById(R.id.date_day_picker_view);
        // buttons
        mPositiveButton = (Button) view.findViewById(R.id.positive_button);
        mNegativeButton = (Button) view.findViewById(R.id.negative_button);
        mPositiveButton.setOnClickListener(this);
        mNegativeButton.setOnClickListener(this);
        mPositiveButton.setTextColor(mPositiveColor);
        mNegativeButton.setTextColor(mNegativeColor);
        mPositiveButton.setText(mPositiveText);
        mNegativeButton.setText(mNegativeText);
        // configure views
        if (savedInstanceState != null) {
            mHeaderView.setPickerMode(savedInstanceState.getInt(SAVED_PICKER_MODE));
        }
        mHeaderView.registerController(this);
        mDayPickerView.registerController(this);
        mYearPickerView.resisterController(this);
        return view;
    }

    public void setOnDateSetListener(OnDateSetListener listener) {
        mDateSetListener = listener;
    }

    @Override
    public int getDefaultMode() {
        return mDefaultPickerMode;
    }

    @Override
    public void onPickerModeChange(int pickerMode) {
        switch (pickerMode) {
        case DateHeaderView.MODE_DAY_PICKER:
            DialogUtils.setVisible(mDayPickerView, true);
            DialogUtils.setVisible(mYearPickerView, false);
            break;
        case DateHeaderView.MODE_YEAR_PICKER:
            mYearPickerView.onPreShow();
            DialogUtils.setVisible(mDayPickerView, false);
            DialogUtils.setVisible(mYearPickerView, true);
            break;
        }
    }

    @Override
    public int getStartYear() {
        return mYearStart;
    }

    @Override
    public int getEndYear() {
        return mYearEnd;
    }

    @Override
    public Calendar getSelectedDate() {
        return mCalendar;
    }

    @Override
    public void onYearChanged(int year) {
        mCalendar.set(Calendar.YEAR, year);
        mYearPickerView.notifyDateChanged();
        mHeaderView.updateDate();
        mDayPickerView.onDateChanged();
        mHeaderView.setPickerMode(DateHeaderView.MODE_DAY_PICKER);
    }

    @Override
    public boolean isDarkMode() {
        return mDarkTheme;
    }

    @Override
    public int getSelectionColor() {
        return mSelectionColor;
    }

    @Override
    public int getTodayColor() {
        return mTodayColor;
    }

    @Override
    public String getHeaderDateFormat() {
        return mHeaderDateFormat;
    }

    @Override
    public int getFirstDayOfWeek() {
        return mFirstDayOfWeek;
    }

    @Override
    public void onDayClicked(int day, int month, int year) {
        mCalendar.set(Calendar.YEAR, year);
        mCalendar.set(Calendar.MONTH, month);
        mCalendar.set(Calendar.DAY_OF_MONTH, day);
        mHeaderView.updateDate();
        mDayPickerView.onDateChanged();
        mYearPickerView.notifyDateChanged();
    }

    @Override
    public int getDirectionalButtonColor() {
        return mDarkTheme ? Color.WHITE : Color.BLACK;
    }

    @Override
    public int getMonthHeaderTextColor() {
        return mDarkTheme ? Color.WHITE : Color.BLACK;
    }

    @Override
    public void onClick(View v) {
        if (v == mPositiveButton) {
            if (mDateSetListener != null) {
                mDateSetListener.onDateSet(this, mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH),
                        mCalendar.get(Calendar.DAY_OF_MONTH));
            }
            dismiss();
        } else if (v == mNegativeButton) {
            dismiss();
        }
    }

    public static class Builder {

        private Context mContext;
        private int mAccentColor;
        private boolean mDarkMode;
        private int mPositiveColor;
        private int mNegativeColor;
        private int mHeaderColor;
        private int mSelectionColor;
        private int mTodayColor;
        private String mHeaderDateFormat;
        private Calendar mCalendar;
        private int mStartYear;
        private int mEndYear;
        private int mFirstDayOfWeek;
        private String mPositiveText;
        private String mNegativeText;

        private boolean mHeaderSet;

        public Builder(Context context) {
            mContext = context;
            mAccentColor = DialogUtils.resolveColor(context, R.attr.colorAccent, DEFAULT_ACCENT_COLOR);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mAccentColor = DialogUtils.resolveColor(context, android.R.attr.colorAccent, mAccentColor);
            }
            mDarkMode = DialogUtils.resolveBoolean(context, R.attr.mdp_darkMode, false);
            mPositiveColor = DialogUtils.resolveColor(context, R.attr.mdp_positiveColor, mAccentColor);
            mNegativeColor = DialogUtils.resolveColor(context, R.attr.mdp_negativeColor, mAccentColor);
            mTodayColor = DialogUtils.resolveColor(context, R.attr.mdp_todayTextColor, mAccentColor);
            mHeaderColor = DialogUtils.resolveColor(context, R.attr.mdp_headerBackgroundColor, mAccentColor);
            mHeaderSet = mHeaderColor != mAccentColor;
            mSelectionColor = DialogUtils.resolveColor(context, R.attr.mdp_selectedCircleColor, mAccentColor);
            mCalendar = Calendar.getInstance();
            DialogUtils.truncate(mCalendar);
            mStartYear = DEFAULT_START_YEAR;
            mEndYear = DEFAULT_END_YEAR;
            mFirstDayOfWeek = DEFAULT_FIRST_DAY_OF_WEEK;
            mHeaderDateFormat = DEFAULT_HEADER_DATE_FORMAT;
        }

        public Builder darkMode(boolean darkMode) {
            mDarkMode = darkMode;
            return this;
        }

        public Builder positiveColor(int color) {
            mPositiveColor = color;
            return this;
        }

        public Builder negativeColor(int color) {
            mNegativeColor = color;
            return this;
        }

        public Builder todayTextColor(int color) {
            mTodayColor = color;
            return this;
        }

        public Builder headerBackgroundColor(int color) {
            mHeaderColor = color;
            mHeaderSet = true;
            return this;
        }

        public Builder selectedCircleColor(int color) {
            mSelectionColor = color;
            return this;
        }

        public Builder selectedDate(Calendar calendar) {
            return selectedDate(calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.MONTH),
                    calendar.get(Calendar.YEAR));
        }

        public Builder selectedDate(Date date) {
            mCalendar.setTime(date);
            DialogUtils.truncate(mCalendar);
            return this;
        }

        public Builder selectedDate(int day, int month, int year) {
            mCalendar.set(Calendar.DAY_OF_MONTH, day);
            mCalendar.set(Calendar.MONTH, month);
            mCalendar.set(Calendar.YEAR, year);
            return this;
        }

        public Builder yearRange(int startYear, int endYear) {
            if (startYear > endYear) {
                throw new IllegalArgumentException("Start year can be later than end year!");
            }
            mStartYear = startYear;
            mEndYear = endYear;
            return this;
        }

        public Builder firstDayOfWeek(int firstDayOfWeek) {
            if (firstDayOfWeek < Calendar.SUNDAY || firstDayOfWeek > Calendar.SATURDAY) {
                throw new IllegalArgumentException("You must provide a valid day of week. See Calendar class");
            }
            mFirstDayOfWeek = firstDayOfWeek;
            return this;
        }

        public Builder headerDateFormat(String format) {
            mHeaderDateFormat = format;
            return this;
        }

        public Builder positiveText(String text) {
            mPositiveText = text;
            return this;
        }

        public Builder positiveText(int text) {
            mPositiveText = mContext.getString(text);
            return this;
        }

        public Builder negativeText(String text) {
            mNegativeText = text;
            return this;
        }

        public Builder negativeText(int text) {
            mNegativeText = mContext.getString(text);
            return this;
        }

        public DatePickerDialog build() {
            if (mPositiveText == null) {
                mPositiveText = mContext.getString(android.R.string.ok);
            }
            if (mNegativeText == null) {
                mNegativeText = mContext.getString(android.R.string.cancel);
            }
            if (!mHeaderSet && mDarkMode) {
                mHeaderColor = Color.parseColor("#555555");
            }
            DatePickerDialog dialog = DatePickerDialog.newInstance();
            dialog.mCalendar = mCalendar;
            dialog.mFirstDayOfWeek = mFirstDayOfWeek;
            dialog.mDarkTheme = mDarkMode;
            dialog.mPositiveColor = mPositiveColor;
            dialog.mNegativeColor = mNegativeColor;
            dialog.mYearStart = mStartYear;
            dialog.mYearEnd = mEndYear;
            dialog.mHeaderDateFormat = mHeaderDateFormat;
            dialog.mHeaderColor = mHeaderColor;
            dialog.mSelectionColor = mSelectionColor;
            dialog.mTodayColor = mTodayColor;
            dialog.mPositiveText = mPositiveText;
            dialog.mNegativeText = mNegativeText;
            dialog.mBuilderFlag = true;
            return dialog;
        }

        public void show(FragmentManager fragmentManager, String tag) {
            DatePickerDialog dialog = build();
            dialog.show(fragmentManager, tag);
        }
    }
}