Android 自定义日期选择器

public class UIDatePicker extends FrameLayout {
    
    /**
     * The callback used to indicate the user changes\d the date.
     */
    public interface OnDateChangedListener {

        /**
         * Called upon a date change.
         *
         * @param view The view associated with this listener.
         * @param year The year that was set.
         * @param monthOfYear The month that was set (0-11) for compatibility
         *            with {@link java.util.Calendar}.
         * @param dayOfMonth The day of the month that was set.
         */
        void onDateChanged(UIDatePicker view, int year, int monthOfYear, int dayOfMonth);
    }
    
    private static final int START_YEAR = 1900;
    
    private static final int END_YEAR = 2100;
    
    private static final String DATE_FORMAT = "yyyy/MM/dd";
    
    private static final String TAG = "UIDatePicker";
    
    private boolean mShowYearWheel;
    
    private boolean mShowMonthWheel;
    
    private boolean mshowDayWheel;
    
    private Calendar mDate;
    
    private Calendar mMinDate;
    
    private Calendar mMaxDate;
    
    private Calendar mTempDate;
    
    private NumberPicker mYearPicker;
    
    private NumberPicker mMonthPicker;
    
    private NumberPicker mDayPicker;
    
    private LinearLayout mSpinners;
    
    private OnDateChangedListener mDateChangedListener;
    
    private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
    
    private Runnable mUpdate = new Runnable() {
        @Override
        public void run() {
        }
    };
    
    
    

    public UIDatePicker(Context context) {
        this(context, null);
    }
    
    public UIDatePicker(Context context, AttributeSet attrs) {
        super(context, attrs);
        
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.UIDatePicker);

        final String minDate = ta.getString(R.styleable.UIDatePicker_datePicker_minDate);
        final String maxDate = ta.getString(R.styleable.UIDatePicker_datePicker_maxDate);

        if (!TextUtils.isEmpty(minDate)) {
            mMinDate = parseDate(minDate);
        }
        
        if (!TextUtils.isEmpty(maxDate)) {
            mMinDate = parseDate(maxDate);
        }

        final int layoutResourceId = ta.getResourceId(
                R.styleable.UIDatePicker_datePicker_internalLayout, R.layout.date_picker);

        mShowYearWheel = ta.getBoolean(R.styleable.UIDatePicker_datePicker_showYearWheel,
                true);
        mShowMonthWheel = ta.getBoolean(R.styleable.UIDatePicker_datePicker_showMonthWheel,
                true);
        mshowDayWheel = ta
                .getBoolean(R.styleable.UIDatePicker_datePicker_showDayWheel, true);

        ta.recycle();
        
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(layoutResourceId, this, true);
        
        init();
        
        
        
    }
    
    private void init(){
        
        mTempDate = Calendar.getInstance();
        
        mDate = Calendar.getInstance(Locale.getDefault());
        
        //make sure the minDate is real
        if(mMinDate == null){
            mMinDate = new GregorianCalendar();
            mMinDate.set(START_YEAR, 0, 1);
        }
        
        //make sure the maxDate is real
        if(mMaxDate == null){
            mMaxDate = new GregorianCalendar();
            mMaxDate.set(END_YEAR, 0, 1);
        }
        
        if(mMinDate.getTimeInMillis() + 24*60*60*1000 >= mMaxDate.getTimeInMillis()){
            throw new IllegalArgumentException("the min date must less than max date");
        }
        
        
        if (mDate.before(mMinDate)) {
            mDate.setTimeInMillis(mMinDate.getTimeInMillis());
        } else if (mDate.after(mMaxDate)) {
            mDate.setTimeInMillis(mMaxDate.getTimeInMillis());
        }
        
        OnValueChangeListener onChangeListener = new OnValueChangeListener() {
            
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                
                mTempDate.setTimeInMillis(mDate.getTimeInMillis());
                
                // take care of wrapping of days and months to update greater fields
                if (picker == mDayPicker) {
                    
                    mTempDate.set(Calendar.DAY_OF_MONTH, newVal);
    
                } else if (picker == mMonthPicker) {
                    mTempDate.set(Calendar.MONTH, newVal - 1);
                } else if (picker == mYearPicker) {
                    mTempDate.set(Calendar.YEAR, newVal);
                } else {
                    throw new IllegalArgumentException();
                }
                
                setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH),
                        mTempDate.get(Calendar.DAY_OF_MONTH));
                
                updateWheels();
                
                notifyDateChanged();
                
//                if(mYearPicker.getScrollState() == OnScrollListener.SCROLL_STATE_IDLE &&
//                        mMonthPicker.getScrollState() == OnScrollListener.SCROLL_STATE_IDLE &&
//                        mDayPicker.getScrollState() == OnScrollListener.SCROLL_STATE_IDLE){
//                    
//                    
//                }
                

            }
        };
        
        OnScrollListener ol = new OnScrollListener() {
            
            @Override
            public void onScrollStateChange(NumberPicker view, int scrollState) {
                if(view.getScrollState() == SCROLL_STATE_IDLE && mYearPicker.getScrollState() == OnScrollListener.SCROLL_STATE_IDLE &&
                            mMonthPicker.getScrollState() == OnScrollListener.SCROLL_STATE_IDLE &&
                            mDayPicker.getScrollState() == OnScrollListener.SCROLL_STATE_IDLE){
                        
                        postDelayed(mUpdate, 200);
                }
                
            }
        };
        
        
        mSpinners = (LinearLayout) findViewById(R.id.pickers);
        mDayPicker = (NumberPicker) findViewById(R.id.day);
        mMonthPicker = (NumberPicker) findViewById(R.id.month);
        mYearPicker = (NumberPicker) findViewById(R.id.year);
        
        if(!mShowYearWheel){
            mYearPicker.setVisibility(View.GONE);
        }
        if(!mShowMonthWheel){
            mMonthPicker.setVisibility(View.GONE);
        }
        if(!mshowDayWheel){
            mDayPicker.setVisibility(View.GONE);
        }
        
        reorderSpinners();
        
        updateWheels();
        mYearPicker.setOnValueChangedListener(onChangeListener);
        mDayPicker.setOnValueChangedListener(onChangeListener);
        mMonthPicker.setOnValueChangedListener(onChangeListener);
        mMonthPicker.setFormatter(new Formatter() {
            
            @Override
            public String format(int value) {
                
                return value + getResources().getString(R.string.month_format_unite);
                
            }
        });
        
//        mYearPicker.setOnScrollListener(ol);
//        mMonthPicker.setOnScrollListener(ol);
//        mDayPicker.setOnScrollListener(ol);
        
    }
    
    /**
     * Reorders the spinners according to the date format that is
     * explicitly set by the user and if no such is set fall back
     * to the current locale's default format.
     */
    private void reorderSpinners() {
        mSpinners.removeAllViews();
        char[] order = DateFormat.getDateFormatOrder(getContext());
        final int spinnerCount = order.length;
        for (int i = 0; i < spinnerCount; i++) {
            switch (order[i]) {
                case SimpleDateFormat.DATE_FIELD:
                    mSpinners.addView(mDayPicker);
                    break;
                case SimpleDateFormat.MONTH_FIELD:
                    mSpinners.addView(mMonthPicker);
                    break;
                case SimpleDateFormat.YEAR_FIELD:
                    mSpinners.addView(mYearPicker);
                    break;
                default:
                    throw new IllegalArgumentException();
            }
        }
    }
    
    /**
     * parse the given date for a Calendar
     * @param date given date
     * @return if parse failed will return null
     */
    private Calendar parseDate(String date){
        try{
            Calendar c = Calendar.getInstance();
            c.setTime(mDateFormat.parse(date));
            
            return c;
        }catch(Exception e){
            Log.e(TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
        }
        
        return null;
    }
    
    /**
     * set the item numbers show on screen
     * @param count
     */
    public void setDisplayItemCount(int count){
        mYearPicker.setDisplayItemCount(count);
        mMonthPicker.setDisplayItemCount(count);
        mDayPicker.setDisplayItemCount(count);
    }
    
    public void setMaxDate(long time){
        
        mTempDate.setTimeInMillis(time);
        
        if(mTempDate.get(Calendar.YEAR) != mMaxDate.get(Calendar.YEAR) ||
                mTempDate.get(Calendar.MONTH) != mMaxDate.get(Calendar.MONTH) ||
                mTempDate.get(Calendar.MONTH) != mMaxDate.get(Calendar.MONTH)){
            
            mMaxDate.setTimeInMillis(time);
            
            if(mMaxDate.before(mDate)){
                mDate.setTimeInMillis(time);
            }
            
            if(mMaxDate.before(mMinDate)){
                mMinDate.setTimeInMillis(time);
            }
            
            updateWheels();
            
        }
        
    }
    
    public void setMaxDate(int year, int month, int day){
        mTempDate.set(year, month, day);
        
        setMaxDate(mTempDate.getTimeInMillis());
    }
    
    public void setMinDate(long time){
        
        mTempDate.setTimeInMillis(time);
        
        if(mTempDate.get(Calendar.YEAR) != mMinDate.get(Calendar.YEAR) ||
                mTempDate.get(Calendar.MONTH) != mMinDate.get(Calendar.MONTH) ||
                mTempDate.get(Calendar.MONTH) != mMinDate.get(Calendar.MONTH)){
            
            mMinDate.setTimeInMillis(time);
            
            if(mMinDate.after(mDate)){
                mDate.setTimeInMillis(time);
            }
            
            if(mMinDate.after(mMinDate)){
                mMinDate.setTimeInMillis(time);
            }
            
            updateWheels();
            
        }
        
    }
    
    public void setMinDate(int year, int month, int day){
        mTempDate.set(year, month, day);
        
        setMinDate(mTempDate.getTimeInMillis());
    }
    
    public void setYearShown(boolean show){
        if(mShowYearWheel == show){
            return;
        }
        
        mShowYearWheel = show;
        
        if(mShowYearWheel){
            mYearPicker.setVisibility(View.VISIBLE);
        }else{
            mYearPicker.setVisibility(View.GONE);
        }
        
    }
    
    public void setMonthShown(boolean show){
        
        if(mShowMonthWheel == show){
            return;
        }
        
        mShowMonthWheel = show;
        
        if(mShowMonthWheel){
            mMonthPicker.setVisibility(View.VISIBLE);
        }else{
            mMonthPicker.setVisibility(View.GONE);
        }
        
    }
    
    public void setDayShown(boolean show){
        
        if(mshowDayWheel == show){
            return;
        }
        
        mshowDayWheel = show;
        
        if(mshowDayWheel){
            mDayPicker.setVisibility(View.VISIBLE);
        }else{
            mDayPicker.setVisibility(View.GONE);
        }
        
    }
    
    public long getDate(){
        return mDate.getTimeInMillis();
    }
    
    public long getMaxDate(){
        return mMaxDate.getTimeInMillis();
    }
    
    public long getMinDate(){
        return mMinDate.getTimeInMillis();
    }
    
    public void updateDate(int year, int month, int day){
        if (!isNewDate(year, month, day)) {
            return;
        }
        setDate(year, month, day);
//        System.out.println(mYearPicker.getScrollState() == OnScrollListener.SCROLL_STATE_IDLE);
//        System.out.println(mMonthPicker.getScrollState() == OnScrollListener.SCROLL_STATE_IDLE);
//        System.out.println(mDayPicker.getScrollState() == OnScrollListener.SCROLL_STATE_IDLE);
        
        updateWheels();
        
        notifyDateChanged();
        
//        notifyDateChanged();
    }
    
    public void init(int year, int month, int day, OnDateChangedListener changeListener){
        mDateChangedListener = null;
        setDate(year, month, day);
        updateWheels();
        mDateChangedListener = changeListener;
    }
    
    /**
     * isShow the year picker wheel
     * @return
     */
    public boolean isShowYear(){
        return mShowYearWheel;
    }
    
    /**
     * isShow the month picker wheel
     * @return
     */
    public boolean isShowMonth(){
        return mShowMonthWheel;
    }
    
    /**
     * isShow the day picker wheel
     * @return
     */
    public boolean isShowDay(){
        return mshowDayWheel;
    }
    
    /**
     * @return The selected year.
     */
    public int getYear() {
        return mDate.get(Calendar.YEAR);
    }

    /**
     * @return The selected month.
     */
    public int getMonth() {
        return mDate.get(Calendar.MONTH);
    }

    /**
     * @return The selected day of month.
     */
    public int getDayOfMonth() {
        return mDate.get(Calendar.DAY_OF_MONTH);
    }
    
    private boolean isNewDate(int year, int month, int dayOfMonth) {
        return (mDate.get(Calendar.YEAR) != year
                || mDate.get(Calendar.MONTH) != dayOfMonth
                || mDate.get(Calendar.DAY_OF_MONTH) != month);
    }
    
    
    private void setDate(int year, int month, int dayOfMonth) {
        
        mDate.set(year, month, dayOfMonth);
        
        if (mDate.before(mMinDate)) {
            mDate.setTimeInMillis(mMinDate.getTimeInMillis());
        } else if (mDate.after(mMaxDate)) {
            mDate.setTimeInMillis(mMaxDate.getTimeInMillis());
        }
    }
    
    /**
     * Notifies the listener, if such, for a change in the selected date.
     */
    private void notifyDateChanged() {
        if (mDateChangedListener != null) {
            mDateChangedListener.onDateChanged(this, getYear(), getMonth(), getDayOfMonth());
        }
    }
    
    private void updateMonthWheel(){
        mMonthPicker.setMinValue(1);
        mMonthPicker.setMaxValue(12);
        mMonthPicker.setValue(mDate.get(Calendar.MONTH) + 1);
    }
    
    private void updateDayWheel(){
        mDayPicker.setMinValue(1);
        mDayPicker.setMaxValue(mDate.getActualMaximum(Calendar.DAY_OF_MONTH));
        mDayPicker.setValue(mDate.get(Calendar.DAY_OF_MONTH));
    }
    
    private void updateYearWheel(){
        mYearPicker.setMinValue(mMinDate.get(Calendar.YEAR));
        mYearPicker.setMaxValue(mMaxDate.get(Calendar.YEAR));
        mYearPicker.setValue(mDate.get(Calendar.YEAR));
    }
    
    private void updates(){
        //if arrive at the min year
        if(mDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)){
            mMonthPicker.setMinValue(mMinDate.get(Calendar.MONTH) + 1);
            
            if(mDate.get(Calendar.MONTH) == mMinDate.get(Calendar.MONTH)){
                mDayPicker.setMinValue(mMinDate.get(Calendar.DAY_OF_MONTH));
            }
        }
    }
    
    private void updateWheels(){
        mYearPicker.setMinValue(mMinDate.get(Calendar.YEAR));
        mYearPicker.setMaxValue(mMaxDate.get(Calendar.YEAR));
        mYearPicker.setValue(mDate.get(Calendar.YEAR));
        
        mMonthPicker.setMinValue(1);
        mMonthPicker.setMaxValue(12);
        mMonthPicker.setValue(mDate.get(Calendar.MONTH) + 1);
        
        mDayPicker.setMinValue(1);
        mDayPicker.setMaxValue(mDate.getActualMaximum(Calendar.DAY_OF_MONTH));
        mDayPicker.setValue(mDate.get(Calendar.DAY_OF_MONTH));
        
        //if arrive at the min year
        if(mDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)){
            mMonthPicker.setMinValue(mMinDate.get(Calendar.MONTH));
            
            if(mDate.get(Calendar.MONTH) == mMinDate.get(Calendar.MONTH)){
                mDayPicker.setMinValue(mMinDate.get(Calendar.DAY_OF_MONTH));
            }
        }
        
        if(mDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)){
            mMonthPicker.setMinValue(mMaxDate.get(Calendar.MONTH));
            
            if(mDate.get(Calendar.MONTH) == mMaxDate.get(Calendar.MONTH)){
                mDayPicker.setMinValue(mMaxDate.get(Calendar.DAY_OF_MONTH));
            }
        }
        
    }
    
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值