Merge "Update AM/PM selectors for clock face TimePicker" into lmp-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0db6536190
@@ -22,9 +22,7 @@ import android.animation.Keyframe;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
@@ -47,7 +45,6 @@ import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
@@ -69,7 +66,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
private static final int HOURS = 0;
|
||||
private static final int MINUTES = 1;
|
||||
private static final int HOURS_INNER = 2;
|
||||
private static final int AMPM = 3;
|
||||
|
||||
private static final int SELECTOR_CIRCLE = 0;
|
||||
private static final int SELECTOR_DOT = 1;
|
||||
@@ -87,12 +83,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
// Alpha level of color for selector.
|
||||
private static final int ALPHA_SELECTOR = 60; // was 51
|
||||
|
||||
// Alpha level of color for selected circle.
|
||||
private static final int ALPHA_AMPM_SELECTED = ALPHA_SELECTOR;
|
||||
|
||||
// Alpha level of color for pressed circle.
|
||||
private static final int ALPHA_AMPM_PRESSED = 255; // was 175
|
||||
|
||||
private static final float COSINE_30_DEGREES = ((float) Math.sqrt(3)) * 0.5f;
|
||||
private static final float SINE_30_DEGREES = 0.5f;
|
||||
|
||||
@@ -105,8 +95,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
|
||||
private static final int CENTER_RADIUS = 2;
|
||||
|
||||
private static final int[] STATE_SET_SELECTED = new int[] {R.attr.state_selected};
|
||||
|
||||
private static int[] sSnapPrefer30sMap = new int[361];
|
||||
|
||||
private final String[] mHours12Texts = new String[12];
|
||||
@@ -114,8 +102,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
private final String[] mInnerHours24Texts = new String[12];
|
||||
private final String[] mMinutesTexts = new String[12];
|
||||
|
||||
private final String[] mAmPmText = new String[2];
|
||||
|
||||
private final Paint[] mPaint = new Paint[2];
|
||||
private final int[] mColor = new int[2];
|
||||
private final IntHolder[] mAlpha = new IntHolder[2];
|
||||
@@ -126,11 +112,7 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
private final int[][] mColorSelector = new int[2][3];
|
||||
private final IntHolder[][] mAlphaSelector = new IntHolder[2][3];
|
||||
|
||||
private final Paint mPaintAmPmText = new Paint();
|
||||
private final Paint[] mPaintAmPmCircle = new Paint[2];
|
||||
|
||||
private final Paint mPaintBackground = new Paint();
|
||||
private final Paint mPaintDisabled = new Paint();
|
||||
private final Paint mPaintDebug = new Paint();
|
||||
|
||||
private Typeface mTypeface;
|
||||
@@ -184,21 +166,7 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
private float mSelectionRadiusMultiplier;
|
||||
private int[] mSelectionDegrees = new int[3];
|
||||
|
||||
private int mAmPmCircleRadius;
|
||||
private float mAmPmYCenter;
|
||||
|
||||
private float mAmPmCircleRadiusMultiplier;
|
||||
private int mAmPmTextColor;
|
||||
|
||||
private float mLeftIndicatorXCenter;
|
||||
private float mRightIndicatorXCenter;
|
||||
|
||||
private int mAmPmUnselectedColor;
|
||||
private int mAmPmSelectedColor;
|
||||
|
||||
private int mAmOrPm;
|
||||
private int mAmOrPmPressed;
|
||||
|
||||
private int mDisabledAlpha;
|
||||
|
||||
private RectF mRectF = new RectF();
|
||||
@@ -331,27 +299,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.TimePicker,
|
||||
defStyle, 0);
|
||||
|
||||
ColorStateList amPmBackgroundColor = a.getColorStateList(
|
||||
R.styleable.TimePicker_amPmBackgroundColor);
|
||||
if (amPmBackgroundColor == null) {
|
||||
amPmBackgroundColor = res.getColorStateList(
|
||||
R.color.timepicker_default_ampm_unselected_background_color_material);
|
||||
}
|
||||
|
||||
// Obtain the backup selected color. If the background color state
|
||||
// list doesn't have a state for selected, we'll use this color.
|
||||
final int amPmSelectedColor = a.getColor(R.styleable.TimePicker_amPmSelectedBackgroundColor,
|
||||
res.getColor(R.color.timepicker_default_ampm_selected_background_color_material));
|
||||
amPmBackgroundColor = ColorStateList.addFirstIfMissing(
|
||||
amPmBackgroundColor, R.attr.state_selected, amPmSelectedColor);
|
||||
|
||||
mAmPmSelectedColor = amPmBackgroundColor.getColorForState(
|
||||
STATE_SET_SELECTED, amPmSelectedColor);
|
||||
mAmPmUnselectedColor = amPmBackgroundColor.getDefaultColor();
|
||||
|
||||
mAmPmTextColor = a.getColor(R.styleable.TimePicker_amPmTextColor,
|
||||
res.getColor(R.color.timepicker_default_text_color_material));
|
||||
|
||||
mTypeface = Typeface.create("sans-serif", Typeface.NORMAL);
|
||||
|
||||
// Initialize all alpha values to opaque.
|
||||
@@ -419,16 +366,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
R.styleable.TimePicker_numbersSelectorColor,
|
||||
R.color.timepicker_default_selector_color_material);
|
||||
|
||||
mPaintAmPmText.setColor(mAmPmTextColor);
|
||||
mPaintAmPmText.setTypeface(mTypeface);
|
||||
mPaintAmPmText.setAntiAlias(true);
|
||||
mPaintAmPmText.setTextAlign(Paint.Align.CENTER);
|
||||
|
||||
mPaintAmPmCircle[AM] = new Paint();
|
||||
mPaintAmPmCircle[AM].setAntiAlias(true);
|
||||
mPaintAmPmCircle[PM] = new Paint();
|
||||
mPaintAmPmCircle[PM].setAntiAlias(true);
|
||||
|
||||
mPaintBackground.setColor(a.getColor(R.styleable.TimePicker_numbersBackgroundColor,
|
||||
res.getColor(R.color.timepicker_default_numbers_background_color_material)));
|
||||
mPaintBackground.setAntiAlias(true);
|
||||
@@ -444,7 +381,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
mShowHours = true;
|
||||
mIs24HourMode = false;
|
||||
mAmOrPm = AM;
|
||||
mAmOrPmPressed = -1;
|
||||
|
||||
initHoursAndMinutesText();
|
||||
initData();
|
||||
@@ -530,13 +466,7 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
|
||||
// 0 is 12 AM (midnight) and 12 is 12 PM (noon).
|
||||
mAmOrPm = (hour == 0 || (hour % 24) < 12) ? AM : PM;
|
||||
|
||||
if (mIs24HourMode) {
|
||||
// Inner circle is 1 through 12.
|
||||
mIsOnInnerCircle = hour >= 1 && hour <= 12;
|
||||
} else {
|
||||
mIsOnInnerCircle = false;
|
||||
}
|
||||
mIsOnInnerCircle = mIs24HourMode && hour >= 1 && hour <= 12;
|
||||
|
||||
initData();
|
||||
updateLayoutData();
|
||||
@@ -586,11 +516,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
return mAmOrPm;
|
||||
}
|
||||
|
||||
public void swapAmPm() {
|
||||
mAmOrPm = (mAmOrPm == AM) ? PM : AM;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void showHours(boolean animate) {
|
||||
if (mShowHours) return;
|
||||
mShowHours = true;
|
||||
@@ -621,10 +546,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
mInnerHours24Texts[i] = String.format("%d", HOURS_NUMBERS[i]);
|
||||
mMinutesTexts[i] = String.format("%02d", MINUTES_NUMBERS[i]);
|
||||
}
|
||||
|
||||
String[] amPmStrings = TimePickerClockDelegate.getAmPmStrings(mContext);
|
||||
mAmPmText[AM] = amPmStrings[0];
|
||||
mAmPmText[PM] = amPmStrings[1];
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
@@ -674,9 +595,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
mAnimationRadiusMultiplier[HOURS_INNER] = 1;
|
||||
mAnimationRadiusMultiplier[MINUTES] = 1;
|
||||
|
||||
mAmPmCircleRadiusMultiplier = Float.parseFloat(
|
||||
res.getString(R.string.timepicker_ampm_circle_radius_multiplier));
|
||||
|
||||
mAlpha[HOURS].setValue(mShowHours ? ALPHA_OPAQUE : ALPHA_TRANSPARENT);
|
||||
mAlpha[MINUTES].setValue(mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE);
|
||||
|
||||
@@ -710,14 +628,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
mCircleRadius[HOURS_INNER] = min * mCircleRadiusMultiplier[HOURS];
|
||||
mCircleRadius[MINUTES] = min * mCircleRadiusMultiplier[MINUTES];
|
||||
|
||||
if (!mIs24HourMode) {
|
||||
// We'll need to draw the AM/PM circles, so the main circle will need to have
|
||||
// a slightly higher center. To keep the entire view centered vertically, we'll
|
||||
// have to push it up by half the radius of the AM/PM circles.
|
||||
int amPmCircleRadius = (int) (mCircleRadius[HOURS] * mAmPmCircleRadiusMultiplier);
|
||||
mYCenter -= amPmCircleRadius / 2;
|
||||
}
|
||||
|
||||
mMinHypotenuseForInnerNumber = (int) (mCircleRadius[HOURS]
|
||||
* mNumbersRadiusMultiplier[HOURS_INNER]) - mSelectionRadius[HOURS];
|
||||
mMaxHypotenuseForOuterNumber = (int) (mCircleRadius[HOURS]
|
||||
@@ -738,17 +648,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
mSelectionRadius[HOURS] = (int) (mCircleRadius[HOURS] * mSelectionRadiusMultiplier);
|
||||
mSelectionRadius[HOURS_INNER] = mSelectionRadius[HOURS];
|
||||
mSelectionRadius[MINUTES] = (int) (mCircleRadius[MINUTES] * mSelectionRadiusMultiplier);
|
||||
|
||||
mAmPmCircleRadius = (int) (mCircleRadius[HOURS] * mAmPmCircleRadiusMultiplier);
|
||||
mPaintAmPmText.setTextSize(mAmPmCircleRadius * 3 / 4);
|
||||
|
||||
// Line up the vertical center of the AM/PM circles with the bottom of the main circle.
|
||||
mAmPmYCenter = mYCenter + mCircleRadius[HOURS];
|
||||
|
||||
// Line up the horizontal edges of the AM/PM circles with the horizontal edges
|
||||
// of the main circle
|
||||
mLeftIndicatorXCenter = mXCenter - mCircleRadius[HOURS] + mAmPmCircleRadius;
|
||||
mRightIndicatorXCenter = mXCenter + mCircleRadius[HOURS] - mAmPmCircleRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -780,9 +679,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
mColor[MINUTES], mAlpha[MINUTES].getValue());
|
||||
|
||||
drawCenter(canvas);
|
||||
if (!mIs24HourMode) {
|
||||
drawAmPm(canvas);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
drawDebug(canvas);
|
||||
@@ -804,50 +700,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
drawSelector(canvas, MINUTES);
|
||||
}
|
||||
|
||||
private void drawAmPm(Canvas canvas) {
|
||||
final boolean isLayoutRtl = isLayoutRtl();
|
||||
|
||||
int amColor = mAmPmUnselectedColor;
|
||||
int amAlpha = ALPHA_OPAQUE;
|
||||
int pmColor = mAmPmUnselectedColor;
|
||||
int pmAlpha = ALPHA_OPAQUE;
|
||||
if (mAmOrPm == AM) {
|
||||
amColor = mAmPmSelectedColor;
|
||||
amAlpha = ALPHA_AMPM_SELECTED;
|
||||
} else if (mAmOrPm == PM) {
|
||||
pmColor = mAmPmSelectedColor;
|
||||
pmAlpha = ALPHA_AMPM_SELECTED;
|
||||
}
|
||||
if (mAmOrPmPressed == AM) {
|
||||
amColor = mAmPmSelectedColor;
|
||||
amAlpha = ALPHA_AMPM_PRESSED;
|
||||
} else if (mAmOrPmPressed == PM) {
|
||||
pmColor = mAmPmSelectedColor;
|
||||
pmAlpha = ALPHA_AMPM_PRESSED;
|
||||
}
|
||||
|
||||
// Draw the two circles
|
||||
mPaintAmPmCircle[AM].setColor(amColor);
|
||||
mPaintAmPmCircle[AM].setAlpha(getMultipliedAlpha(amColor, amAlpha));
|
||||
canvas.drawCircle(isLayoutRtl ? mRightIndicatorXCenter : mLeftIndicatorXCenter,
|
||||
mAmPmYCenter, mAmPmCircleRadius, mPaintAmPmCircle[AM]);
|
||||
|
||||
mPaintAmPmCircle[PM].setColor(pmColor);
|
||||
mPaintAmPmCircle[PM].setAlpha(getMultipliedAlpha(pmColor, pmAlpha));
|
||||
canvas.drawCircle(isLayoutRtl ? mLeftIndicatorXCenter : mRightIndicatorXCenter,
|
||||
mAmPmYCenter, mAmPmCircleRadius, mPaintAmPmCircle[PM]);
|
||||
|
||||
// Draw the AM/PM texts on top
|
||||
mPaintAmPmText.setColor(mAmPmTextColor);
|
||||
float textYCenter = mAmPmYCenter -
|
||||
(int) (mPaintAmPmText.descent() + mPaintAmPmText.ascent()) / 2;
|
||||
|
||||
canvas.drawText(isLayoutRtl ? mAmPmText[PM] : mAmPmText[AM], mLeftIndicatorXCenter,
|
||||
textYCenter, mPaintAmPmText);
|
||||
canvas.drawText(isLayoutRtl ? mAmPmText[AM] : mAmPmText[PM], mRightIndicatorXCenter,
|
||||
textYCenter, mPaintAmPmText);
|
||||
}
|
||||
|
||||
private int getMultipliedAlpha(int argb, int alpha) {
|
||||
return (int) (Color.alpha(argb) * (alpha / 255.0) + 0.5);
|
||||
}
|
||||
@@ -950,7 +802,7 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
float x = mXCenter - width / 2;
|
||||
float y = mYCenter + 1.5f * height;
|
||||
|
||||
canvas.drawText(selected.toString(), x, y, paint);
|
||||
canvas.drawText(selected, x, y, paint);
|
||||
}
|
||||
|
||||
private void calculateGridSizesHours() {
|
||||
@@ -1259,26 +1111,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
return (int) degrees;
|
||||
}
|
||||
|
||||
private int getIsTouchingAmOrPm(float x, float y) {
|
||||
final boolean isLayoutRtl = isLayoutRtl();
|
||||
int squaredYDistance = (int) ((y - mAmPmYCenter) * (y - mAmPmYCenter));
|
||||
|
||||
int distanceToAmCenter = (int) Math.sqrt(
|
||||
(x - mLeftIndicatorXCenter) * (x - mLeftIndicatorXCenter) + squaredYDistance);
|
||||
if (distanceToAmCenter <= mAmPmCircleRadius) {
|
||||
return (isLayoutRtl ? PM : AM);
|
||||
}
|
||||
|
||||
int distanceToPmCenter = (int) Math.sqrt(
|
||||
(x - mRightIndicatorXCenter) * (x - mRightIndicatorXCenter) + squaredYDistance);
|
||||
if (distanceToPmCenter <= mAmPmCircleRadius) {
|
||||
return (isLayoutRtl ? AM : PM);
|
||||
}
|
||||
|
||||
// Neither was close enough.
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if(!mInputEnabled) {
|
||||
@@ -1295,75 +1127,53 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
switch(event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
mAmOrPmPressed = getIsTouchingAmOrPm(eventX, eventY);
|
||||
if (mAmOrPmPressed != -1) {
|
||||
result = true;
|
||||
} else {
|
||||
degrees = getDegreesFromXY(eventX, eventY);
|
||||
if (degrees != -1) {
|
||||
snapDegrees = (mShowHours ?
|
||||
snapOnly30s(degrees, 0) : snapPrefer30s(degrees)) % 360;
|
||||
if (mShowHours) {
|
||||
mSelectionDegrees[HOURS] = snapDegrees;
|
||||
mSelectionDegrees[HOURS_INNER] = snapDegrees;
|
||||
} else {
|
||||
mSelectionDegrees[MINUTES] = snapDegrees;
|
||||
}
|
||||
performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
|
||||
if (mListener != null) {
|
||||
if (mShowHours) {
|
||||
mListener.onValueSelected(HOURS, getCurrentHour(), false);
|
||||
} else {
|
||||
mListener.onValueSelected(MINUTES, getCurrentMinute(), false);
|
||||
}
|
||||
}
|
||||
result = true;
|
||||
degrees = getDegreesFromXY(eventX, eventY);
|
||||
if (degrees != -1) {
|
||||
snapDegrees = (mShowHours ?
|
||||
snapOnly30s(degrees, 0) : snapPrefer30s(degrees)) % 360;
|
||||
if (mShowHours) {
|
||||
mSelectionDegrees[HOURS] = snapDegrees;
|
||||
mSelectionDegrees[HOURS_INNER] = snapDegrees;
|
||||
} else {
|
||||
mSelectionDegrees[MINUTES] = snapDegrees;
|
||||
}
|
||||
}
|
||||
invalidate();
|
||||
return result;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
mAmOrPmPressed = getIsTouchingAmOrPm(eventX, eventY);
|
||||
if (mAmOrPmPressed != -1) {
|
||||
if (mAmOrPm != mAmOrPmPressed) {
|
||||
swapAmPm();
|
||||
}
|
||||
mAmOrPmPressed = -1;
|
||||
performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
|
||||
if (mListener != null) {
|
||||
mListener.onValueSelected(AMPM, getCurrentHour(), true);
|
||||
if (mShowHours) {
|
||||
mListener.onValueSelected(HOURS, getCurrentHour(), false);
|
||||
} else {
|
||||
mListener.onValueSelected(MINUTES, getCurrentMinute(), false);
|
||||
}
|
||||
}
|
||||
result = true;
|
||||
} else {
|
||||
degrees = getDegreesFromXY(eventX, eventY);
|
||||
if (degrees != -1) {
|
||||
snapDegrees = (mShowHours ?
|
||||
snapOnly30s(degrees, 0) : snapPrefer30s(degrees)) % 360;
|
||||
if (mShowHours) {
|
||||
mSelectionDegrees[HOURS] = snapDegrees;
|
||||
mSelectionDegrees[HOURS_INNER] = snapDegrees;
|
||||
} else {
|
||||
mSelectionDegrees[MINUTES] = snapDegrees;
|
||||
}
|
||||
if (mListener != null) {
|
||||
if (mShowHours) {
|
||||
mListener.onValueSelected(HOURS, getCurrentHour(), true);
|
||||
} else {
|
||||
mListener.onValueSelected(MINUTES, getCurrentMinute(), true);
|
||||
}
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
if (result) {
|
||||
invalidate();
|
||||
}
|
||||
return result;
|
||||
break;
|
||||
|
||||
default:
|
||||
case MotionEvent.ACTION_UP:
|
||||
degrees = getDegreesFromXY(eventX, eventY);
|
||||
if (degrees != -1) {
|
||||
snapDegrees = (mShowHours ?
|
||||
snapOnly30s(degrees, 0) : snapPrefer30s(degrees)) % 360;
|
||||
if (mShowHours) {
|
||||
mSelectionDegrees[HOURS] = snapDegrees;
|
||||
mSelectionDegrees[HOURS_INNER] = snapDegrees;
|
||||
} else {
|
||||
mSelectionDegrees[MINUTES] = snapDegrees;
|
||||
}
|
||||
if (mListener != null) {
|
||||
if (mShowHours) {
|
||||
mListener.onValueSelected(HOURS, getCurrentHour(), true);
|
||||
} else {
|
||||
mListener.onValueSelected(MINUTES, getCurrentMinute(), true);
|
||||
}
|
||||
}
|
||||
invalidate();
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1373,8 +1183,8 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
|
||||
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
|
||||
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1404,7 +1214,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
* When scroll forward/backward events are received, jump the time to the higher/lower
|
||||
* discrete, visible value on the circle.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public boolean performAccessibilityAction(int action, Bundle arguments) {
|
||||
if (super.performAccessibilityAction(action, arguments)) {
|
||||
@@ -1418,8 +1227,8 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
changeMultiplier = -1;
|
||||
}
|
||||
if (changeMultiplier != 0) {
|
||||
int value = 0;
|
||||
int stepSize = 0;
|
||||
int value;
|
||||
final int stepSize;
|
||||
if (mShowHours) {
|
||||
stepSize = DEGREES_FOR_ONE_HOUR;
|
||||
value = getCurrentHour() % 12;
|
||||
@@ -1431,7 +1240,7 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
|
||||
int degrees = value * stepSize;
|
||||
degrees = snapOnly30s(degrees, changeMultiplier);
|
||||
value = degrees / stepSize;
|
||||
int maxValue = 0;
|
||||
final int maxValue;
|
||||
int minValue = 0;
|
||||
if (mShowHours) {
|
||||
if (mIs24HourMode) {
|
||||
|
||||
@@ -43,7 +43,7 @@ import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
|
||||
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
|
||||
|
||||
/**
|
||||
* A delegate implementing the basic TimePicker
|
||||
* A delegate implementing the basic spinner-based TimePicker.
|
||||
*/
|
||||
class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
|
||||
private static final boolean DEFAULT_ENABLED_STATE = true;
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.text.format.DateFormat;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
@@ -44,7 +45,7 @@ import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* A view for selecting the time of day, in either 24 hour or AM/PM mode.
|
||||
* A delegate implementing the radial clock-based TimePicker.
|
||||
*/
|
||||
class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate implements
|
||||
RadialTimePickerView.OnValueSelectedListener {
|
||||
@@ -61,23 +62,27 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
// Also NOT a real index, just used for keyboard mode.
|
||||
private static final int ENABLE_PICKER_INDEX = 3;
|
||||
|
||||
private static final int AM = 0;
|
||||
private static final int PM = 1;
|
||||
static final int AM = 0;
|
||||
static final int PM = 1;
|
||||
|
||||
private static final boolean DEFAULT_ENABLED_STATE = true;
|
||||
private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
|
||||
|
||||
private static final int HOURS_IN_HALF_DAY = 12;
|
||||
|
||||
private View mHeaderView;
|
||||
private TextView mHourView;
|
||||
private TextView mMinuteView;
|
||||
private TextView mAmPmTextView;
|
||||
private RadialTimePickerView mRadialTimePickerView;
|
||||
private TextView mSeparatorView;
|
||||
private final View mHeaderView;
|
||||
private final TextView mHourView;
|
||||
private final TextView mMinuteView;
|
||||
private final View mAmPmLayout;
|
||||
private final CheckedTextView mAmLabel;
|
||||
private final CheckedTextView mPmLabel;
|
||||
private final RadialTimePickerView mRadialTimePickerView;
|
||||
private final TextView mSeparatorView;
|
||||
|
||||
private String mAmText;
|
||||
private String mPmText;
|
||||
private final String mAmText;
|
||||
private final String mPmText;
|
||||
|
||||
private final float mDisabledAlpha;
|
||||
|
||||
private boolean mAllowAutoAdvance;
|
||||
private int mInitialHourOfDay;
|
||||
@@ -124,15 +129,18 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
|
||||
final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout,
|
||||
R.layout.time_picker_holo);
|
||||
final View mainView = inflater.inflate(layoutResourceId, null);
|
||||
mDelegator.addView(mainView);
|
||||
final View mainView = inflater.inflate(layoutResourceId, delegator);
|
||||
|
||||
mHourView = (TextView) mainView.findViewById(R.id.hours);
|
||||
mSeparatorView = (TextView) mainView.findViewById(R.id.separator);
|
||||
mMinuteView = (TextView) mainView.findViewById(R.id.minutes);
|
||||
mAmPmTextView = (TextView) mainView.findViewById(R.id.ampm_label);
|
||||
mHeaderView = mainView.findViewById(R.id.time_header);
|
||||
mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
|
||||
|
||||
// Set up hour/minute labels.
|
||||
mHourView = (TextView) mHeaderView.findViewById(R.id.hours);
|
||||
mHourView.setOnClickListener(mClickListener);
|
||||
mSeparatorView = (TextView) mHeaderView.findViewById(R.id.separator);
|
||||
mMinuteView = (TextView) mHeaderView.findViewById(R.id.minutes);
|
||||
mMinuteView.setOnClickListener(mClickListener);
|
||||
|
||||
// Set up text appearances from style.
|
||||
final int headerTimeTextAppearance = a.getResourceId(
|
||||
R.styleable.TimePicker_headerTimeTextAppearance, 0);
|
||||
if (headerTimeTextAppearance != 0) {
|
||||
@@ -141,6 +149,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
mMinuteView.setTextAppearance(context, headerTimeTextAppearance);
|
||||
}
|
||||
|
||||
// TODO: This can be removed once we support themed color state lists.
|
||||
final int headerSelectedTextColor = a.getColor(
|
||||
R.styleable.TimePicker_headerSelectedTextColor,
|
||||
res.getColor(R.color.timepicker_default_selector_color_material));
|
||||
@@ -149,17 +158,29 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
mMinuteView.setTextColor(ColorStateList.addFirstIfMissing(mMinuteView.getTextColors(),
|
||||
R.attr.state_selected, headerSelectedTextColor));
|
||||
|
||||
// Set up AM/PM labels.
|
||||
mAmPmLayout = mHeaderView.findViewById(R.id.ampm_layout);
|
||||
mAmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.am_label);
|
||||
mAmLabel.setText(amPmStrings[0]);
|
||||
mAmLabel.setOnClickListener(mClickListener);
|
||||
mPmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.pm_label);
|
||||
mPmLabel.setText(amPmStrings[1]);
|
||||
mPmLabel.setOnClickListener(mClickListener);
|
||||
|
||||
final int headerAmPmTextAppearance = a.getResourceId(
|
||||
R.styleable.TimePicker_headerAmPmTextAppearance, 0);
|
||||
if (headerAmPmTextAppearance != 0) {
|
||||
mAmPmTextView.setTextAppearance(context, headerAmPmTextAppearance);
|
||||
mAmLabel.setTextAppearance(context, headerAmPmTextAppearance);
|
||||
mPmLabel.setTextAppearance(context, headerAmPmTextAppearance);
|
||||
}
|
||||
|
||||
mHeaderView = mainView.findViewById(R.id.time_header);
|
||||
mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
|
||||
|
||||
a.recycle();
|
||||
|
||||
// Pull disabled alpha from theme.
|
||||
final TypedValue outValue = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
|
||||
mDisabledAlpha = outValue.getFloat();
|
||||
|
||||
mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById(
|
||||
R.id.radial_picker);
|
||||
|
||||
@@ -195,21 +216,6 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
mHeaderView.setFocusable(true);
|
||||
|
||||
mRadialTimePickerView.setOnValueSelectedListener(this);
|
||||
|
||||
mHourView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setCurrentItemShowing(HOUR_INDEX, true, true);
|
||||
tryVibrate();
|
||||
}
|
||||
});
|
||||
mMinuteView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setCurrentItemShowing(MINUTE_INDEX, true, true);
|
||||
tryVibrate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateUI(int index) {
|
||||
@@ -250,46 +256,31 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
|
||||
private void updateHeaderAmPm() {
|
||||
if (mIs24HourView) {
|
||||
mAmPmTextView.setVisibility(View.GONE);
|
||||
mAmPmLayout.setVisibility(View.GONE);
|
||||
} else {
|
||||
mAmPmTextView.setVisibility(View.VISIBLE);
|
||||
final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
|
||||
"hm");
|
||||
|
||||
final String bestDateTimePattern = DateFormat.getBestDateTimePattern(
|
||||
mCurrentLocale, "hm");
|
||||
boolean amPmOnLeft = bestDateTimePattern.startsWith("a");
|
||||
if (TextUtils.getLayoutDirectionFromLocale(mCurrentLocale) ==
|
||||
View.LAYOUT_DIRECTION_RTL) {
|
||||
amPmOnLeft = !amPmOnLeft;
|
||||
}
|
||||
|
||||
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
|
||||
mAmPmTextView.getLayoutParams();
|
||||
final ViewGroup.MarginLayoutParams params =
|
||||
(ViewGroup.MarginLayoutParams) mAmPmLayout.getLayoutParams();
|
||||
|
||||
if (amPmOnLeft) {
|
||||
layoutParams.rightMargin = computeMaxWidthOfNumbers(12 /* for hours */);
|
||||
layoutParams.removeRule(RelativeLayout.RIGHT_OF);
|
||||
layoutParams.addRule(RelativeLayout.LEFT_OF, R.id.separator);
|
||||
params.leftMargin = 0;
|
||||
params.rightMargin = computeMaxWidthOfNumbers(12 /* for hours */);
|
||||
} else {
|
||||
layoutParams.leftMargin = computeMaxWidthOfNumbers(60 /* for minutes */);
|
||||
layoutParams.removeRule(RelativeLayout.LEFT_OF);
|
||||
layoutParams.addRule(RelativeLayout.RIGHT_OF, R.id.separator);
|
||||
params.leftMargin = computeMaxWidthOfNumbers(60 /* for minutes */);
|
||||
params.rightMargin = 0;
|
||||
}
|
||||
|
||||
updateAmPmDisplay(mInitialHourOfDay < 12 ? AM : PM);
|
||||
mAmPmTextView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
tryVibrate();
|
||||
int amOrPm = mRadialTimePickerView.getAmOrPm();
|
||||
if (amOrPm == AM) {
|
||||
amOrPm = PM;
|
||||
} else if (amOrPm == PM){
|
||||
amOrPm = AM;
|
||||
}
|
||||
updateAmPmDisplay(amOrPm);
|
||||
mRadialTimePickerView.setAmOrPm(amOrPm);
|
||||
}
|
||||
});
|
||||
mAmPmLayout.setLayoutParams(params);
|
||||
mAmPmLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +380,8 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
public void setEnabled(boolean enabled) {
|
||||
mHourView.setEnabled(enabled);
|
||||
mMinuteView.setEnabled(enabled);
|
||||
mAmPmTextView.setEnabled(enabled);
|
||||
mAmLabel.setEnabled(enabled);
|
||||
mPmLabel.setEnabled(enabled);
|
||||
mRadialTimePickerView.setEnabled(enabled);
|
||||
mIsEnabled = enabled;
|
||||
}
|
||||
@@ -596,16 +588,14 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
mDelegator.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
|
||||
}
|
||||
|
||||
private void updateAmPmDisplay(int amOrPm) {
|
||||
if (amOrPm == AM) {
|
||||
mAmPmTextView.setText(mAmText);
|
||||
mRadialTimePickerView.announceForAccessibility(mAmText);
|
||||
} else if (amOrPm == PM){
|
||||
mAmPmTextView.setText(mPmText);
|
||||
mRadialTimePickerView.announceForAccessibility(mPmText);
|
||||
} else {
|
||||
mAmPmTextView.setText(mDoublePlaceholderText);
|
||||
}
|
||||
private void updateAmPmLabelStates(int amOrPm) {
|
||||
final boolean isAm = amOrPm == AM;
|
||||
mAmLabel.setChecked(isAm);
|
||||
mAmLabel.setAlpha(isAm ? 1 : mDisabledAlpha);
|
||||
|
||||
final boolean isPm = amOrPm == PM;
|
||||
mPmLabel.setChecked(isPm);
|
||||
mPmLabel.setAlpha(isPm ? 1 : mDisabledAlpha);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,7 +619,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
updateHeaderMinute(newValue);
|
||||
mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + newValue);
|
||||
} else if (pickerIndex == AMPM_INDEX) {
|
||||
updateAmPmDisplay(newValue);
|
||||
updateAmPmLabelStates(newValue);
|
||||
} else if (pickerIndex == ENABLE_PICKER_INDEX) {
|
||||
if (!isTypedTimeFullyLegal()) {
|
||||
mTypedTimes.clear();
|
||||
@@ -761,6 +751,11 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
mMinuteView.setSelected(index == MINUTE_INDEX);
|
||||
}
|
||||
|
||||
private void setAmOrPm(int amOrPm) {
|
||||
updateAmPmLabelStates(amOrPm);
|
||||
mRadialTimePickerView.setAmOrPm(amOrPm);
|
||||
}
|
||||
|
||||
/**
|
||||
* For keyboard mode, processes key events.
|
||||
*
|
||||
@@ -929,7 +924,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
updateHeaderHour(hour, true);
|
||||
updateHeaderMinute(minute);
|
||||
if (!mIs24HourView) {
|
||||
updateAmPmDisplay(hour < 12 ? AM : PM);
|
||||
updateAmPmLabelStates(hour < 12 ? AM : PM);
|
||||
}
|
||||
setCurrentItemShowing(mRadialTimePickerView.getCurrentItemShowing(), true, true);
|
||||
onValidationChanged(true);
|
||||
@@ -947,7 +942,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
mMinuteView.setText(minuteStr);
|
||||
mMinuteView.setSelected(false);
|
||||
if (!mIs24HourView) {
|
||||
updateAmPmDisplay(values[2]);
|
||||
updateAmPmLabelStates(values[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1231,6 +1226,33 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
|
||||
}
|
||||
}
|
||||
|
||||
private final View.OnClickListener mClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
final int amOrPm;
|
||||
switch (v.getId()) {
|
||||
case R.id.am_label:
|
||||
setAmOrPm(AM);
|
||||
break;
|
||||
case R.id.pm_label:
|
||||
setAmOrPm(PM);
|
||||
break;
|
||||
case R.id.hours:
|
||||
setCurrentItemShowing(HOUR_INDEX, true, true);
|
||||
break;
|
||||
case R.id.minutes:
|
||||
setCurrentItemShowing(MINUTE_INDEX, true, true);
|
||||
break;
|
||||
default:
|
||||
// Failed to handle this click, don't vibrate.
|
||||
return;
|
||||
}
|
||||
|
||||
tryVibrate();
|
||||
}
|
||||
};
|
||||
|
||||
private final View.OnKeyListener mKeyListener = new View.OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
|
||||
@@ -20,14 +20,13 @@
|
||||
android:layout_height="match_parent">
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center">
|
||||
android:layout_height="match_parent">
|
||||
<TextView
|
||||
android:id="@+id/hours"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toLeftOf="@+id/separator"
|
||||
android:layout_alignBaseline="@+id/separator" />
|
||||
android:layout_centerVertical="true" />
|
||||
<TextView
|
||||
android:id="@+id/separator"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -41,14 +40,31 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@+id/separator"
|
||||
android:layout_alignBaseline="@+id/separator" />
|
||||
<TextView
|
||||
android:id="@+id/ampm_label"
|
||||
android:layout_centerVertical="true" />
|
||||
<LinearLayout
|
||||
android:id="@+id/ampm_layout"
|
||||
android:layout_alignBaseline="@+id/minutes"
|
||||
android:layout_toEndOf="@+id/separator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/timepicker_ampm_left_padding"
|
||||
android:paddingRight="@dimen/timepicker_ampm_left_padding"
|
||||
android:layout_toRightOf="@+id/separator"
|
||||
android:layout_alignBaseline="@+id/separator" />
|
||||
android:baselineAlignedChildIndex="1"
|
||||
android:orientation="vertical">
|
||||
<CheckedTextView
|
||||
android:id="@+id/am_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
|
||||
android:paddingTop="@dimen/timepicker_ampm_vertical_padding"
|
||||
android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
|
||||
android:paddingBottom="@dimen/timepicker_am_bottom_padding" />
|
||||
<CheckedTextView
|
||||
android:id="@+id/pm_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
|
||||
android:paddingTop="@dimen/timepicker_pm_top_padding"
|
||||
android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
|
||||
android:paddingBottom="@dimen/timepicker_ampm_vertical_padding" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</FrameLayout>
|
||||
|
||||
@@ -367,12 +367,15 @@
|
||||
<dimen name="timepicker_time_label_size">60sp</dimen>
|
||||
<dimen name="timepicker_extra_time_label_margin">-30dp</dimen>
|
||||
<dimen name="timepicker_ampm_label_size">16sp</dimen>
|
||||
<dimen name="timepicker_ampm_left_padding">6dip</dimen>
|
||||
<dimen name="timepicker_separator_padding">4dip</dimen>
|
||||
<dimen name="timepicker_header_height">96dip</dimen>
|
||||
<dimen name="timepicker_minimum_margin_sides">48dip</dimen>
|
||||
<dimen name="timepicker_minimum_margin_top_bottom">24dip</dimen>
|
||||
<dimen name="timepicker_radial_picker_dimen">270dip</dimen>
|
||||
<dimen name="timepicker_ampm_horizontal_padding">12dp</dimen>
|
||||
<dimen name="timepicker_ampm_vertical_padding">16dp</dimen>
|
||||
<dimen name="timepicker_am_bottom_padding">1dp</dimen>
|
||||
<dimen name="timepicker_pm_top_padding">2dp</dimen>
|
||||
<dimen name="timepicker_separator_padding">4dp</dimen>
|
||||
<dimen name="timepicker_header_height">96dp</dimen>
|
||||
<dimen name="timepicker_minimum_margin_sides">48dp</dimen>
|
||||
<dimen name="timepicker_minimum_margin_top_bottom">24dp</dimen>
|
||||
<dimen name="timepicker_radial_picker_dimen">270dp</dimen>
|
||||
|
||||
<!-- Used by SimpleMonthView -->
|
||||
<dimen name="datepicker_day_number_size">12sp</dimen>
|
||||
|
||||
@@ -1936,7 +1936,9 @@
|
||||
<java-symbol type="id" name="time_header" />
|
||||
<java-symbol type="id" name="hours" />
|
||||
<java-symbol type="id" name="minutes" />
|
||||
<java-symbol type="id" name="ampm_label" />
|
||||
<java-symbol type="id" name="ampm_layout" />
|
||||
<java-symbol type="id" name="am_label" />
|
||||
<java-symbol type="id" name="pm_label" />
|
||||
<java-symbol type="id" name="radial_picker" />
|
||||
<java-symbol type="id" name="separator" />
|
||||
<java-symbol type="id" name="date_picker_header" />
|
||||
|
||||
Reference in New Issue
Block a user