diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java index e33c4d4da7a6d..1c1d77a9c3338 100644 --- a/core/java/android/widget/TimePicker.java +++ b/core/java/android/widget/TimePicker.java @@ -22,10 +22,12 @@ import android.content.res.Configuration; import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; +import android.text.format.DateFormat; import android.text.format.DateUtils; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; @@ -105,6 +107,9 @@ public class TimePicker extends FrameLayout { private Locale mCurrentLocale; + private boolean mHourWithTwoDigit; + private char mHourFormat; + /** * The callback interface used to indicate the time has been adjusted. */ @@ -164,7 +169,7 @@ public class TimePicker extends FrameLayout { // divider (only for the new widget style) mDivider = (TextView) findViewById(R.id.divider); if (mDivider != null) { - mDivider.setText(R.string.time_picker_separator); + setDividerText(); } // minute @@ -235,6 +240,24 @@ public class TimePicker extends FrameLayout { mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE); } + if (isAmPmAtStart()) { + // Move the am/pm view to the beginning + ViewGroup amPmParent = (ViewGroup) findViewById(R.id.timePickerLayout); + amPmParent.removeView(amPmView); + amPmParent.addView(amPmView, 0); + // Swap layout margins if needed. They may be not symmetrical (Old Standard Theme for + // example and not for Holo Theme) + ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) amPmView.getLayoutParams(); + final int startMargin = lp.getMarginStart(); + final int endMargin = lp.getMarginEnd(); + if (startMargin != endMargin) { + lp.setMarginStart(endMargin); + lp.setMarginEnd(startMargin); + } + } + + getHourFormatData(); + // update controls to initial state updateHourControl(); updateMinuteControl(); @@ -259,6 +282,35 @@ public class TimePicker extends FrameLayout { } } + private void getHourFormatData() { + final Locale defaultLocale = Locale.getDefault(); + final String bestDateTimePattern = DateFormat.getBestDateTimePattern(defaultLocale, + (mIs24HourView) ? "Hm" : "hm"); + final int lengthPattern = bestDateTimePattern.length(); + mHourWithTwoDigit = false; + char hourFormat = '\0'; + // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save + // the hour format that we found. + for (int i = 0; i < lengthPattern; i++) { + final char c = bestDateTimePattern.charAt(i); + if (c == 'H' || c == 'h' || c == 'K' || c == 'k') { + mHourFormat = c; + if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) { + mHourWithTwoDigit = true; + } + break; + } + } + } + + private boolean isAmPmAtStart() { + final Locale defaultLocale = Locale.getDefault(); + final String bestDateTimePattern = DateFormat.getBestDateTimePattern(defaultLocale, + "hm" /* skeleton */); + + return bestDateTimePattern.startsWith("a"); + } + @Override public void setEnabled(boolean enabled) { if (mIsEnabled == enabled) { @@ -423,9 +475,11 @@ public class TimePicker extends FrameLayout { if (mIs24HourView == is24HourView) { return; } - mIs24HourView = is24HourView; - // cache the current hour since spinner range changes + // cache the current hour since spinner range changes and BEFORE changing mIs24HourView!! int currentHour = getCurrentHour(); + // Order is important here. + mIs24HourView = is24HourView; + getHourFormatData(); updateHourControl(); // set value after spinner range is updated setCurrentHour(currentHour); @@ -458,6 +512,38 @@ public class TimePicker extends FrameLayout { onTimeChanged(); } + /** + * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":". + * + * See http://unicode.org/cldr/trac/browser/trunk/common/main + * + * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the + * separator as the character which is just after the hour marker in the returned pattern. + */ + private void setDividerText() { + final Locale defaultLocale = Locale.getDefault(); + final String skeleton = (mIs24HourView) ? "Hm" : "hm"; + final String bestDateTimePattern = DateFormat.getBestDateTimePattern(defaultLocale, + skeleton); + final String separatorText; + int hourIndex = bestDateTimePattern.lastIndexOf('H'); + if (hourIndex == -1) { + hourIndex = bestDateTimePattern.lastIndexOf('h'); + } + if (hourIndex == -1) { + // Default case + separatorText = ":"; + } else { + int minuteIndex = bestDateTimePattern.indexOf('m', hourIndex + 1); + if (minuteIndex == -1) { + separatorText = Character.toString(bestDateTimePattern.charAt(hourIndex + 1)); + } else { + separatorText = bestDateTimePattern.substring(hourIndex + 1, minuteIndex); + } + } + mDivider.setText(separatorText); + } + @Override public int getBaseline() { return mHourSpinner.getBaseline(); @@ -500,14 +586,25 @@ public class TimePicker extends FrameLayout { private void updateHourControl() { if (is24HourView()) { - mHourSpinner.setMinValue(0); - mHourSpinner.setMaxValue(23); - mHourSpinner.setFormatter(NumberPicker.getTwoDigitFormatter()); + // 'k' means 1-24 hour + if (mHourFormat == 'k') { + mHourSpinner.setMinValue(1); + mHourSpinner.setMaxValue(24); + } else { + mHourSpinner.setMinValue(0); + mHourSpinner.setMaxValue(23); + } } else { - mHourSpinner.setMinValue(1); - mHourSpinner.setMaxValue(12); - mHourSpinner.setFormatter(null); + // 'K' means 0-11 hour + if (mHourFormat == 'K') { + mHourSpinner.setMinValue(0); + mHourSpinner.setMaxValue(11); + } else { + mHourSpinner.setMinValue(1); + mHourSpinner.setMaxValue(12); + } } + mHourSpinner.setFormatter(mHourWithTwoDigit ? NumberPicker.getTwoDigitFormatter() : null); } private void updateMinuteControl() { diff --git a/core/res/res/layout/time_picker.xml b/core/res/res/layout/time_picker.xml index a78cd85870aa0..4fa94f328a5cc 100644 --- a/core/res/res/layout/time_picker.xml +++ b/core/res/res/layout/time_picker.xml @@ -20,6 +20,7 @@ + android:layout_height="wrap_content" + android:paddingStart="8dip" + android:paddingEnd="8dip"> @@ -37,8 +42,6 @@ android:layout_height="wrap_content" android:layout_marginTop="16dip" android:layout_marginBottom="16dip" - android:layout_marginStart="16dip" - android:layout_marginEnd="6dip" android:focusable="true" android:focusableInTouchMode="true" /> @@ -48,6 +51,8 @@ android:id="@+id/divider" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginStart="6dip" + android:layout_marginEnd="6dip" android:layout_gravity="center_vertical" android:importantForAccessibility="no" /> @@ -59,8 +64,6 @@ android:layout_height="wrap_content" android:layout_marginTop="16dip" android:layout_marginBottom="16dip" - android:layout_marginStart="6dip" - android:layout_marginEnd="8dip" android:focusable="true" android:focusableInTouchMode="true" /> @@ -75,7 +78,7 @@ android:layout_marginTop="16dip" android:layout_marginBottom="16dip" android:layout_marginStart="8dip" - android:layout_marginEnd="16dip" + android:layout_marginEnd="8dip" android:focusable="true" android:focusableInTouchMode="true" /> diff --git a/core/res/res/values/donottranslate.xml b/core/res/res/values/donottranslate.xml index b49e7bd50037b..a7288e166c3ee 100644 --- a/core/res/res/values/donottranslate.xml +++ b/core/res/res/values/donottranslate.xml @@ -24,8 +24,6 @@ true square - - : eeeMMMMd diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 14ae1e6f08014..ca93d1c67a98d 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -217,6 +217,7 @@ + @@ -773,7 +774,6 @@ -