1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.datetimepicker.time; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.graphics.Canvas; 22 import android.graphics.Paint; 23 import android.graphics.Typeface; 24 import android.graphics.Paint.Align; 25 import android.util.Log; 26 import android.view.View; 27 28 import com.android.datetimepicker.R; 29 import com.android.datetimepicker.Utils; 30 31 import java.text.DateFormatSymbols; 32 33 /** 34 * Draw the two smaller AM and PM circles next to where the larger circle will be. 35 */ 36 public class AmPmCirclesView extends View { 37 private static final String TAG = "AmPmCirclesView"; 38 39 // Alpha level for selected circle. 40 private static final int SELECTED_ALPHA = Utils.SELECTED_ALPHA; 41 private static final int SELECTED_ALPHA_THEME_DARK = Utils.SELECTED_ALPHA_THEME_DARK; 42 43 private final Paint mPaint = new Paint(); 44 private int mSelectedAlpha; 45 private int mUnselectedColor; 46 private int mAmPmTextColor; 47 private int mSelectedColor; 48 private float mCircleRadiusMultiplier; 49 private float mAmPmCircleRadiusMultiplier; 50 private String mAmText; 51 private String mPmText; 52 private boolean mIsInitialized; 53 54 private static final int AM = TimePickerDialog.AM; 55 private static final int PM = TimePickerDialog.PM; 56 57 private boolean mDrawValuesReady; 58 private int mAmPmCircleRadius; 59 private int mAmXCenter; 60 private int mPmXCenter; 61 private int mAmPmYCenter; 62 private int mAmOrPm; 63 private int mAmOrPmPressed; 64 AmPmCirclesView(Context context)65 public AmPmCirclesView(Context context) { 66 super(context); 67 mIsInitialized = false; 68 } 69 initialize(Context context, int amOrPm)70 public void initialize(Context context, int amOrPm) { 71 if (mIsInitialized) { 72 Log.e(TAG, "AmPmCirclesView may only be initialized once."); 73 return; 74 } 75 76 Resources res = context.getResources(); 77 mUnselectedColor = res.getColor(android.R.color.white); 78 mSelectedColor = res.getColor(R.color.blue); 79 mAmPmTextColor = res.getColor(R.color.ampm_text_color); 80 mSelectedAlpha = SELECTED_ALPHA; 81 String typefaceFamily = res.getString(R.string.sans_serif); 82 Typeface tf = Typeface.create(typefaceFamily, Typeface.NORMAL); 83 mPaint.setTypeface(tf); 84 mPaint.setAntiAlias(true); 85 mPaint.setTextAlign(Align.CENTER); 86 87 mCircleRadiusMultiplier = 88 Float.parseFloat(res.getString(R.string.circle_radius_multiplier)); 89 mAmPmCircleRadiusMultiplier = 90 Float.parseFloat(res.getString(R.string.ampm_circle_radius_multiplier)); 91 String[] amPmTexts = new DateFormatSymbols().getAmPmStrings(); 92 mAmText = amPmTexts[0]; 93 mPmText = amPmTexts[1]; 94 95 setAmOrPm(amOrPm); 96 mAmOrPmPressed = -1; 97 98 mIsInitialized = true; 99 } 100 setTheme(Context context, boolean themeDark)101 /* package */ void setTheme(Context context, boolean themeDark) { 102 Resources res = context.getResources(); 103 if (themeDark) { 104 mUnselectedColor = res.getColor(R.color.dark_gray); 105 mSelectedColor = res.getColor(R.color.red); 106 mAmPmTextColor = res.getColor(android.R.color.white); 107 mSelectedAlpha = SELECTED_ALPHA_THEME_DARK; 108 } else { 109 mUnselectedColor = res.getColor(android.R.color.white); 110 mSelectedColor = res.getColor(R.color.blue); 111 mAmPmTextColor = res.getColor(R.color.ampm_text_color); 112 mSelectedAlpha = SELECTED_ALPHA; 113 } 114 } 115 setAmOrPm(int amOrPm)116 public void setAmOrPm(int amOrPm) { 117 mAmOrPm = amOrPm; 118 } 119 setAmOrPmPressed(int amOrPmPressed)120 public void setAmOrPmPressed(int amOrPmPressed) { 121 mAmOrPmPressed = amOrPmPressed; 122 } 123 124 /** 125 * Calculate whether the coordinates are touching the AM or PM circle. 126 */ getIsTouchingAmOrPm(float xCoord, float yCoord)127 public int getIsTouchingAmOrPm(float xCoord, float yCoord) { 128 if (!mDrawValuesReady) { 129 return -1; 130 } 131 132 int squaredYDistance = (int) ((yCoord - mAmPmYCenter)*(yCoord - mAmPmYCenter)); 133 134 int distanceToAmCenter = 135 (int) Math.sqrt((xCoord - mAmXCenter)*(xCoord - mAmXCenter) + squaredYDistance); 136 if (distanceToAmCenter <= mAmPmCircleRadius) { 137 return AM; 138 } 139 140 int distanceToPmCenter = 141 (int) Math.sqrt((xCoord - mPmXCenter)*(xCoord - mPmXCenter) + squaredYDistance); 142 if (distanceToPmCenter <= mAmPmCircleRadius) { 143 return PM; 144 } 145 146 // Neither was close enough. 147 return -1; 148 } 149 150 @Override onDraw(Canvas canvas)151 public void onDraw(Canvas canvas) { 152 int viewWidth = getWidth(); 153 if (viewWidth == 0 || !mIsInitialized) { 154 return; 155 } 156 157 if (!mDrawValuesReady) { 158 int layoutXCenter = getWidth() / 2; 159 int layoutYCenter = getHeight() / 2; 160 int circleRadius = 161 (int) (Math.min(layoutXCenter, layoutYCenter) * mCircleRadiusMultiplier); 162 mAmPmCircleRadius = (int) (circleRadius * mAmPmCircleRadiusMultiplier); 163 int textSize = mAmPmCircleRadius * 3 / 4; 164 mPaint.setTextSize(textSize); 165 166 // Line up the vertical center of the AM/PM circles with the bottom of the main circle. 167 mAmPmYCenter = layoutYCenter - mAmPmCircleRadius / 2 + circleRadius; 168 // Line up the horizontal edges of the AM/PM circles with the horizontal edges 169 // of the main circle. 170 mAmXCenter = layoutXCenter - circleRadius + mAmPmCircleRadius; 171 mPmXCenter = layoutXCenter + circleRadius - mAmPmCircleRadius; 172 173 mDrawValuesReady = true; 174 } 175 176 // We'll need to draw either a lighter blue (for selection), a darker blue (for touching) 177 // or white (for not selected). 178 int amColor = mUnselectedColor; 179 int amAlpha = 255; 180 int pmColor = mUnselectedColor; 181 int pmAlpha = 255; 182 if (mAmOrPm == AM) { 183 amColor = mSelectedColor; 184 amAlpha = mSelectedAlpha; 185 } else if (mAmOrPm == PM) { 186 pmColor = mSelectedColor; 187 pmAlpha = mSelectedAlpha; 188 } 189 if (mAmOrPmPressed == AM) { 190 amColor = mSelectedColor; 191 amAlpha = mSelectedAlpha; 192 } else if (mAmOrPmPressed == PM) { 193 pmColor = mSelectedColor; 194 pmAlpha = mSelectedAlpha; 195 } 196 197 // Draw the two circles. 198 mPaint.setColor(amColor); 199 mPaint.setAlpha(amAlpha); 200 canvas.drawCircle(mAmXCenter, mAmPmYCenter, mAmPmCircleRadius, mPaint); 201 mPaint.setColor(pmColor); 202 mPaint.setAlpha(pmAlpha); 203 canvas.drawCircle(mPmXCenter, mAmPmYCenter, mAmPmCircleRadius, mPaint); 204 205 // Draw the AM/PM texts on top. 206 mPaint.setColor(mAmPmTextColor); 207 int textYCenter = mAmPmYCenter - (int) (mPaint.descent() + mPaint.ascent()) / 2; 208 canvas.drawText(mAmText, mAmXCenter, textYCenter, mPaint); 209 canvas.drawText(mPmText, mPmXCenter, textYCenter, mPaint); 210 } 211 } 212