package com.rey.material.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import com.rey.material.R;
import com.rey.material.util.ColorUtil;
import com.rey.material.util.ThemeUtil;
import com.rey.material.util.TypefaceUtil;
import com.rey.material.util.ViewUtil;
/**
* Created by Rey on 12/19/2014.
*/
public class TimePicker extends View{
private int mBackgroundColor;
private int mSelectionColor;
private int mSelectionRadius;
private int mTickSize;
private Typeface mTypeface;
private int mTextSize;
private int mTextColor;
private int mTextHighlightColor;
private boolean m24Hour = true;
private int mAnimDuration;
private Interpolator mInInterpolator;
private Interpolator mOutInterpolator;
private long mStartTime;
private float mAnimProgress;
private boolean mRunning;
private Paint mPaint;
private PointF mCenterPoint;
private float mOuterRadius;
private float mInnerRadius;
private float mSecondInnerRadius;
private float[] mLocations = new float[72];
private Rect mRect;
private String[] mTicks;
private int mMode = MODE_HOUR;
public static final int MODE_HOUR = 0;
public static final int MODE_MINUTE = 1;
private int mHour = 0;
private int mMinute = 0;
private boolean mEdited = false;
/**
* Interface definition for a callback to be invoked when the selected time is changed.
*/
public interface OnTimeChangedListener{
/**
* Called when the select mode is changed
* @param mode The current mode. Can be {@link #MODE_HOUR} or {@link #MODE_MINUTE}.
*/
public void onModeChanged(int mode);
/**
* Called then the selected hour is changed.
* @param oldValue The old hour value.
* @param newValue The new hour value.
*/
public void onHourChanged(int oldValue, int newValue);
/**
* Called then the selected minute is changed.
* @param oldValue The old minute value.
* @param newValue The new minute value.
*/
public void onMinuteChanged(int oldValue, int newValue);
}
private OnTimeChangedListener mOnTimeChangedListener;
public TimePicker(Context context) {
super(context);
init(context, null, 0, 0);
}
public TimePicker(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0, 0);
}
public TimePicker(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr, 0);
}
public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr, defStyleRes);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRect = new Rect();
initTickLabels();
setWillNotDraw(false);
applyStyle(context, attrs, defStyleAttr, defStyleRes);
}
/**
* Init the localized label of ticks. The value of ticks in order:
* 1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
* "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "0",
* "5", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55", "0"
*/
private void initTickLabels(){
String format = "%2d";
mTicks = new String[36];
for(int i = 0; i < 23; i++)
mTicks[i] = String.format(format, i + 1);
mTicks[23] = String.format(format, 0);
mTicks[35] = mTicks[23];
for(int i = 24; i < 35; i++)
mTicks[i] = String.format(format, (i - 23) * 5);
}
public void applyStyle(int styleId){
applyStyle(getContext(), null, 0, styleId);
}
private void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
mBackgroundColor = a.getColor(R.styleable.TimePicker_tp_backgroundColor, ColorUtil.getColor(ThemeUtil.colorPrimary(context, 0xFF000000), 0.25f));
mSelectionColor = a.getColor(R.styleable.TimePicker_tp_selectionColor, ThemeUtil.colorPrimary(context, 0xFF000000));
mSelectionRadius = a.getDimensionPixelOffset(R.styleable.TimePicker_tp_selectionRadius, ThemeUtil.dpToPx(context, 8));
mTickSize = a.getDimensionPixelSize(R.styleable.TimePicker_tp_tickSize, ThemeUtil.dpToPx(context, 1));
mTextSize = a.getDimensionPixelSize(R.styleable.TimePicker_tp_textSize, context.getResources().getDimensionPixelOffset(R.dimen.abc_text_size_caption_material));
mTextColor = a.getColor(R.styleable.TimePicker_tp_textColor, 0xFF000000);
mTextHighlightColor = a.getColor(R.styleable.TimePicker_tp_textHighlightColor, 0xFFFFFFFF);
mAnimDuration = a.getInteger(R.styleable.TimePicker_tp_animDuration, context.getResources().getInteger(android.R.integer.config_mediumAnimTime));
int resId = a.getResourceId(R.styleable.TimePicker_tp_inInterpolator, 0);
mInInterpolator = resId == 0 ? new DecelerateInterpolator() : AnimationUtils.loadInterpolator(context, resId);
resId = a.getResourceId(R.styleable.TimePicker_tp_outInterpolator, 0);
mOutInterpolator = resId == 0 ? new DecelerateInterpolator() : AnimationUtils.loadInterpolator(context, resId);
setMode(a.getInteger(R.styleable.TimePicker_tp_mode, mMode), false);
if(a.hasValue(R.styleable.TimePicker_tp_24Hour))
set24Hour(a.getBoolean(R.styleable.TimePicker_tp_24Hour, m24Hour));
else
set24Hour(DateFormat.is24HourFormat(context));
setHour(a.getInteger(R.styleable.TimePicker_tp_hour, mHour));
setMinute(a.getInteger(R.styleable.TimePicker_tp_minute, mMinute));
String familyName = a.getString(R.styleable.TimePicker_tp_fontFamily);
int style = a.getInteger(R.styleable.TimePicker_tp_textStyle, Typeface.NORMAL);
mTypeface = TypefaceUtil.load(context, familyName, style);
a.recycle();
}
public int getBackgroundColor(){
return mBackgroundColor;
}
public int getSelectionColor(){
return mSelectionColor;
}
public Typeface getTypeface(){
return mTypeface;
}
public int getTextSize(){
return mTextSize;
}
public int getTextColor(){
return mTextColor;
}
public int getTextHighlightColor(){
return mTextHighlightColor;
}
public int getAnimDuration(){
return mAnimDuration;
}
public Interpolator getInInterpolator(){
return mInInterpolator;
}
public Interpolator getOutInterpolator(){
return mOutInterpolator;
}
/**
* @return The current select mode. Can be {@link #MODE_HOUR} or {@link #MODE_MINUTE}.
*/
public int getMode(){
return mMode;
}
/**
* @return The selected hour value.
*/
public int getHour(){
return mHour;
}
/**
* @return The selected minute value.
*/
public int getMinute(){
return mMinute;
}
/**
* @return this TimePicker use 24-hour format or not.
*/
public boolean is24Hour(){
return m24Hour;
}
/**
* Set the select mode of this TimePicker.
* @param mode The select mode. Can be {@link #MODE_HOUR} or {@link #MODE_MINUTE}.
* @param animation Indicate that should show animation when switch select mode or not.
*/
public void setMode(int mode, boolean animation){
if(mMode != mode){
mMode = mode;
if(mOnTimeChangedListener != null)
mOnTimeChangedListener.onModeChanged(mMode);
if(animation)
startAnimation();
else
invalidate();
}
}
/**
* Set the selected hour value.
* @param hour The selected hour value.
*/
public void setHour(int hour){
if(m24Hour)
hour = Math.max(hour, 0) % 24;
else
hour = Math.max(hour, 0) % 12;
if(mHour != hour){
int old = mHour;
mHour = hour;
if(mOnTimeChangedListener != null)
mOnTimeChangedListener.onHourChanged(old, mHour);
if(mMode == MODE_HOUR)
invalidate();
}
}
/**
* Set the selected minute value.
* @param minute The selected minute value.
*/
public void setMinute(int minute){
minute = Math.min(Math.max(minute, 0), 59);
if(mMinute != minute){
int old = mMinute;
mMinute = minute;
if(mOnTimeChangedListener != null)
mOnTimeChangedListener.onMinuteChanged(old, mMinute);
if(mMode == MODE_MINUTE)
invalidate();
}
}
/**
* Set a listener will be called when the selected time is changed.
* @param listener The {@link TimePicker.OnTimeChangedListener} will be called.
*/
public void setOnTimeChangedListener(OnTimeChangedListener listener){
mOnTimeChangedListener = listener;
}
/**
* Set this TimePicker use 24-hour format or not.
* @param b
*/
public void set24Hour(boolean b){
if(m24Hour != b){
m24Hour = b;
if(!m24Hour && mHour > 11)
setHour(mHour - 12);
calculateTextLocation();
}
}
private float getAngle(int value, int mode){
switch (mode){
case MODE_HOUR:
return (float)(-Math.PI / 2 + Math.PI / 6 * value);
case MODE_MINUTE:
return (float)(-Math.PI / 2 + Math.PI / 30 * value);
default:
return 0f;
}
}
private int getSelectedTick(int value, int mode){
switch (mode){
case MODE_HOUR:
return value == 0 ? (m24Hour ? 23 : 11) : value - 1;
case MODE_MINUTE:
if(value % 5 == 0)
return (value == 0) ? 35 : (value / 5 + 23);
default:
return -1;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = (widthMode == MeasureSpec.UNSPECIFIED) ? mSelectionRadius * 12 : MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = (heightMode == MeasureSpec.UNSPECIFIED) ? mSelectionRadius * 12 : MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
int size = Math.min(widthSize, heightSize);
int width = (widthMode == MeasureSpec.EXACTLY) ? widthSize : size;
int height = (heightMode == MeasureSpec.EXACTLY) ? heightSize : size;
setMeasuredDimension(width + getPaddingLeft() + getPaddingRight(), height + getPaddingTop() + getPaddingBottom());
}
private void calculateTextLocation(){
if(mCenterPoint == null)
return;
double step = Math.PI / 6;
double angle = -Math.PI / 3;
float x, y;
mPaint.setTextSize(mTextSize);
mPaint.setTypeface(mTypeface);
mPaint.setTextAlign(Paint.Align.CENTER);
if(m24Hour){
for(int i = 0; i < 12; i++){
mPaint.getTextBounds(mTicks[i], 0, mTicks[i].length(), mRect);
if(i == 0)
mSecondInnerRadius = mInnerRadius - mSelectionRadius - mRect.height();
x = mCenterPoint.x + (float)Math.cos(angle) * mSecondInnerRadius;
y = mCenterPoint.y + (float)Math.sin(angle) * mSecondInnerRadius;
mLocations[i * 2] = x;
mLocations[i * 2 + 1] = y + mRect.height() / 2f;
angle += step;
}
for(int i = 12; i < mTicks.length; i++){
x = mCenterPoint.x + (float)Math.cos(angle) * mInnerRadius;
y = mCenterPoint.y + (float)Math.sin(angle) * mInnerRadius;
mPaint.getTextBounds(mTicks[i], 0, mTicks[i].length(), mRect);
mLocations[i * 2] = x;
mLocations[i * 2 + 1] = y + mRect.height() / 2f;
angle += step;
}
}
else{
for(int i = 0; i < 12; i++){
x = mCenterPoint.x + (float)Math.cos(angle) * mInnerRadius;
y = mCenterPoint.y + (float)Math.sin(angle) * mInnerRadius;
mPaint.getTextBounds(mTicks[i], 0, mTicks[i].length(), mRect);
mLocations[i * 2] = x;
mLocations[i * 2 + 1] = y + mRect.height() / 2f;
angle += step;
}
for(int i = 24; i < mTicks.length; i++){
x = mCenterPoint.x + (float)Math.cos(angle) * mInnerRadius;
y = mCenterPoint.y + (float)Math.sin(angle) * mInnerRadius;
mPaint.getTextBounds(mTicks[i], 0, mTicks[i].length(), mRect);
mLocations[i * 2] = x;
mLocations[i * 2 + 1] = y + mRect.height() / 2f;
angle += step;
}
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
int left = getPaddingLeft();
int top = getPaddingTop();
int size = Math.min(w - getPaddingLeft() - getPaddingRight(), h - getPaddingTop() - getPaddingBottom());
if(mCenterPoint == null)
mCenterPoint = new PointF();
mOuterRadius = size / 2f;
mCenterPoint.set(left + mOuterRadius, top + mOuterRadius);
mInnerRadius = mOuterRadius - mSelectionRadius - ThemeUtil.dpToPx(getContext(), 4);
calculateTextLocation();
}
private int getPointedValue(float x, float y, boolean isDown){
float radius = (float) Math.sqrt(Math.pow(x - mCenterPoint.x, 2) + Math.pow(y - mCenterPoint.y, 2));
if(isDown) {
if(mMode == MODE_HOUR && m24Hour){
if (radius > mInnerRadius + mSelectionRadius || radius < mSecondInnerRadius - mSelectionRadius)
return -1;
}
else if (radius > mInnerRadius + mSelectionRadius || radius < mInnerRadius - mSelectionRadius)
return -1;
}
float angle = (float)Math.atan2(y - mCenterPoint.y, x - mCenterPoint.x);
if(angle < 0)
angle += Math.PI * 2;
if(mMode == MODE_HOUR){
if(m24Hour){
if(radius > mSecondInnerRadius + mSelectionRadius / 2){
int value = (int) Math.round(angle * 6 / Math.PI) + 15;
if(value == 24)
return 0;
else if(value > 24)
return value - 12;
else
return value;
}
else{
int value = (int) Math.round(angle * 6 / Math.PI) + 3;
return value > 12 ? value - 12 : value;
}
}
else {
int value = (int) Math.round(angle * 6 / Math.PI) + 3;
return value > 11 ? value - 12 : value;
}
}
else if(mMode == MODE_MINUTE){
int value = (int)Math.round(angle * 30 / Math.PI) + 15;
return value > 59 ? value - 60 : value;
}
return -1;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
int value = getPointedValue(event.getX(), event.getY(), true);
if(value < 0)
return false;
else if(mMode == MODE_HOUR)
setHour(value);
else if(mMode == MODE_MINUTE)
setMinute(value);
mEdited = true;
return true;
case MotionEvent.ACTION_MOVE:
value = getPointedValue(event.getX(), event.getY(), false);
if(value < 0)
return true;
else if(mMode == MODE_HOUR)
setHour(value);
else if(mMode == MODE_MINUTE)
setMinute(value);
mEdited = true;
return true;
case MotionEvent.ACTION_UP:
if(mEdited && mMode == MODE_HOUR){
setMode(MODE_MINUTE, true);
mEdited = false;
return true;
}
break;
case MotionEvent.ACTION_CANCEL:
mEdited = false;
break;
}
return false;
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
mPaint.setColor(mBackgroundColor);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mOuterRadius, mPaint);
if(!mRunning){
float angle;
int selectedTick;
int start;
int length;
float radius;
if(mMode == MODE_HOUR){
angle = getAngle(mHour, MODE_HOUR);
selectedTick = getSelectedTick(mHour, MODE_HOUR);
start = 0;
length = m24Hour ? 24 : 12;
radius = m24Hour && selectedTick < 12 ? mSecondInnerRadius : mInnerRadius;
}
else{
angle = getAngle(mMinute, MODE_MINUTE);
selectedTick = getSelectedTick(mMinute, MODE_MINUTE);
start = 24;
length = 12;
radius = mInnerRadius;
}
mPaint.setColor(mSelectionColor);
float x = mCenterPoint.x + (float)Math.cos(angle) * radius;
float y = mCenterPoint.y + (float)Math.sin(angle) * radius;
canvas.drawCircle(x, y, mSelectionRadius, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mTickSize);
x -= (float)Math.cos(angle) * mSelectionRadius;
y -= (float)Math.sin(angle) * mSelectionRadius;
canvas.drawLine(mCenterPoint.x, mCenterPoint.y, x, y, mPaint);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mTextColor);
canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mTickSize * 2, mPaint);
mPaint.setTextSize(mTextSize);
mPaint.setTypeface(mTypeface);
mPaint.setTextAlign(Paint.Align.CENTER);
int index;
for(int i = 0; i < length; i++) {
index = start + i;
mPaint.setColor(index == selectedTick ? mTextHighlightColor : mTextColor);
canvas.drawText(mTicks[index], mLocations[index * 2], mLocations[index * 2 + 1], mPaint);
}
}
else{
float maxOffset = mOuterRadius - mInnerRadius + mTextSize / 2;
int textOutColor = ColorUtil.getColor(mTextColor, 1f - mAnimProgress);
int textHighlightOutColor= ColorUtil.getColor(mTextHighlightColor, 1f - mAnimProgress);
int textInColor = ColorUtil.getColor(mTextColor, mAnimProgress);
int textHighlightInColor= ColorUtil.getColor(mTextHighlightColor, mAnimProgress);
float outOffset;
float inOffset;
float outAngle;
float inAngle;
int outStart;
int inStart;
int outLength;
int inLength;
int outSelectedTick;
int inSelectedTick;
float outRadius;
float inRadius;
if(mMode == MODE_MINUTE){
outAngle = getAngle(mHour, MODE_HOUR);
inAngle = getAngle(mMinute, MODE_MINUTE);
outOffset = mOutInterpolator.getInterpolation(mAnimProgress) * maxOffset;
inOffset = (1f - mInInterpolator.getInterpolation(mAnimProgress)) * -maxOffset;
outSelectedTick = getSelectedTick(mHour, MODE_HOUR);
inSelectedTick = getSelectedTick(mMinute, MODE_MINUTE);
outStart = 0;
outLength = m24Hour ? 24 : 12;
outRadius = m24Hour && outSelectedTick < 12 ? mSecondInnerRadius : mInnerRadius;
inStart = 24;
inLength = 12;
inRadius = mInnerRadius;
}
else{
outAngle = getAngle(mMinute, MODE_MINUTE);
inAngle = getAngle(mHour, MODE_HOUR);
outOffset = mOutInterpolator.getInterpolation(mAnimProgress) * -maxOffset;
inOffset = (1f - mInInterpolator.getInterpolation(mAnimProgress)) * maxOffset;
outSelectedTick = getSelectedTick(mMinute, MODE_MINUTE);
inSelectedTick = getSelectedTick(mHour, MODE_HOUR);
outStart = 24;
outLength = 12;
outRadius = mInnerRadius;
inStart = 0;
inLength = m24Hour ? 24 : 12;
inRadius = m24Hour && inSelectedTick < 12 ? mSecondInnerRadius : mInnerRadius;
}
mPaint.setColor(ColorUtil.getColor(mSelectionColor, 1f - mAnimProgress));
float x = mCenterPoint.x + (float)Math.cos(outAngle) * (outRadius + outOffset);
float y = mCenterPoint.y + (float)Math.sin(outAngle) * (outRadius + outOffset);
canvas.drawCircle(x, y, mSelectionRadius, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mTickSize);
x -= (float)Math.cos(outAngle) * mSelectionRadius;
y -= (float)Math.sin(outAngle) * mSelectionRadius;
canvas.drawLine(mCenterPoint.x, mCenterPoint.y, x, y, mPaint);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(ColorUtil.getColor(mSelectionColor, mAnimProgress));
x = mCenterPoint.x + (float)Math.cos(inAngle) * (inRadius + inOffset);
y = mCenterPoint.y + (float)Math.sin(inAngle) * (inRadius + inOffset);
canvas.drawCircle(x, y, mSelectionRadius, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mTickSize);
x -= (float)Math.cos(inAngle) * mSelectionRadius;
y -= (float)Math.sin(inAngle) * mSelectionRadius;
canvas.drawLine(mCenterPoint.x, mCenterPoint.y, x, y, mPaint);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mTextColor);
canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mTickSize * 2, mPaint);
mPaint.setTextSize(mTextSize);
mPaint.setTypeface(mTypeface);
mPaint.setTextAlign(Paint.Align.CENTER);
double step = Math.PI / 6;
double angle = -Math.PI / 3;
int index;
for(int i = 0; i < outLength; i++){
index = i + outStart;
x = mLocations[index * 2] + (float)Math.cos(angle) * outOffset;
y = mLocations[index * 2 + 1] + (float)Math.sin(angle) * outOffset;
mPaint.setColor(index == outSelectedTick ? textHighlightOutColor : textOutColor);
canvas.drawText(mTicks[index], x, y, mPaint);
angle += step;
}
for(int i = 0; i < inLength; i++){
index = i + inStart;
x = mLocations[index * 2] + (float)Math.cos(angle) * inOffset;
y = mLocations[index * 2 + 1] + (float)Math.sin(angle) * inOffset;
mPaint.setColor(index == inSelectedTick ? textHighlightInColor : textInColor);
canvas.drawText(mTicks[index], x, y, mPaint);
angle += step;
}
}
}
private void resetAnimation(){
mStartTime = SystemClock.uptimeMillis();
mAnimProgress = 0f;
}
private void startAnimation() {
if(getHandler() != null){
resetAnimation();
mRunning = true;
getHandler().postAtTime(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
}
invalidate();
}
private void stopAnimation() {
mRunning = false;
mAnimProgress = 1f;
if(getHandler() != null)
getHandler().removeCallbacks(mUpdater);
invalidate();
}
private final Runnable mUpdater = new Runnable() {
@Override
public void run() {
update();
}
};
private void update(){
long curTime = SystemClock.uptimeMillis();
mAnimProgress = Math.min(1f, (float)(curTime - mStartTime) / mAnimDuration);
if(mAnimProgress == 1f)
stopAnimation();
if(mRunning) {
if(getHandler() != null)
getHandler().postAtTime(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
else
stopAnimation();
}
invalidate();
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.mode = mMode;
ss.hour = mHour;
ss.minute = mMinute;
ss.is24Hour = m24Hour;
return ss;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
set24Hour(ss.is24Hour);
setMode(ss.mode, false);
setHour(ss.hour);
setMinute(ss.minute);
}
static class SavedState extends BaseSavedState {
int mode;
int hour;
int minute;
boolean is24Hour;
/**
* Constructor called from {@link Switch#onSaveInstanceState()}
*/
SavedState(Parcelable superState) {
super(superState);
}
/**
* Constructor called from {@link #CREATOR}
*/
private SavedState(Parcel in) {
super(in);
mode = in.readInt();
hour = in.readInt();
minute = in.readInt();
is24Hour = in.readInt() == 1;
}
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeValue(mode);
out.writeValue(hour);
out.writeValue(minute);
out.writeValue(is24Hour ? 1 : 0);
}
@Override
public String toString() {
return "TimePicker.SavedState{"
+ Integer.toHexString(System.identityHashCode(this))
+ " mode=" + mode
+ " hour=" + hour
+ " minute=" + minute
+ "24hour=" + is24Hour + "}";
}
public static final Creator<SavedState> CREATOR
= new Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}