Merge "Update AM/PM selectors for clock face TimePicker" into lmp-mr1-dev

This commit is contained in:
Alan Viverette
2014-10-16 23:48:35 +00:00
committed by Android (Google) Code Review
6 changed files with 185 additions and 333 deletions

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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>

View File

@@ -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>

View File

@@ -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" />