All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.holoeverywhere.widget.TimePicker Maven / Gradle / Ivy

There is a newer version: 1.6.8
Show newest version

package org.holoeverywhere.widget;

import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.Locale;

import org.holoeverywhere.FontLoader;
import org.holoeverywhere.LayoutInflater;
import org.holoeverywhere.R;
import org.holoeverywhere.internal.NumberPickerEditText;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Build.VERSION;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.FrameLayout;

public class TimePicker extends FrameLayout {
    public interface OnTimeChangedListener {
        void onTimeChanged(TimePicker view, int hourOfDay, int minute);
    }

    private static class SavedState extends BaseSavedState {
        @SuppressWarnings("unused")
        public static final Creator CREATOR = new Creator() {
            @Override
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            @Override
            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };

        private final int mHour, mMinute;

        private SavedState(Parcel in) {
            super(in);
            mHour = in.readInt();
            mMinute = in.readInt();
        }

        private SavedState(Parcelable superState, int hour, int minute) {
            super(superState);
            mHour = hour;
            mMinute = minute;
        }

        public int getHour() {
            return mHour;
        }

        public int getMinute() {
            return mMinute;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(mHour);
            dest.writeInt(mMinute);
        }
    }

    private static final boolean DEFAULT_ENABLED_STATE = true;
    private static final int HOURS_IN_HALF_DAY = 12;
    private static final OnTimeChangedListener NO_OP_CHANGE_LISTENER = new OnTimeChangedListener() {
        @Override
        public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
        }
    };

    private static void setContentDescription(View parent, int childId,
            int textId) {
        if (parent == null) {
            return;
        }
        View child = parent.findViewById(childId);
        if (child != null) {
            child.setContentDescription(parent.getContext().getText(textId));
        }
    }

    private final Button mAmPmButton;
    private final String[] mAmPmStrings;
    private Context mContext;
    private Locale mCurrentLocale;
    private final TextView mDivider;
    private final NumberPicker mHourSpinner, mMinuteSpinner, mAmPmSpinner;
    private final NumberPickerEditText mHourSpinnerInput, mMinuteSpinnerInput,
            mAmPmSpinnerInput;
    private boolean mIs24HourView, mIsAm;

    private boolean mIsEnabled = TimePicker.DEFAULT_ENABLED_STATE;

    private OnTimeChangedListener mOnTimeChangedListener;

    private Calendar mTempCalendar;

    public TimePicker(Context context) {
        this(context, null);
    }

    public TimePicker(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.timePickerStyle);
    }

    public TimePicker(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
        setCurrentLocale(Locale.getDefault());
        TypedArray attributesArray = context.obtainStyledAttributes(attrs,
                R.styleable.TimePicker, defStyle, 0);
        int layoutResourceId = attributesArray.getResourceId(
                R.styleable.TimePicker_internalLayout,
                R.layout.time_picker_holo);
        attributesArray.recycle();
        LayoutInflater.inflate(mContext, layoutResourceId, this, true);
        FontLoader.apply(this);
        mHourSpinner = (NumberPicker) findViewById(R.id.hour);
        mHourSpinner
                .setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
                    @Override
                    public void onValueChange(NumberPicker spinner, int oldVal,
                            int newVal) {
                        updateInputState();
                        if (!is24HourView()) {
                            if (oldVal == TimePicker.HOURS_IN_HALF_DAY - 1
                                    && newVal == TimePicker.HOURS_IN_HALF_DAY
                                    || oldVal == TimePicker.HOURS_IN_HALF_DAY
                                    && newVal == TimePicker.HOURS_IN_HALF_DAY - 1) {
                                mIsAm = !mIsAm;
                                updateAmPmControl();
                            }
                        }
                        onTimeChanged();
                    }
                });
        mHourSpinnerInput = mHourSpinner.getInputField();
        mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
        mDivider = (TextView) findViewById(R.id.divider);
        if (mDivider != null) {
            mDivider.setText(R.string.time_picker_separator);
        }
        mMinuteSpinner = (NumberPicker) findViewById(R.id.minute);
        mMinuteSpinner.setMinValue(0);
        mMinuteSpinner.setMaxValue(59);
        mMinuteSpinner.setOnLongPressUpdateInterval(100);
        mMinuteSpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
        mMinuteSpinner
                .setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
                    @Override
                    public void onValueChange(NumberPicker spinner, int oldVal,
                            int newVal) {
                        updateInputState();
                        int minValue = mMinuteSpinner.getMinValue();
                        int maxValue = mMinuteSpinner.getMaxValue();
                        if (oldVal == maxValue && newVal == minValue) {
                            int newHour = mHourSpinner.getValue() + 1;
                            if (!is24HourView()
                                    && newHour == TimePicker.HOURS_IN_HALF_DAY) {
                                mIsAm = !mIsAm;
                                updateAmPmControl();
                            }
                            mHourSpinner.setValue(newHour);
                        } else if (oldVal == minValue && newVal == maxValue) {
                            int newHour = mHourSpinner.getValue() - 1;
                            if (!is24HourView()
                                    && newHour == TimePicker.HOURS_IN_HALF_DAY - 1) {
                                mIsAm = !mIsAm;
                                updateAmPmControl();
                            }
                            mHourSpinner.setValue(newHour);
                        }
                        onTimeChanged();
                    }
                });
        mMinuteSpinnerInput = mMinuteSpinner.getInputField();
        mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
        mAmPmStrings = new DateFormatSymbols().getAmPmStrings();
        View amPmView = findViewById(R.id.amPm);
        if (amPmView instanceof Button) {
            mAmPmSpinner = null;
            mAmPmSpinnerInput = null;
            mAmPmButton = (Button) amPmView;
            mAmPmButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View button) {
                    button.requestFocus();
                    mIsAm = !mIsAm;
                    updateAmPmControl();
                    onTimeChanged();
                }
            });
        } else {
            mAmPmButton = null;
            mAmPmSpinner = (NumberPicker) amPmView;
            mAmPmSpinner.setMinValue(0);
            mAmPmSpinner.setMaxValue(1);
            mAmPmSpinner.setDisplayedValues(mAmPmStrings);
            mAmPmSpinner
                    .setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
                        @Override
                        public void onValueChange(NumberPicker picker,
                                int oldVal, int newVal) {
                            updateInputState();
                            picker.requestFocus();
                            mIsAm = !mIsAm;
                            updateAmPmControl();
                            onTimeChanged();
                        }
                    });
            mAmPmSpinnerInput = mAmPmSpinner.getInputField();
            mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
        }
        updateHourControl();
        updateAmPmControl();
        setOnTimeChangedListener(TimePicker.NO_OP_CHANGE_LISTENER);
        setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY));
        setCurrentMinute(mTempCalendar.get(Calendar.MINUTE));
        if (!isEnabled()) {
            setEnabled(false);
        }
        setContentDescriptions();
    }

    @SuppressLint("NewApi")
    @Override
    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
        if (VERSION.SDK_INT >= 14) {
            onPopulateAccessibilityEvent(event);
            return true;
        } else {
            return super.dispatchPopulateAccessibilityEvent(event);
        }
    }

    @Override
    public int getBaseline() {
        return mHourSpinner.getBaseline();
    }

    public Integer getCurrentHour() {
        int currentHour = mHourSpinner.getValue();
        if (is24HourView()) {
            return currentHour;
        } else if (mIsAm) {
            return currentHour % TimePicker.HOURS_IN_HALF_DAY;
        } else {
            return currentHour % TimePicker.HOURS_IN_HALF_DAY
                    + TimePicker.HOURS_IN_HALF_DAY;
        }
    }

    public Integer getCurrentMinute() {
        return mMinuteSpinner.getValue();
    }

    public boolean is24HourView() {
        return mIs24HourView;
    }

    @Override
    public boolean isEnabled() {
        return mIsEnabled;
    }

    @SuppressLint("NewApi")
    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setCurrentLocale(newConfig.locale);
    }

    @SuppressLint("NewApi")
    @Override
    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
        super.onPopulateAccessibilityEvent(event);
        int flags = DateUtils.FORMAT_SHOW_TIME;
        if (mIs24HourView) {
            flags |= DateUtils.FORMAT_24HOUR;
        } else {
            flags |= DateUtils.FORMAT_12HOUR;
        }
        mTempCalendar.set(Calendar.HOUR_OF_DAY, getCurrentHour());
        mTempCalendar.set(Calendar.MINUTE, getCurrentMinute());
        String selectedDateUtterance = DateUtils.formatDateTime(mContext,
                mTempCalendar.getTimeInMillis(), flags);
        event.getText().add(selectedDateUtterance);
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());
        setCurrentHour(ss.getHour());
        setCurrentMinute(ss.getMinute());
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        return new SavedState(superState, getCurrentHour(), getCurrentMinute());
    }

    private void onTimeChanged() {
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
        if (mOnTimeChangedListener != null) {
            mOnTimeChangedListener.onTimeChanged(this, getCurrentHour(),
                    getCurrentMinute());
        }
    }

    private void setContentDescriptions() {
        TimePicker.setContentDescription(mMinuteSpinner, R.id.increment,
                R.string.time_picker_increment_minute_button);
        TimePicker.setContentDescription(mMinuteSpinner, R.id.decrement,
                R.string.time_picker_decrement_minute_button);
        TimePicker.setContentDescription(mHourSpinner, R.id.increment,
                R.string.time_picker_increment_hour_button);
        TimePicker.setContentDescription(mHourSpinner, R.id.decrement,
                R.string.time_picker_decrement_hour_button);
        if (mAmPmSpinner != null) {
            TimePicker.setContentDescription(mAmPmSpinner, R.id.increment,
                    R.string.time_picker_increment_set_pm_button);
            TimePicker.setContentDescription(mAmPmSpinner, R.id.decrement,
                    R.string.time_picker_decrement_set_am_button);
        }
    }

    public void setCurrentHour(Integer currentHour) {
        if (currentHour == null || currentHour == getCurrentHour()) {
            return;
        }
        if (!is24HourView()) {
            if (currentHour >= TimePicker.HOURS_IN_HALF_DAY) {
                mIsAm = false;
                if (currentHour > TimePicker.HOURS_IN_HALF_DAY) {
                    currentHour = currentHour - TimePicker.HOURS_IN_HALF_DAY;
                }
            } else {
                mIsAm = true;
                if (currentHour == 0) {
                    currentHour = TimePicker.HOURS_IN_HALF_DAY;
                }
            }
            updateAmPmControl();
        }
        mHourSpinner.setValue(currentHour);
        onTimeChanged();
    }

    private void setCurrentLocale(Locale locale) {
        if (locale.equals(mCurrentLocale)) {
            return;
        }
        mCurrentLocale = locale;
        mTempCalendar = Calendar.getInstance(locale);
    }

    public void setCurrentMinute(Integer currentMinute) {
        if (currentMinute == getCurrentMinute()) {
            return;
        }
        mMinuteSpinner.setValue(currentMinute);
        onTimeChanged();
    }

    @Override
    public void setEnabled(boolean enabled) {
        if (mIsEnabled == enabled) {
            return;
        }
        super.setEnabled(enabled);
        mMinuteSpinner.setEnabled(enabled);
        if (mDivider != null) {
            mDivider.setEnabled(enabled);
        }
        mHourSpinner.setEnabled(enabled);
        if (mAmPmSpinner != null) {
            mAmPmSpinner.setEnabled(enabled);
        } else {
            mAmPmButton.setEnabled(enabled);
        }
        mIsEnabled = enabled;
    }

    public void setIs24HourView(Boolean is24HourView) {
        if (mIs24HourView == is24HourView) {
            return;
        }
        mIs24HourView = is24HourView;
        int currentHour = getCurrentHour();
        updateHourControl();
        setCurrentHour(currentHour);
        updateAmPmControl();
    }

    public void setOnTimeChangedListener(
            OnTimeChangedListener onTimeChangedListener) {
        mOnTimeChangedListener = onTimeChangedListener;
    }

    private void updateAmPmControl() {
        if (is24HourView()) {
            if (mAmPmSpinner != null) {
                mAmPmSpinner.setVisibility(View.GONE);
            } else {
                mAmPmButton.setVisibility(View.GONE);
            }
        } else {
            int index = mIsAm ? Calendar.AM : Calendar.PM;
            if (mAmPmSpinner != null) {
                mAmPmSpinner.setValue(index);
                mAmPmSpinner.setVisibility(View.VISIBLE);
            } else {
                mAmPmButton.setText(mAmPmStrings[index]);
                mAmPmButton.setVisibility(View.VISIBLE);
            }
        }
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
    }

    private void updateHourControl() {
        if (is24HourView()) {
            mHourSpinner.setMinValue(0);
            mHourSpinner.setMaxValue(23);
            mHourSpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
        } else {
            mHourSpinner.setMinValue(1);
            mHourSpinner.setMaxValue(12);
            mHourSpinner.setFormatter(null);
        }
    }

    private void updateInputState() {
        InputMethodManager inputMethodManager = (InputMethodManager) mContext
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputMethodManager != null) {
            if (inputMethodManager.isActive(mHourSpinnerInput)) {
                mHourSpinnerInput.clearFocus();
                inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
            } else if (inputMethodManager.isActive(mMinuteSpinnerInput)) {
                mMinuteSpinnerInput.clearFocus();
                inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
            } else if (inputMethodManager.isActive(mAmPmSpinnerInput)) {
                mAmPmSpinnerInput.clearFocus();
                inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy