RadialTimePickerView.java revision 5134478151d8aa3d776f8d4f368dbcdbc501a92a
1eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio/* 2eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Copyright (C) 2013 The Android Open Source Project 3eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 4eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License"); 5eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * you may not use this file except in compliance with the License. 6eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * You may obtain a copy of the License at 7eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 8eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * http://www.apache.org/licenses/LICENSE-2.0 9eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 10eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Unless required by applicable law or agreed to in writing, software 11eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS, 12eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * See the License for the specific language governing permissions and 14eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * limitations under the License. 15eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 16eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 17eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Megliopackage android.widget; 18eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 19eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.animation.Animator; 20eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.animation.AnimatorSet; 21eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.animation.Keyframe; 22eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.animation.ObjectAnimator; 23eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.animation.PropertyValuesHolder; 24eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.animation.ValueAnimator; 25eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.annotation.SuppressLint; 26eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.content.Context; 27eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.content.res.Resources; 28eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.content.res.TypedArray; 29eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.graphics.Canvas; 30eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.graphics.Color; 31eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.graphics.Paint; 32eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.graphics.Typeface; 33eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.graphics.RectF; 34eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.os.Bundle; 35eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.text.format.DateUtils; 36eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.text.format.Time; 37eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.util.AttributeSet; 38eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.util.Log; 395134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viveretteimport android.util.TypedValue; 40eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.HapticFeedbackConstants; 41eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.MotionEvent; 42eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.View; 43eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.ViewGroup; 44eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.accessibility.AccessibilityEvent; 45eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.accessibility.AccessibilityNodeInfo; 46eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 47eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport com.android.internal.R; 48eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 49eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport java.text.DateFormatSymbols; 50eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport java.util.ArrayList; 51eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport java.util.Calendar; 52eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport java.util.Locale; 53eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 54eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio/** 55eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * View to show a clock circle picker (with one or two picking circles) 56eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 57eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @hide 58eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 59eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Megliopublic class RadialTimePickerView extends View implements View.OnTouchListener { 60eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final String TAG = "ClockView"; 61eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 62eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final boolean DEBUG = false; 63eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 64eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int DEBUG_COLOR = 0x20FF0000; 65eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int DEBUG_TEXT_COLOR = 0x60FF0000; 66eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int DEBUG_STROKE_WIDTH = 2; 67eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 68eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int HOURS = 0; 69eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int MINUTES = 1; 70eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int HOURS_INNER = 2; 71eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int AMPM = 3; 72eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 73eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int SELECTOR_CIRCLE = 0; 74eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int SELECTOR_DOT = 1; 75eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int SELECTOR_LINE = 2; 76eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 77eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int AM = 0; 78eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int PM = 1; 79eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 80eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Opaque alpha level 81eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int ALPHA_OPAQUE = 255; 82eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 83eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Transparent alpha level 84eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int ALPHA_TRANSPARENT = 0; 85eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 86eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Alpha level of color for selector. 87eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private static final int ALPHA_SELECTOR = 255; // was 51 88eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 89eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Alpha level of color for selected circle. 90eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int ALPHA_AMPM_SELECTED = ALPHA_SELECTOR; 91eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 92eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Alpha level of color for pressed circle. 93eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private static final int ALPHA_AMPM_PRESSED = 255; // was 175 94eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 95eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final float COSINE_30_DEGREES = ((float) Math.sqrt(3)) * 0.5f; 96eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final float SINE_30_DEGREES = 0.5f; 97eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 98eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int DEGREES_FOR_ONE_HOUR = 30; 99eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int DEGREES_FOR_ONE_MINUTE = 6; 100eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 101eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int[] HOURS_NUMBERS = {12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; 102eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int[] HOURS_NUMBERS_24 = {0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}; 103eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int[] MINUTES_NUMBERS = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55}; 104eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 105eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int CENTER_RADIUS = 2; 106eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 107eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static int[] sSnapPrefer30sMap = new int[361]; 108eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 109eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final String[] mHours12Texts = new String[12]; 110eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final String[] mOuterHours24Texts = new String[12]; 111eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final String[] mInnerHours24Texts = new String[12]; 112eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final String[] mMinutesTexts = new String[12]; 113eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 114eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final String[] mAmPmText = new String[2]; 115eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 116eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final Paint[] mPaint = new Paint[2]; 117eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private final int[] mColor = new int[2]; 118eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private final IntHolder[] mAlpha = new IntHolder[2]; 119eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 120eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final Paint mPaintCenter = new Paint(); 121eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 122eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final Paint[][] mPaintSelector = new Paint[2][3]; 123eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private final int[][] mColorSelector = new int[2][3]; 124eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private final IntHolder[][] mAlphaSelector = new IntHolder[2][3]; 125eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 126eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final Paint mPaintAmPmText = new Paint(); 127eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final Paint[] mPaintAmPmCircle = new Paint[2]; 128eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 129eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final Paint mPaintBackground = new Paint(); 130eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final Paint mPaintDisabled = new Paint(); 131eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final Paint mPaintDebug = new Paint(); 132eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 133eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private Typeface mTypeface; 134eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 135eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean mIs24HourMode; 136eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean mShowHours; 137eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean mIsOnInnerCircle; 138eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 139eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mXCenter; 140eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mYCenter; 141eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 142eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float[] mCircleRadius = new float[3]; 143eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 144eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mMinHypotenuseForInnerNumber; 145eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mMaxHypotenuseForOuterNumber; 146eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mHalfwayHypotenusePoint; 147eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 148eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float[] mTextSize = new float[2]; 149eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float mInnerTextSize; 150eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 151eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float[][] mTextGridHeights = new float[2][7]; 152eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float[][] mTextGridWidths = new float[2][7]; 153eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 154eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float[] mInnerTextGridHeights = new float[7]; 155eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float[] mInnerTextGridWidths = new float[7]; 156eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 157eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private String[] mOuterTextHours; 158eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private String[] mInnerTextHours; 159eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private String[] mOuterTextMinutes; 160eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 161eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float[] mCircleRadiusMultiplier = new float[2]; 162eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float[] mNumbersRadiusMultiplier = new float[3]; 163eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 164eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float[] mTextSizeMultiplier = new float[3]; 165eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 166eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float[] mAnimationRadiusMultiplier = new float[3]; 167eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 168eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float mTransitionMidRadiusMultiplier; 169eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float mTransitionEndRadiusMultiplier; 170eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 171eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private AnimatorSet mTransition; 172eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private InvalidateUpdateListener mInvalidateUpdateListener = new InvalidateUpdateListener(); 173eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 174eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int[] mLineLength = new int[3]; 175eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int[] mSelectionRadius = new int[3]; 176eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float mSelectionRadiusMultiplier; 177eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int[] mSelectionDegrees = new int[3]; 178eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 179eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mAmPmCircleRadius; 180eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float mAmPmYCenter; 181eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 182eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float mAmPmCircleRadiusMultiplier; 183eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mAmPmTextColor; 184eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 185eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float mLeftIndicatorXCenter; 186eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private float mRightIndicatorXCenter; 187eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 188eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mAmPmUnselectedColor; 189eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mAmPmSelectedColor; 190eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 191eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mAmOrPm; 192eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mAmOrPmPressed; 193eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1945134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette private int mDisabledAlpha; 1955134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette 196eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private RectF mRectF = new RectF(); 197eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean mInputEnabled = true; 198eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private OnValueSelectedListener mListener; 199eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 200eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final ArrayList<Animator> mHoursToMinutesAnims = new ArrayList<Animator>(); 201eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final ArrayList<Animator> mMinuteToHoursAnims = new ArrayList<Animator>(); 202eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 203eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public interface OnValueSelectedListener { 204eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance); 205eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 206eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 207eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio static { 208eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Prepare mapping to snap touchable degrees to selectable degrees. 209eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio preparePrefer30sMap(); 210eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 211eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 212eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 213eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Split up the 360 degrees of the circle among the 60 selectable values. Assigns a larger 214eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * selectable area to each of the 12 visible values, such that the ratio of space apportioned 215eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * to a visible value : space apportioned to a non-visible value will be 14 : 4. 216eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * E.g. the output of 30 degrees should have a higher range of input associated with it than 217eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * the output of 24 degrees, because 30 degrees corresponds to a visible number on the clock 218eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * circle (5 on the minutes, 1 or 13 on the hours). 219eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 220eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static void preparePrefer30sMap() { 221eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We'll split up the visible output and the non-visible output such that each visible 222eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // output will correspond to a range of 14 associated input degrees, and each non-visible 223eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // output will correspond to a range of 4 associate input degrees, so visible numbers 224eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // are more than 3 times easier to get than non-visible numbers: 225eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // {354-359,0-7}:0, {8-11}:6, {12-15}:12, {16-19}:18, {20-23}:24, {24-37}:30, etc. 226eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // 227eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // If an output of 30 degrees should correspond to a range of 14 associated degrees, then 228eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // we'll need any input between 24 - 37 to snap to 30. Working out from there, 20-23 should 229eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // snap to 24, while 38-41 should snap to 36. This is somewhat counter-intuitive, that you 230eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // can be touching 36 degrees but have the selection snapped to 30 degrees; however, this 231eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // inconsistency isn't noticeable at such fine-grained degrees, and it affords us the 232eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // ability to aggressively prefer the visible values by a factor of more than 3:1, which 233eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // greatly contributes to the selectability of these values. 234eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 235eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The first output is 0, and each following output will increment by 6 {0, 6, 12, ...}. 236eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int snappedOutputDegrees = 0; 237eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Count of how many inputs we've designated to the specified output. 238eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int count = 1; 239eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // How many input we expect for a specified output. This will be 14 for output divisible 240eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // by 30, and 4 for the remaining output. We'll special case the outputs of 0 and 360, so 241eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // the caller can decide which they need. 242eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int expectedCount = 8; 243eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Iterate through the input. 244eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (int degrees = 0; degrees < 361; degrees++) { 245eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Save the input-output mapping. 246eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio sSnapPrefer30sMap[degrees] = snappedOutputDegrees; 247eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // If this is the last input for the specified output, calculate the next output and 248eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // the next expected count. 249eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (count == expectedCount) { 250eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio snappedOutputDegrees += 6; 251eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (snappedOutputDegrees == 360) { 252eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio expectedCount = 7; 253eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (snappedOutputDegrees % 30 == 0) { 254eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio expectedCount = 14; 255eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 256eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio expectedCount = 4; 257eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 258eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio count = 1; 259eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 260eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio count++; 261eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 262eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 263eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 264eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 265eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 266eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Returns mapping of any input degrees (0 to 360) to one of 60 selectable output degrees, 267eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * where the degrees corresponding to visible numbers (i.e. those divisible by 30) will be 268eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * weighted heavier than the degrees corresponding to non-visible numbers. 269eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * See {@link #preparePrefer30sMap()} documentation for the rationale and generation of the 270eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * mapping. 271eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 272eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static int snapPrefer30s(int degrees) { 273eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (sSnapPrefer30sMap == null) { 274eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return -1; 275eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 276eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return sSnapPrefer30sMap[degrees]; 277eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 278eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 279eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 280eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Returns mapping of any input degrees (0 to 360) to one of 12 visible output degrees (all 281eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * multiples of 30), where the input will be "snapped" to the closest visible degrees. 282eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @param degrees The input degrees 283eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @param forceHigherOrLower The output may be forced to either the higher or lower step, or may 284eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * be allowed to snap to whichever is closer. Use 1 to force strictly higher, -1 to force 285eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * strictly lower, and 0 to snap to the closer one. 286eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @return output degrees, will be a multiple of 30 287eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 288eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static int snapOnly30s(int degrees, int forceHigherOrLower) { 289eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int stepSize = DEGREES_FOR_ONE_HOUR; 290eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int floor = (degrees / stepSize) * stepSize; 291eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int ceiling = floor + stepSize; 292eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (forceHigherOrLower == 1) { 293eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = ceiling; 294eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (forceHigherOrLower == -1) { 295eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (degrees == floor) { 296eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio floor -= stepSize; 297eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 298eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = floor; 299eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 300eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if ((degrees - floor) < (ceiling - degrees)) { 301eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = floor; 302eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 303eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = ceiling; 304eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 305eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 306eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return degrees; 307eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 308eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 309eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public RadialTimePickerView(Context context, AttributeSet attrs) { 310eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio this(context, attrs, R.attr.timePickerStyle); 311eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 312eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 313eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public RadialTimePickerView(Context context, AttributeSet attrs, int defStyle) { 314eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio super(context, attrs); 315eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 3165134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette // Pull disabled alpha from theme. 3175134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette final TypedValue outValue = new TypedValue(); 3185134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true); 3195134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette mDisabledAlpha = (int) (outValue.getFloat() * 255 + 0.5f); 3205134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette 321eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // process style attributes 3225134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette final Resources res = getResources(); 323eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.TimePicker, 324eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio defStyle, 0); 325eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 326eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmPmUnselectedColor = a.getColor(R.styleable.TimePicker_amPmUnselectedBackgroundColor, 327830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette res.getColor(R.color.timepicker_default_ampm_unselected_background_color_material)); 328eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmPmSelectedColor = a.getColor(R.styleable.TimePicker_amPmSelectedBackgroundColor, 329830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette res.getColor(R.color.timepicker_default_ampm_selected_background_color_material)); 330eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 331eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmPmTextColor = a.getColor(R.styleable.TimePicker_amPmTextColor, 332830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette res.getColor(R.color.timepicker_default_text_color_material)); 333eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 334eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypeface = Typeface.create("sans-serif", Typeface.NORMAL); 335eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 336eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette // Initialize all alpha values to opaque. 337eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette for (int i = 0; i < mAlpha.length; i++) { 338eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mAlpha[i] = new IntHolder(ALPHA_OPAQUE); 339eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette } 340eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette for (int i = 0; i < mAlphaSelector.length; i++) { 341eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette for (int j = 0; j < mAlphaSelector[i].length; j++) { 342eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mAlphaSelector[i][j] = new IntHolder(ALPHA_OPAQUE); 343eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette } 344eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette } 345eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 346eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette final int numbersTextColor = a.getColor(R.styleable.TimePicker_numbersTextColor, 347830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette res.getColor(R.color.timepicker_default_text_color_material)); 348eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 349eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaint[HOURS] = new Paint(); 350eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaint[HOURS].setAntiAlias(true); 351eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaint[HOURS].setTextAlign(Paint.Align.CENTER); 352eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColor[HOURS] = numbersTextColor; 353eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 354eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaint[MINUTES] = new Paint(); 355eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaint[MINUTES].setAntiAlias(true); 356eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaint[MINUTES].setTextAlign(Paint.Align.CENTER); 357eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColor[MINUTES] = numbersTextColor; 358eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 359eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintCenter.setColor(numbersTextColor); 360eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintCenter.setAntiAlias(true); 361eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintCenter.setTextAlign(Paint.Align.CENTER); 362eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 363eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[HOURS][SELECTOR_CIRCLE] = new Paint(); 364eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[HOURS][SELECTOR_CIRCLE].setAntiAlias(true); 365eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColorSelector[HOURS][SELECTOR_CIRCLE] = a.getColor( 366eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette R.styleable.TimePicker_numbersSelectorColor, 367830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette R.color.timepicker_default_selector_color_material); 368eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 369eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[HOURS][SELECTOR_DOT] = new Paint(); 370eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[HOURS][SELECTOR_DOT].setAntiAlias(true); 371eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColorSelector[HOURS][SELECTOR_DOT] = a.getColor( 372eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette R.styleable.TimePicker_numbersSelectorColor, 373830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette R.color.timepicker_default_selector_color_material); 374eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 375eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[HOURS][SELECTOR_LINE] = new Paint(); 376eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[HOURS][SELECTOR_LINE].setAntiAlias(true); 377eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[HOURS][SELECTOR_LINE].setStrokeWidth(2); 378eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColorSelector[HOURS][SELECTOR_LINE] = a.getColor( 379eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette R.styleable.TimePicker_numbersSelectorColor, 380830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette R.color.timepicker_default_selector_color_material); 381eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 382eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[MINUTES][SELECTOR_CIRCLE] = new Paint(); 383eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[MINUTES][SELECTOR_CIRCLE].setAntiAlias(true); 384eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColorSelector[MINUTES][SELECTOR_CIRCLE] = a.getColor( 385eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette R.styleable.TimePicker_numbersSelectorColor, 386830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette R.color.timepicker_default_selector_color_material); 387eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 388eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[MINUTES][SELECTOR_DOT] = new Paint(); 389eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[MINUTES][SELECTOR_DOT].setAntiAlias(true); 390eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColorSelector[MINUTES][SELECTOR_DOT] = a.getColor( 391eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette R.styleable.TimePicker_numbersSelectorColor, 392830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette R.color.timepicker_default_selector_color_material); 393eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 394eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[MINUTES][SELECTOR_LINE] = new Paint(); 395eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[MINUTES][SELECTOR_LINE].setAntiAlias(true); 396eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintSelector[MINUTES][SELECTOR_LINE].setStrokeWidth(2); 397eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColorSelector[MINUTES][SELECTOR_LINE] = a.getColor( 398eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette R.styleable.TimePicker_numbersSelectorColor, 399830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette R.color.timepicker_default_selector_color_material); 400eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 401eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmText.setColor(mAmPmTextColor); 402eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmText.setTypeface(mTypeface); 403eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmText.setAntiAlias(true); 404eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmText.setTextAlign(Paint.Align.CENTER); 405eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 406eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmCircle[AM] = new Paint(); 407eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmCircle[AM].setAntiAlias(true); 408eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmCircle[PM] = new Paint(); 409eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmCircle[PM].setAntiAlias(true); 410eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 411eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mPaintBackground.setColor(a.getColor(R.styleable.TimePicker_numbersBackgroundColor, 412830960cce032a1b0dc0cf54bcc44ffa339388c21Alan Viverette res.getColor(R.color.timepicker_default_numbers_background_color_material))); 413eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintBackground.setAntiAlias(true); 414eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 415eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (DEBUG) { 416eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintDebug.setColor(DEBUG_COLOR); 417eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintDebug.setAntiAlias(true); 418eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintDebug.setStrokeWidth(DEBUG_STROKE_WIDTH); 419eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintDebug.setStyle(Paint.Style.STROKE); 420eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintDebug.setTextAlign(Paint.Align.CENTER); 421eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 422eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 423eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mShowHours = true; 424eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIs24HourMode = false; 425eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmOrPm = AM; 426eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmOrPmPressed = -1; 427eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 428eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio initHoursAndMinutesText(); 429eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio initData(); 430eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 431eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransitionMidRadiusMultiplier = Float.parseFloat( 432eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_transition_mid_radius_multiplier)); 433eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransitionEndRadiusMultiplier = Float.parseFloat( 434eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_transition_end_radius_multiplier)); 435eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 436eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTextGridHeights[HOURS] = new float[7]; 437eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTextGridHeights[MINUTES] = new float[7]; 438eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 439eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionRadiusMultiplier = Float.parseFloat( 440eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_selection_radius_multiplier)); 441eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 442eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette a.recycle(); 443eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 444eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setOnTouchListener(this); 445eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 446eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Initial values 447eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final Calendar calendar = Calendar.getInstance(Locale.getDefault()); 448eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int currentHour = calendar.get(Calendar.HOUR_OF_DAY); 449eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int currentMinute = calendar.get(Calendar.MINUTE); 450eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 451eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setCurrentHour(currentHour); 452eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setCurrentMinute(currentMinute); 453eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 454eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setHapticFeedbackEnabled(true); 455eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 456eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 457eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 458eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Measure the view to end up as a square, based on the minimum of the height and width. 459eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 460eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 461eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 462eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); 463eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int widthMode = MeasureSpec.getMode(widthMeasureSpec); 464eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int measuredHeight = MeasureSpec.getSize(heightMeasureSpec); 465eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int heightMode = MeasureSpec.getMode(heightMeasureSpec); 466eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int minDimension = Math.min(measuredWidth, measuredHeight); 467eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 468eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio super.onMeasure(MeasureSpec.makeMeasureSpec(minDimension, widthMode), 469eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio MeasureSpec.makeMeasureSpec(minDimension, heightMode)); 470eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 471eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 472eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void initialize(int hour, int minute, boolean is24HourMode) { 473eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIs24HourMode = is24HourMode; 474eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setCurrentHour(hour); 475eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setCurrentMinute(minute); 476eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 477eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 478eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setCurrentItemShowing(int item, boolean animate) { 479eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio switch (item){ 480eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case HOURS: 481eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio showHours(animate); 482eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio break; 483eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case MINUTES: 484eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio showMinutes(animate); 485eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio break; 486eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio default: 487eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Log.e(TAG, "ClockView does not support showing item " + item); 488eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 489eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 490eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 491eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public int getCurrentItemShowing() { 492eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mShowHours ? HOURS : MINUTES; 493eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 494eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 495eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setOnValueSelectedListener(OnValueSelectedListener listener) { 496eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mListener = listener; 497eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 498eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 499eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setCurrentHour(int hour) { 500eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int degrees = (hour % 12) * DEGREES_FOR_ONE_HOUR; 501eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionDegrees[HOURS] = degrees; 502eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionDegrees[HOURS_INNER] = degrees; 503eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmOrPm = ((hour % 24) < 12) ? AM : PM; 504eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourMode) { 505eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIsOnInnerCircle = (mAmOrPm == AM); 506eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 507eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIsOnInnerCircle = false; 508eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 509eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio initData(); 510eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateLayoutData(); 511eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio invalidate(); 512eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 513eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 514eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Return hours in 0-23 range 515eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public int getCurrentHour() { 516eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int hours = 517eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionDegrees[mIsOnInnerCircle ? HOURS_INNER : HOURS] / DEGREES_FOR_ONE_HOUR; 518eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourMode) { 519eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIsOnInnerCircle) { 520eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio hours = hours % 12; 521eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 522eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (hours != 0) { 523eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio hours += 12; 524eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 525eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 526eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 527eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio hours = hours % 12; 528eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (hours == 0) { 529eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mAmOrPm == PM) { 530eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio hours = 12; 531eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 532eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 533eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mAmOrPm == PM) { 534eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio hours += 12; 535eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 536eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 537eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 538eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return hours; 539eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 540eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 541eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setCurrentMinute(int minute) { 542eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionDegrees[MINUTES] = (minute % 60) * DEGREES_FOR_ONE_MINUTE; 543eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio invalidate(); 544eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 545eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 546eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Returns minutes in 0-59 range 547eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public int getCurrentMinute() { 548eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return (mSelectionDegrees[MINUTES] / DEGREES_FOR_ONE_MINUTE); 549eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 550eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 551eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setAmOrPm(int val) { 552eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmOrPm = (val % 2); 553eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio invalidate(); 554eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 555eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 556eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public int getAmOrPm() { 557eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mAmOrPm; 558eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 559eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 560eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void swapAmPm() { 561eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmOrPm = (mAmOrPm == AM) ? PM : AM; 562eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio invalidate(); 563eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 564eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 565eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void showHours(boolean animate) { 566eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mShowHours) return; 567eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mShowHours = true; 568eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (animate) { 569eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio startMinutesToHoursAnimation(); 570eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 571eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio initData(); 572eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateLayoutData(); 573eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio invalidate(); 574eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 575eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 576eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void showMinutes(boolean animate) { 577eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mShowHours) return; 578eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mShowHours = false; 579eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (animate) { 580eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio startHoursToMinutesAnimation(); 581eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 582eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio initData(); 583eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateLayoutData(); 584eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio invalidate(); 585eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 586eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 587eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void initHoursAndMinutesText() { 588eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Initialize the hours and minutes numbers. 589eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (int i = 0; i < 12; i++) { 590eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHours12Texts[i] = String.format("%d", HOURS_NUMBERS[i]); 591eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mOuterHours24Texts[i] = String.format("%02d", HOURS_NUMBERS_24[i]); 592eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInnerHours24Texts[i] = String.format("%d", HOURS_NUMBERS[i]); 593eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMinutesTexts[i] = String.format("%02d", MINUTES_NUMBERS[i]); 594eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 595eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 596eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String[] amPmTexts = new DateFormatSymbols().getAmPmStrings(); 597eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmPmText[AM] = amPmTexts[0]; 598eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmPmText[PM] = amPmTexts[1]; 599eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 600eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 601eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void initData() { 602eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourMode) { 603eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mOuterTextHours = mOuterHours24Texts; 604eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInnerTextHours = mInnerHours24Texts; 605eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 606eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mOuterTextHours = mHours12Texts; 607eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInnerTextHours = null; 608eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 609eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 610eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mOuterTextMinutes = mMinutesTexts; 611eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 612eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final Resources res = getResources(); 613eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 614eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mShowHours) { 615eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourMode) { 616eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mCircleRadiusMultiplier[HOURS] = Float.parseFloat( 617eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_circle_radius_multiplier_24HourMode)); 618eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mNumbersRadiusMultiplier[HOURS] = Float.parseFloat( 619eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_numbers_radius_multiplier_outer)); 620eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTextSizeMultiplier[HOURS] = Float.parseFloat( 621eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_text_size_multiplier_outer)); 622eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 623eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mNumbersRadiusMultiplier[HOURS_INNER] = Float.parseFloat( 624eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_numbers_radius_multiplier_inner)); 625eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTextSizeMultiplier[HOURS_INNER] = Float.parseFloat( 626eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_text_size_multiplier_inner)); 627eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 628eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mCircleRadiusMultiplier[HOURS] = Float.parseFloat( 629eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_circle_radius_multiplier)); 630eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mNumbersRadiusMultiplier[HOURS] = Float.parseFloat( 631eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_numbers_radius_multiplier_normal)); 632eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTextSizeMultiplier[HOURS] = Float.parseFloat( 633eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_text_size_multiplier_normal)); 634eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 635eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 636eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mCircleRadiusMultiplier[MINUTES] = Float.parseFloat( 637eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_circle_radius_multiplier)); 638eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mNumbersRadiusMultiplier[MINUTES] = Float.parseFloat( 639eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_numbers_radius_multiplier_normal)); 640eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTextSizeMultiplier[MINUTES] = Float.parseFloat( 641eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_text_size_multiplier_normal)); 642eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 643eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 644eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAnimationRadiusMultiplier[HOURS] = 1; 645eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAnimationRadiusMultiplier[HOURS_INNER] = 1; 646eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAnimationRadiusMultiplier[MINUTES] = 1; 647eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 648eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmPmCircleRadiusMultiplier = Float.parseFloat( 649eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio res.getString(R.string.timepicker_ampm_circle_radius_multiplier)); 650eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 651eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mAlpha[HOURS].setValue(mShowHours ? ALPHA_OPAQUE : ALPHA_TRANSPARENT); 652eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mAlpha[MINUTES].setValue(mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE); 653eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 654eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mAlphaSelector[HOURS][SELECTOR_CIRCLE].setValue( 655eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mShowHours ? ALPHA_SELECTOR : ALPHA_TRANSPARENT); 656eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mAlphaSelector[HOURS][SELECTOR_DOT].setValue( 657eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mShowHours ? ALPHA_OPAQUE : ALPHA_TRANSPARENT); 658eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mAlphaSelector[HOURS][SELECTOR_LINE].setValue( 659eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mShowHours ? ALPHA_SELECTOR : ALPHA_TRANSPARENT); 660eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 661eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mAlphaSelector[MINUTES][SELECTOR_CIRCLE].setValue( 662eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mShowHours ? ALPHA_TRANSPARENT : ALPHA_SELECTOR); 663eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mAlphaSelector[MINUTES][SELECTOR_DOT].setValue( 664eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE); 665eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mAlphaSelector[MINUTES][SELECTOR_LINE].setValue( 666eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mShowHours ? ALPHA_TRANSPARENT : ALPHA_SELECTOR); 667eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 668eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 669eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 670eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 671eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateLayoutData(); 672eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 673eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 674eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void updateLayoutData() { 675eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mXCenter = getWidth() / 2; 676eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mYCenter = getHeight() / 2; 677eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 678eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int min = Math.min(mXCenter, mYCenter); 679eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 680eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mCircleRadius[HOURS] = min * mCircleRadiusMultiplier[HOURS]; 681eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mCircleRadius[HOURS_INNER] = min * mCircleRadiusMultiplier[HOURS]; 682eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mCircleRadius[MINUTES] = min * mCircleRadiusMultiplier[MINUTES]; 683eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 684eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mIs24HourMode) { 685eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We'll need to draw the AM/PM circles, so the main circle will need to have 686eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // a slightly higher center. To keep the entire view centered vertically, we'll 687eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // have to push it up by half the radius of the AM/PM circles. 688eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int amPmCircleRadius = (int) (mCircleRadius[HOURS] * mAmPmCircleRadiusMultiplier); 689eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mYCenter -= amPmCircleRadius / 2; 690eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 691eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 692eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMinHypotenuseForInnerNumber = (int) (mCircleRadius[HOURS] 693eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * mNumbersRadiusMultiplier[HOURS_INNER]) - mSelectionRadius[HOURS]; 694eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMaxHypotenuseForOuterNumber = (int) (mCircleRadius[HOURS] 695eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * mNumbersRadiusMultiplier[HOURS]) + mSelectionRadius[HOURS]; 696eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHalfwayHypotenusePoint = (int) (mCircleRadius[HOURS] 697eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * ((mNumbersRadiusMultiplier[HOURS] + mNumbersRadiusMultiplier[HOURS_INNER]) / 2)); 698eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 699eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTextSize[HOURS] = mCircleRadius[HOURS] * mTextSizeMultiplier[HOURS]; 700eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTextSize[MINUTES] = mCircleRadius[MINUTES] * mTextSizeMultiplier[MINUTES]; 701eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 702eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourMode) { 703eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInnerTextSize = mCircleRadius[HOURS] * mTextSizeMultiplier[HOURS_INNER]; 704eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 705eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 706eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio calculateGridSizesHours(); 707eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio calculateGridSizesMinutes(); 708eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 709eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionRadius[HOURS] = (int) (mCircleRadius[HOURS] * mSelectionRadiusMultiplier); 710eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionRadius[HOURS_INNER] = mSelectionRadius[HOURS]; 711eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionRadius[MINUTES] = (int) (mCircleRadius[MINUTES] * mSelectionRadiusMultiplier); 712eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 713eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmPmCircleRadius = (int) (mCircleRadius[HOURS] * mAmPmCircleRadiusMultiplier); 714eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmText.setTextSize(mAmPmCircleRadius * 3 / 4); 715eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 716eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Line up the vertical center of the AM/PM circles with the bottom of the main circle. 717eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmPmYCenter = mYCenter + mCircleRadius[HOURS]; 718eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 719eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Line up the horizontal edges of the AM/PM circles with the horizontal edges 720eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // of the main circle 721eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mLeftIndicatorXCenter = mXCenter - mCircleRadius[HOURS] + mAmPmCircleRadius; 722eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRightIndicatorXCenter = mXCenter + mCircleRadius[HOURS] - mAmPmCircleRadius; 723eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 724eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 725eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 726eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onDraw(Canvas canvas) { 7275134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette if (!mInputEnabled) { 7285134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), mDisabledAlpha); 7295134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette } else { 7305134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette canvas.save(); 7315134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette } 732eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 733eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio calculateGridSizesHours(); 734eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio calculateGridSizesMinutes(); 735eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 736eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio drawCircleBackground(canvas); 737eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette drawSelector(canvas); 738eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 739eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio drawTextElements(canvas, mTextSize[HOURS], mTypeface, mOuterTextHours, 740eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mTextGridWidths[HOURS], mTextGridHeights[HOURS], mPaint[HOURS], 741eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColor[HOURS], mAlpha[HOURS].getValue()); 742eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 743eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourMode && mInnerTextHours != null) { 744eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio drawTextElements(canvas, mInnerTextSize, mTypeface, mInnerTextHours, 745eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mInnerTextGridWidths, mInnerTextGridHeights, mPaint[HOURS], 746eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColor[HOURS], mAlpha[HOURS].getValue()); 747eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 748eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 749eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mOuterTextMinutes, 750eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mTextGridWidths[MINUTES], mTextGridHeights[MINUTES], mPaint[MINUTES], 751eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mColor[MINUTES], mAlpha[MINUTES].getValue()); 752eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 753eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio drawCenter(canvas); 754eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mIs24HourMode) { 755eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio drawAmPm(canvas); 756eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 757eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 758eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (DEBUG) { 759eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio drawDebug(canvas); 760eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 761eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 762eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.restore(); 763eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 764eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 765eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void drawCircleBackground(Canvas canvas) { 766eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawCircle(mXCenter, mYCenter, mCircleRadius[HOURS], mPaintBackground); 767eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 768eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 769eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void drawCenter(Canvas canvas) { 770eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawCircle(mXCenter, mYCenter, CENTER_RADIUS, mPaintCenter); 771eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 772eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 773eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void drawSelector(Canvas canvas) { 774eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio drawSelector(canvas, mIsOnInnerCircle ? HOURS_INNER : HOURS); 775eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio drawSelector(canvas, MINUTES); 776eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 777eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 778eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void drawAmPm(Canvas canvas) { 779eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final boolean isLayoutRtl = isLayoutRtl(); 780eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 781eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int amColor = mAmPmUnselectedColor; 782eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int amAlpha = ALPHA_OPAQUE; 783eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int pmColor = mAmPmUnselectedColor; 784eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int pmAlpha = ALPHA_OPAQUE; 785eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mAmOrPm == AM) { 786eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio amColor = mAmPmSelectedColor; 787eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio amAlpha = ALPHA_AMPM_SELECTED; 788eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (mAmOrPm == PM) { 789eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio pmColor = mAmPmSelectedColor; 790eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio pmAlpha = ALPHA_AMPM_SELECTED; 791eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 792eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mAmOrPmPressed == AM) { 793eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio amColor = mAmPmSelectedColor; 794eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio amAlpha = ALPHA_AMPM_PRESSED; 795eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (mAmOrPmPressed == PM) { 796eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio pmColor = mAmPmSelectedColor; 797eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio pmAlpha = ALPHA_AMPM_PRESSED; 798eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 799eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 800eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw the two circles 801eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmCircle[AM].setColor(amColor); 802eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mPaintAmPmCircle[AM].setAlpha(getMultipliedAlpha(amColor, amAlpha)); 803eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawCircle(isLayoutRtl ? mRightIndicatorXCenter : mLeftIndicatorXCenter, 804eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmPmYCenter, mAmPmCircleRadius, mPaintAmPmCircle[AM]); 805eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 806eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmCircle[PM].setColor(pmColor); 807eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mPaintAmPmCircle[PM].setAlpha(getMultipliedAlpha(pmColor, pmAlpha)); 808eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawCircle(isLayoutRtl ? mLeftIndicatorXCenter : mRightIndicatorXCenter, 809eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmPmYCenter, mAmPmCircleRadius, mPaintAmPmCircle[PM]); 810eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 811eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw the AM/PM texts on top 812eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPaintAmPmText.setColor(mAmPmTextColor); 813eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float textYCenter = mAmPmYCenter - 814eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio (int) (mPaintAmPmText.descent() + mPaintAmPmText.ascent()) / 2; 815eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 816eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(isLayoutRtl ? mAmPmText[PM] : mAmPmText[AM], mLeftIndicatorXCenter, 817eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textYCenter, mPaintAmPmText); 818eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(isLayoutRtl ? mAmPmText[AM] : mAmPmText[PM], mRightIndicatorXCenter, 819eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textYCenter, mPaintAmPmText); 820eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 821eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 822eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private int getMultipliedAlpha(int argb, int alpha) { 823eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette return (int) (Color.alpha(argb) * (alpha / 255.0) + 0.5); 824eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette } 825eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 826eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void drawSelector(Canvas canvas, int index) { 827eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Calculate the current radius at which to place the selection circle. 828eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mLineLength[index] = (int) (mCircleRadius[index] 829eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * mNumbersRadiusMultiplier[index] * mAnimationRadiusMultiplier[index]); 830eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 831eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio double selectionRadians = Math.toRadians(mSelectionDegrees[index]); 832eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 833eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int pointX = mXCenter + (int) (mLineLength[index] * Math.sin(selectionRadians)); 834eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int pointY = mYCenter - (int) (mLineLength[index] * Math.cos(selectionRadians)); 835eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 836eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette int color; 837eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette int alpha; 838eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette Paint paint; 839eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 840eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw the selection circle 841eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette color = mColorSelector[index % 2][SELECTOR_CIRCLE]; 842eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette alpha = mAlphaSelector[index % 2][SELECTOR_CIRCLE].getValue(); 843eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint = mPaintSelector[index % 2][SELECTOR_CIRCLE]; 844eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint.setColor(color); 845eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint.setAlpha(getMultipliedAlpha(color, alpha)); 846eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette canvas.drawCircle(pointX, pointY, mSelectionRadius[index], paint); 847eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 848eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw the dot if needed 849eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mSelectionDegrees[index] % 30 != 0) { 850eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We're not on a direct tick 851eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette color = mColorSelector[index % 2][SELECTOR_DOT]; 852eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette alpha = mAlphaSelector[index % 2][SELECTOR_DOT].getValue(); 853eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint = mPaintSelector[index % 2][SELECTOR_DOT]; 854eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint.setColor(color); 855eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint.setAlpha(getMultipliedAlpha(color, alpha)); 856eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette canvas.drawCircle(pointX, pointY, (mSelectionRadius[index] * 2 / 7), paint); 857eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 858eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We're not drawing the dot, so shorten the line to only go as far as the edge of the 859eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // selection circle 860eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int lineLength = mLineLength[index] - mSelectionRadius[index]; 861eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio pointX = mXCenter + (int) (lineLength * Math.sin(selectionRadians)); 862eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio pointY = mYCenter - (int) (lineLength * Math.cos(selectionRadians)); 863eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 864eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 865eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw the line 866eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette color = mColorSelector[index % 2][SELECTOR_LINE]; 867eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette alpha = mAlphaSelector[index % 2][SELECTOR_LINE].getValue(); 868eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint = mPaintSelector[index % 2][SELECTOR_LINE]; 869eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint.setColor(color); 870eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint.setAlpha(getMultipliedAlpha(color, alpha)); 871eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette canvas.drawLine(mXCenter, mYCenter, pointX, pointY, paint); 872eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 873eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 874eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void drawDebug(Canvas canvas) { 875eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw outer numbers circle 876eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final float outerRadius = mCircleRadius[HOURS] * mNumbersRadiusMultiplier[HOURS]; 877eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawCircle(mXCenter, mYCenter, outerRadius, mPaintDebug); 878eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 879eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw inner numbers circle 880eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final float innerRadius = mCircleRadius[HOURS] * mNumbersRadiusMultiplier[HOURS_INNER]; 881eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawCircle(mXCenter, mYCenter, innerRadius, mPaintDebug); 882eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 883eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw outer background circle 884eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawCircle(mXCenter, mYCenter, mCircleRadius[HOURS], mPaintDebug); 885eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 886eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw outer rectangle for circles 887eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float left = mXCenter - outerRadius; 888eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float top = mYCenter - outerRadius; 889eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float right = mXCenter + outerRadius; 890eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float bottom = mYCenter + outerRadius; 891eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRectF = new RectF(left, top, right, bottom); 892eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawRect(mRectF, mPaintDebug); 893eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 894eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw outer rectangle for background 895eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio left = mXCenter - mCircleRadius[HOURS]; 896eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio top = mYCenter - mCircleRadius[HOURS]; 897eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio right = mXCenter + mCircleRadius[HOURS]; 898eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio bottom = mYCenter + mCircleRadius[HOURS]; 899eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRectF.set(left, top, right, bottom); 900eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawRect(mRectF, mPaintDebug); 901eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 902eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw outer view rectangle 903eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRectF.set(0, 0, getWidth(), getHeight()); 904eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawRect(mRectF, mPaintDebug); 905eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 906eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Draw selected time 907eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final String selected = String.format("%02d:%02d", getCurrentHour(), getCurrentMinute()); 908eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 909eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 910eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ViewGroup.LayoutParams.WRAP_CONTENT); 911eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio TextView tv = new TextView(getContext()); 912eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio tv.setLayoutParams(lp); 913eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio tv.setText(selected); 914eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio tv.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 915eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Paint paint = tv.getPaint(); 916eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio paint.setColor(DEBUG_TEXT_COLOR); 917eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 918eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int width = tv.getMeasuredWidth(); 919eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 920eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float height = paint.descent() - paint.ascent(); 921eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float x = mXCenter - width / 2; 922eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float y = mYCenter + 1.5f * height; 923eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 924eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(selected.toString(), x, y, paint); 925eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 926eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 927eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void calculateGridSizesHours() { 928eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Calculate the text positions 929eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float numbersRadius = mCircleRadius[HOURS] 930eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * mNumbersRadiusMultiplier[HOURS] * mAnimationRadiusMultiplier[HOURS]; 931eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 932eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Calculate the positions for the 12 numbers in the main circle. 933eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio calculateGridSizes(mPaint[HOURS], numbersRadius, mXCenter, mYCenter, 934eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTextSize[HOURS], mTextGridHeights[HOURS], mTextGridWidths[HOURS]); 935eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 936eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // If we have an inner circle, calculate those positions too. 937eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourMode) { 938eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float innerNumbersRadius = mCircleRadius[HOURS_INNER] 939eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * mNumbersRadiusMultiplier[HOURS_INNER] 940eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * mAnimationRadiusMultiplier[HOURS_INNER]; 941eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 942eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio calculateGridSizes(mPaint[HOURS], innerNumbersRadius, mXCenter, mYCenter, 943eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInnerTextSize, mInnerTextGridHeights, mInnerTextGridWidths); 944eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 945eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 946eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 947eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void calculateGridSizesMinutes() { 948eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Calculate the text positions 949eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float numbersRadius = mCircleRadius[MINUTES] 950eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * mNumbersRadiusMultiplier[MINUTES] * mAnimationRadiusMultiplier[MINUTES]; 951eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 952eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Calculate the positions for the 12 numbers in the main circle. 953eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio calculateGridSizes(mPaint[MINUTES], numbersRadius, mXCenter, mYCenter, 954eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTextSize[MINUTES], mTextGridHeights[MINUTES], mTextGridWidths[MINUTES]); 955eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 956eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 957eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 958eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 959eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Using the trigonometric Unit Circle, calculate the positions that the text will need to be 960eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * drawn at based on the specified circle radius. Place the values in the textGridHeights and 961eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * textGridWidths parameters. 962eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 963eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static void calculateGridSizes(Paint paint, float numbersRadius, float xCenter, 964eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float yCenter, float textSize, float[] textGridHeights, float[] textGridWidths) { 965eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /* 966eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * The numbers need to be drawn in a 7x7 grid, representing the points on the Unit Circle. 967eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 968eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final float offset1 = numbersRadius; 969eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // cos(30) = a / r => r * cos(30) 970eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final float offset2 = numbersRadius * COSINE_30_DEGREES; 971eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // sin(30) = o / r => r * sin(30) 972eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final float offset3 = numbersRadius * SINE_30_DEGREES; 973eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 974eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio paint.setTextSize(textSize); 975eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We'll need yTextBase to be slightly lower to account for the text's baseline. 976eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio yCenter -= (paint.descent() + paint.ascent()) / 2; 977eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 978eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridHeights[0] = yCenter - offset1; 979eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridWidths[0] = xCenter - offset1; 980eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridHeights[1] = yCenter - offset2; 981eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridWidths[1] = xCenter - offset2; 982eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridHeights[2] = yCenter - offset3; 983eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridWidths[2] = xCenter - offset3; 984eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridHeights[3] = yCenter; 985eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridWidths[3] = xCenter; 986eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridHeights[4] = yCenter + offset3; 987eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridWidths[4] = xCenter + offset3; 988eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridHeights[5] = yCenter + offset2; 989eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridWidths[5] = xCenter + offset2; 990eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridHeights[6] = yCenter + offset1; 991eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio textGridWidths[6] = xCenter + offset1; 992eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 993eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 994eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 995eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Draw the 12 text values at the positions specified by the textGrid parameters. 996eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 997eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void drawTextElements(Canvas canvas, float textSize, Typeface typeface, String[] texts, 998eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette float[] textGridWidths, float[] textGridHeights, Paint paint, int color, int alpha) { 999eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio paint.setTextSize(textSize); 1000eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio paint.setTypeface(typeface); 1001eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint.setColor(color); 1002eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette paint.setAlpha(getMultipliedAlpha(color, alpha)); 1003eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[0], textGridWidths[3], textGridHeights[0], paint); 1004eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[1], textGridWidths[4], textGridHeights[1], paint); 1005eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[2], textGridWidths[5], textGridHeights[2], paint); 1006eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[3], textGridWidths[6], textGridHeights[3], paint); 1007eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[4], textGridWidths[5], textGridHeights[4], paint); 1008eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[5], textGridWidths[4], textGridHeights[5], paint); 1009eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[6], textGridWidths[3], textGridHeights[6], paint); 1010eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[7], textGridWidths[2], textGridHeights[5], paint); 1011eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[8], textGridWidths[1], textGridHeights[4], paint); 1012eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[9], textGridWidths[0], textGridHeights[3], paint); 1013eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[10], textGridWidths[1], textGridHeights[2], paint); 1014eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio canvas.drawText(texts[11], textGridWidths[2], textGridHeights[1], paint); 1015eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1016eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1017eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Used for animating the hours by changing their radius 1018eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void setAnimationRadiusMultiplierHours(float animationRadiusMultiplier) { 1019eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAnimationRadiusMultiplier[HOURS] = animationRadiusMultiplier; 1020eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAnimationRadiusMultiplier[HOURS_INNER] = animationRadiusMultiplier; 1021eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1022eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1023eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Used for animating the minutes by changing their radius 1024eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void setAnimationRadiusMultiplierMinutes(float animationRadiusMultiplier) { 1025eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAnimationRadiusMultiplier[MINUTES] = animationRadiusMultiplier; 1026eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1027eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1028eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static ObjectAnimator getRadiusDisappearAnimator(Object target, 1029eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String radiusPropertyName, InvalidateUpdateListener updateListener, 1030eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float midRadiusMultiplier, float endRadiusMultiplier) { 1031eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Keyframe kf0, kf1, kf2; 1032eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float midwayPoint = 0.2f; 1033eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int duration = 500; 1034eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1035eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio kf0 = Keyframe.ofFloat(0f, 1); 1036eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio kf1 = Keyframe.ofFloat(midwayPoint, midRadiusMultiplier); 1037eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio kf2 = Keyframe.ofFloat(1f, endRadiusMultiplier); 1038eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio PropertyValuesHolder radiusDisappear = PropertyValuesHolder.ofKeyframe( 1039eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio radiusPropertyName, kf0, kf1, kf2); 1040eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1041eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder( 1042eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio target, radiusDisappear).setDuration(duration); 1043eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio animator.addUpdateListener(updateListener); 1044eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return animator; 1045eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1046eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1047eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static ObjectAnimator getRadiusReappearAnimator(Object target, 1048eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String radiusPropertyName, InvalidateUpdateListener updateListener, 1049eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float midRadiusMultiplier, float endRadiusMultiplier) { 1050eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Keyframe kf0, kf1, kf2, kf3; 1051eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float midwayPoint = 0.2f; 1052eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int duration = 500; 1053eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1054eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Set up animator for reappearing. 1055eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float delayMultiplier = 0.25f; 1056eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float transitionDurationMultiplier = 1f; 1057eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float totalDurationMultiplier = transitionDurationMultiplier + delayMultiplier; 1058eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int totalDuration = (int) (duration * totalDurationMultiplier); 1059eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float delayPoint = (delayMultiplier * duration) / totalDuration; 1060eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio midwayPoint = 1 - (midwayPoint * (1 - delayPoint)); 1061eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1062eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio kf0 = Keyframe.ofFloat(0f, endRadiusMultiplier); 1063eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio kf1 = Keyframe.ofFloat(delayPoint, endRadiusMultiplier); 1064eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio kf2 = Keyframe.ofFloat(midwayPoint, midRadiusMultiplier); 1065eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio kf3 = Keyframe.ofFloat(1f, 1); 1066eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio PropertyValuesHolder radiusReappear = PropertyValuesHolder.ofKeyframe( 1067eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio radiusPropertyName, kf0, kf1, kf2, kf3); 1068eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1069eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder( 1070eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio target, radiusReappear).setDuration(totalDuration); 1071eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio animator.addUpdateListener(updateListener); 1072eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return animator; 1073eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1074eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1075eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private static ObjectAnimator getFadeOutAnimator(IntHolder target, int startAlpha, int endAlpha, 1076eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio InvalidateUpdateListener updateListener) { 1077eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int duration = 500; 1078eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette ObjectAnimator animator = ObjectAnimator.ofInt(target, "value", startAlpha, endAlpha); 1079eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio animator.setDuration(duration); 1080eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio animator.addUpdateListener(updateListener); 1081eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1082eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return animator; 1083eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1084eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1085eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private static ObjectAnimator getFadeInAnimator(IntHolder target, int startAlpha, int endAlpha, 1086eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio InvalidateUpdateListener updateListener) { 1087eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Keyframe kf0, kf1, kf2; 1088eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int duration = 500; 1089eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1090eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Set up animator for reappearing. 1091eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float delayMultiplier = 0.25f; 1092eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float transitionDurationMultiplier = 1f; 1093eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float totalDurationMultiplier = transitionDurationMultiplier + delayMultiplier; 1094eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int totalDuration = (int) (duration * totalDurationMultiplier); 1095eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio float delayPoint = (delayMultiplier * duration) / totalDuration; 1096eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1097eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio kf0 = Keyframe.ofInt(0f, startAlpha); 1098eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio kf1 = Keyframe.ofInt(delayPoint, startAlpha); 1099eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio kf2 = Keyframe.ofInt(1f, endAlpha); 1100eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette PropertyValuesHolder fadeIn = PropertyValuesHolder.ofKeyframe("value", kf0, kf1, kf2); 1101eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1102eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder( 1103eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio target, fadeIn).setDuration(totalDuration); 1104eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio animator.addUpdateListener(updateListener); 1105eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return animator; 1106eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1107eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1108eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private class InvalidateUpdateListener implements ValueAnimator.AnimatorUpdateListener { 1109eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 1110eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onAnimationUpdate(ValueAnimator animation) { 1111eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio RadialTimePickerView.this.invalidate(); 1112eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1113eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1114eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1115eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void startHoursToMinutesAnimation() { 1116eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mHoursToMinutesAnims.size() == 0) { 1117eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHoursToMinutesAnims.add(getRadiusDisappearAnimator(this, 1118eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio "animationRadiusMultiplierHours", mInvalidateUpdateListener, 1119eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransitionMidRadiusMultiplier, mTransitionEndRadiusMultiplier)); 1120eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mHoursToMinutesAnims.add(getFadeOutAnimator(mAlpha[HOURS], 1121eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener)); 1122eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mHoursToMinutesAnims.add(getFadeOutAnimator(mAlphaSelector[HOURS][SELECTOR_CIRCLE], 1123eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_SELECTOR, ALPHA_TRANSPARENT, mInvalidateUpdateListener)); 1124eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mHoursToMinutesAnims.add(getFadeOutAnimator(mAlphaSelector[HOURS][SELECTOR_DOT], 1125eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener)); 1126eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mHoursToMinutesAnims.add(getFadeOutAnimator(mAlphaSelector[HOURS][SELECTOR_LINE], 1127eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_SELECTOR, ALPHA_TRANSPARENT, mInvalidateUpdateListener)); 1128eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1129eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHoursToMinutesAnims.add(getRadiusReappearAnimator(this, 1130eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio "animationRadiusMultiplierMinutes", mInvalidateUpdateListener, 1131eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransitionMidRadiusMultiplier, mTransitionEndRadiusMultiplier)); 1132eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mHoursToMinutesAnims.add(getFadeInAnimator(mAlpha[MINUTES], 1133eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener)); 1134eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mHoursToMinutesAnims.add(getFadeInAnimator(mAlphaSelector[MINUTES][SELECTOR_CIRCLE], 1135eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_TRANSPARENT, ALPHA_SELECTOR, mInvalidateUpdateListener)); 1136eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mHoursToMinutesAnims.add(getFadeInAnimator(mAlphaSelector[MINUTES][SELECTOR_DOT], 1137eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener)); 1138eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mHoursToMinutesAnims.add(getFadeInAnimator(mAlphaSelector[MINUTES][SELECTOR_LINE], 1139eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_TRANSPARENT, ALPHA_SELECTOR, mInvalidateUpdateListener)); 1140eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1141eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1142eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mTransition != null && mTransition.isRunning()) { 1143eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransition.end(); 1144eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1145eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransition = new AnimatorSet(); 1146eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransition.playTogether(mHoursToMinutesAnims); 1147eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransition.start(); 1148eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1149eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1150eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void startMinutesToHoursAnimation() { 1151eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mMinuteToHoursAnims.size() == 0) { 1152eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMinuteToHoursAnims.add(getRadiusDisappearAnimator(this, 1153eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio "animationRadiusMultiplierMinutes", mInvalidateUpdateListener, 1154eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransitionMidRadiusMultiplier, mTransitionEndRadiusMultiplier)); 1155eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mMinuteToHoursAnims.add(getFadeOutAnimator(mAlpha[MINUTES], 1156eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener)); 1157eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mMinuteToHoursAnims.add(getFadeOutAnimator(mAlphaSelector[MINUTES][SELECTOR_CIRCLE], 1158eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_SELECTOR, ALPHA_TRANSPARENT, mInvalidateUpdateListener)); 1159eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mMinuteToHoursAnims.add(getFadeOutAnimator(mAlphaSelector[MINUTES][SELECTOR_DOT], 1160eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener)); 1161eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mMinuteToHoursAnims.add(getFadeOutAnimator(mAlphaSelector[MINUTES][SELECTOR_LINE], 1162eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_SELECTOR, ALPHA_TRANSPARENT, mInvalidateUpdateListener)); 1163eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1164eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMinuteToHoursAnims.add(getRadiusReappearAnimator(this, 1165eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio "animationRadiusMultiplierHours", mInvalidateUpdateListener, 1166eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransitionMidRadiusMultiplier, mTransitionEndRadiusMultiplier)); 1167eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mMinuteToHoursAnims.add(getFadeInAnimator(mAlpha[HOURS], 1168eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener)); 1169eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mMinuteToHoursAnims.add(getFadeInAnimator(mAlphaSelector[HOURS][SELECTOR_CIRCLE], 1170eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_TRANSPARENT, ALPHA_SELECTOR, mInvalidateUpdateListener)); 1171eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mMinuteToHoursAnims.add(getFadeInAnimator(mAlphaSelector[HOURS][SELECTOR_DOT], 1172eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener)); 1173eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mMinuteToHoursAnims.add(getFadeInAnimator(mAlphaSelector[HOURS][SELECTOR_LINE], 1174eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ALPHA_TRANSPARENT, ALPHA_SELECTOR, mInvalidateUpdateListener)); 1175eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1176eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1177eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mTransition != null && mTransition.isRunning()) { 1178eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransition.end(); 1179eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1180eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransition = new AnimatorSet(); 1181eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransition.playTogether(mMinuteToHoursAnims); 1182eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTransition.start(); 1183eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1184eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1185eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int getDegreesFromXY(float x, float y) { 1186eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final double hypotenuse = Math.sqrt( 1187eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio (y - mYCenter) * (y - mYCenter) + (x - mXCenter) * (x - mXCenter)); 1188eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1189eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Basic check if we're outside the range of the disk 1190eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (hypotenuse > mCircleRadius[HOURS]) { 1191eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return -1; 1192eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1193eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Check 1194eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourMode && mShowHours) { 1195eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (hypotenuse >= mMinHypotenuseForInnerNumber 1196eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio && hypotenuse <= mHalfwayHypotenusePoint) { 1197eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIsOnInnerCircle = true; 1198eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (hypotenuse <= mMaxHypotenuseForOuterNumber 1199eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio && hypotenuse >= mHalfwayHypotenusePoint) { 1200eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIsOnInnerCircle = false; 1201eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1202eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return -1; 1203eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1204eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1205eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int index = (mShowHours) ? HOURS : MINUTES; 1206eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final float length = (mCircleRadius[index] * mNumbersRadiusMultiplier[index]); 1207eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int distanceToNumber = (int) Math.abs(hypotenuse - length); 1208eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int maxAllowedDistance = 1209eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio (int) (mCircleRadius[index] * (1 - mNumbersRadiusMultiplier[index])); 1210eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (distanceToNumber > maxAllowedDistance) { 1211eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return -1; 1212eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1213eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1214eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1215eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final float opposite = Math.abs(y - mYCenter); 1216eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio double degrees = Math.toDegrees(Math.asin(opposite / hypotenuse)); 1217eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1218eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Now we have to translate to the correct quadrant. 1219eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio boolean rightSide = (x > mXCenter); 1220eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio boolean topSide = (y < mYCenter); 1221eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (rightSide && topSide) { 1222eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = 90 - degrees; 1223eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (rightSide && !topSide) { 1224eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = 90 + degrees; 1225eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (!rightSide && !topSide) { 1226eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = 270 - degrees; 1227eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (!rightSide && topSide) { 1228eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = 270 + degrees; 1229eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1230eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return (int) degrees; 1231eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1232eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1233eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int getIsTouchingAmOrPm(float x, float y) { 1234eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final boolean isLayoutRtl = isLayoutRtl(); 1235eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int squaredYDistance = (int) ((y - mAmPmYCenter) * (y - mAmPmYCenter)); 1236eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1237eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int distanceToAmCenter = (int) Math.sqrt( 1238eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio (x - mLeftIndicatorXCenter) * (x - mLeftIndicatorXCenter) + squaredYDistance); 1239eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (distanceToAmCenter <= mAmPmCircleRadius) { 1240eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return (isLayoutRtl ? PM : AM); 1241eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1242eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1243eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int distanceToPmCenter = (int) Math.sqrt( 1244eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio (x - mRightIndicatorXCenter) * (x - mRightIndicatorXCenter) + squaredYDistance); 1245eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (distanceToPmCenter <= mAmPmCircleRadius) { 1246eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return (isLayoutRtl ? AM : PM); 1247eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1248eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1249eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Neither was close enough. 1250eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return -1; 1251eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1252eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1253eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 1254eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean onTouch(View v, MotionEvent event) { 1255eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if(!mInputEnabled) { 1256eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return true; 1257eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1258eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1259eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final float eventX = event.getX(); 1260eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final float eventY = event.getY(); 1261eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1262eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int degrees; 1263eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int snapDegrees; 1264eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio boolean result = false; 1265eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1266eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio switch(event.getAction()) { 1267eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case MotionEvent.ACTION_DOWN: 1268eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case MotionEvent.ACTION_MOVE: 1269eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmOrPmPressed = getIsTouchingAmOrPm(eventX, eventY); 1270eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mAmOrPmPressed != -1) { 1271eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio result = true; 1272eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1273eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = getDegreesFromXY(eventX, eventY); 1274eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (degrees != -1) { 1275eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio snapDegrees = (mShowHours ? 1276eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio snapOnly30s(degrees, 0) : snapPrefer30s(degrees)) % 360; 1277eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mShowHours) { 1278eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionDegrees[HOURS] = snapDegrees; 1279eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionDegrees[HOURS_INNER] = snapDegrees; 1280eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1281eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionDegrees[MINUTES] = snapDegrees; 1282eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1283eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); 1284eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mListener != null) { 1285eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mShowHours) { 1286eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mListener.onValueSelected(HOURS, getCurrentHour(), false); 1287eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1288eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mListener.onValueSelected(MINUTES, getCurrentMinute(), false); 1289eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1290eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1291eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio result = true; 1292eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1293eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1294eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio invalidate(); 1295eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return result; 1296eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1297eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case MotionEvent.ACTION_UP: 1298eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmOrPmPressed = getIsTouchingAmOrPm(eventX, eventY); 1299eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mAmOrPmPressed != -1) { 1300eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mAmOrPm != mAmOrPmPressed) { 1301eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio swapAmPm(); 1302eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1303eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmOrPmPressed = -1; 1304eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mListener != null) { 1305eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mListener.onValueSelected(AMPM, getCurrentHour(), true); 1306eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1307eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio result = true; 1308eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1309eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = getDegreesFromXY(eventX, eventY); 1310eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (degrees != -1) { 1311eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio snapDegrees = (mShowHours ? 1312eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio snapOnly30s(degrees, 0) : snapPrefer30s(degrees)) % 360; 1313eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mShowHours) { 1314eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionDegrees[HOURS] = snapDegrees; 1315eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionDegrees[HOURS_INNER] = snapDegrees; 1316eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1317eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectionDegrees[MINUTES] = snapDegrees; 1318eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1319eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mListener != null) { 1320eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mShowHours) { 1321eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mListener.onValueSelected(HOURS, getCurrentHour(), true); 1322eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1323eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mListener.onValueSelected(MINUTES, getCurrentMinute(), true); 1324eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1325eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1326eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio result = true; 1327eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1328eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1329eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (result) { 1330eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio invalidate(); 1331eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1332eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return result; 1333eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1334eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio default: 1335eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio break; 1336eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1337eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return false; 1338eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1339eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1340eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 1341eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Necessary for accessibility, to ensure we support "scrolling" forward and backward 1342eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * in the circle. 1343eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 1344eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 1345eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 1346eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio super.onInitializeAccessibilityNodeInfo(info); 1347eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); 1348eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); 1349eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1350eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1351eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 1352eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Announce the currently-selected time when launched. 1353eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 1354eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 1355eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 1356eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { 1357eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Clear the event's current text so that only the current time will be spoken. 1358eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio event.getText().clear(); 1359eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Time time = new Time(); 1360eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio time.hour = getCurrentHour(); 1361eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio time.minute = getCurrentMinute(); 1362eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio long millis = time.normalize(true); 1363eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int flags = DateUtils.FORMAT_SHOW_TIME; 1364eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourMode) { 1365eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio flags |= DateUtils.FORMAT_24HOUR; 1366eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1367eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String timeString = DateUtils.formatDateTime(getContext(), millis, flags); 1368eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio event.getText().add(timeString); 1369eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return true; 1370eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1371eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return super.dispatchPopulateAccessibilityEvent(event); 1372eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1373eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1374eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 1375eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * When scroll forward/backward events are received, jump the time to the higher/lower 1376eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * discrete, visible value on the circle. 1377eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 1378eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @SuppressLint("NewApi") 1379eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 1380eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean performAccessibilityAction(int action, Bundle arguments) { 1381eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (super.performAccessibilityAction(action, arguments)) { 1382eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return true; 1383eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1384eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1385eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int changeMultiplier = 0; 1386eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) { 1387eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio changeMultiplier = 1; 1388eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) { 1389eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio changeMultiplier = -1; 1390eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1391eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (changeMultiplier != 0) { 1392eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int value = 0; 1393eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int stepSize = 0; 1394eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mShowHours) { 1395eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio stepSize = DEGREES_FOR_ONE_HOUR; 1396eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio value = getCurrentHour() % 12; 1397eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1398eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio stepSize = DEGREES_FOR_ONE_MINUTE; 1399eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio value = getCurrentMinute(); 1400eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1401eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1402eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int degrees = value * stepSize; 1403eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio degrees = snapOnly30s(degrees, changeMultiplier); 1404eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio value = degrees / stepSize; 1405eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int maxValue = 0; 1406eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int minValue = 0; 1407eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mShowHours) { 1408eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourMode) { 1409eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio maxValue = 23; 1410eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1411eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio maxValue = 12; 1412eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio minValue = 1; 1413eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1414eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1415eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio maxValue = 55; 1416eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1417eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (value > maxValue) { 1418eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // If we scrolled forward past the highest number, wrap around to the lowest. 1419eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio value = minValue; 1420eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (value < minValue) { 1421eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // If we scrolled backward past the lowest number, wrap around to the highest. 1422eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio value = maxValue; 1423eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1424eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mShowHours) { 1425eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setCurrentHour(value); 1426eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mListener != null) { 1427eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mListener.onValueSelected(HOURS, value, false); 1428eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1429eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1430eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setCurrentMinute(value); 1431eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mListener != null) { 1432eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mListener.onValueSelected(MINUTES, value, false); 1433eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1434eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1435eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return true; 1436eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1437eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1438eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return false; 1439eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1440eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1441eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setInputEnabled(boolean inputEnabled) { 1442eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInputEnabled = inputEnabled; 1443eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio invalidate(); 1444eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1445eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 1446eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private static class IntHolder { 1447eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette private int mValue; 1448eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 1449eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette public IntHolder(int value) { 1450eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mValue = value; 1451eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette } 1452eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 1453eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette public void setValue(int value) { 1454eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette mValue = value; 1455eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette } 1456eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette 1457eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette public int getValue() { 1458eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette return mValue; 1459eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette } 1460eb1d3798e37572ca515aad572350f5745adf023dAlan Viverette } 1461eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio} 1462