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