Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6791c7bf authored by Roozbeh Pournader's avatar Roozbeh Pournader
Browse files

Respect the locale in vertical location of AM/PM

If the locale puts the AM/PM before the hour and minute in time
formatting, make sure TimePicker respects that by putting the AM/PM
above the hour and minute in landscape mode, where the AM/PM used to
always appear below the hour and minute.

Two sets of locales are affected. All of them put the AM/PM before
the hour and minute, but the first set also defaults to 12-hour, so
the change is most visible in these: Ewe, Chinese (both Simplified
and Traditional, including Cantonese), Korean, and Tamil. The second
set, Hungarian, Japanese, Myanmar, Sinhala, and Turkish, would only
see the difference if the time picker is forced into 12-hour mode.

Test: manual (tested en-US, ar-EG, ta-IN, zh-Hans-CN, ko-KR)
Change-Id: Ic5840d46d81a004294bda4644df02c721152686b
Fixes: 63352170
parent 01bcf1ef
Loading
Loading
Loading
Loading
+60 −28
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ import com.android.internal.widget.NumericTextView.OnValueChangedListener;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Calendar;
import java.util.Locale;

/**
 * A delegate implementing the radial clock-based TimePicker.
@@ -113,7 +112,11 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
    private int mCurrentHour;
    private int mCurrentMinute;
    private boolean mIs24Hour;
    private boolean mIsAmPmAtLeft = false; // The layouts put AM/PM at the right by default.

    // The portrait layout puts AM/PM at the right by default.
    private boolean mIsAmPmAtLeft = false;
    // The landscape layouts put AM/PM at the bottom by default.
    private boolean mIsAmPmAtTop = false;

    // Localization data.
    private boolean mHourFormatShowLeadingZero;
@@ -433,34 +436,35 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
        setCurrentItemShowing(index, false, true);
    }

    // Find the location of AM/PM based on locale information.
    private static boolean isAmPmAtLeftSide(Locale locale) {
        final String dateTimePattern = DateFormat.getBestDateTimePattern(locale, "hm");
        final boolean isAmPmAtStart = dateTimePattern.startsWith("a");
        if (TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_LTR) {
            return isAmPmAtStart;
        } else {
            return !isAmPmAtStart;
        }
    }

    private void updateHeaderAmPm() {
        if (mIs24Hour) {
            mAmPmLayout.setVisibility(View.GONE);
        } else {
            setAmPmAtLeft(isAmPmAtLeftSide(mLocale));
            // Find the location of AM/PM based on locale information.
            final String dateTimePattern = DateFormat.getBestDateTimePattern(mLocale, "hm");
            final boolean isAmPmAtStart = dateTimePattern.startsWith("a");
            setAmPmStart(isAmPmAtStart);
            updateAmPmLabelStates(mCurrentHour < 12 ? AM : PM);
        }
    }

    private void setAmPmAtLeft(boolean isAmPmAtLeft) {
        if (mIsAmPmAtLeft != isAmPmAtLeft) {
            mIsAmPmAtLeft = isAmPmAtLeft;

    private void setAmPmStart(boolean isAmPmAtStart) {
        final RelativeLayout.LayoutParams params =
                (RelativeLayout.LayoutParams) mAmPmLayout.getLayoutParams();
            if (params.getRule(RelativeLayout.RIGHT_OF) != 0 ||
                    params.getRule(RelativeLayout.LEFT_OF) != 0) {
        if (params.getRule(RelativeLayout.RIGHT_OF) != 0
                || params.getRule(RelativeLayout.LEFT_OF) != 0) {
            // Horizontal mode, with AM/PM appearing to left/right of hours and minutes.
            final boolean isAmPmAtLeft;
            if (TextUtils.getLayoutDirectionFromLocale(mLocale) == View.LAYOUT_DIRECTION_LTR) {
                isAmPmAtLeft = isAmPmAtStart;
            } else {
                isAmPmAtLeft = !isAmPmAtStart;
            }
            if (mIsAmPmAtLeft == isAmPmAtLeft) {
                // AM/PM is already at the correct location. No change needed.
                return;
            }

            if (isAmPmAtLeft) {
                params.removeRule(RelativeLayout.RIGHT_OF);
                params.addRule(RelativeLayout.LEFT_OF, mHourView.getId());
@@ -468,10 +472,38 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
                params.removeRule(RelativeLayout.LEFT_OF);
                params.addRule(RelativeLayout.RIGHT_OF, mMinuteView.getId());
            }
            mIsAmPmAtLeft = isAmPmAtLeft;
        } else if (params.getRule(RelativeLayout.BELOW) != 0
                || params.getRule(RelativeLayout.ABOVE) != 0) {
            // Vertical mode, with AM/PM appearing to top/bottom of hours and minutes.
            if (mIsAmPmAtTop == isAmPmAtStart) {
                // AM/PM is already at the correct location. No change needed.
                return;
            }

            mAmPmLayout.setLayoutParams(params);
            final int otherViewId;
            if (isAmPmAtStart) {
                otherViewId = params.getRule(RelativeLayout.BELOW);
                params.removeRule(RelativeLayout.BELOW);
                params.addRule(RelativeLayout.ABOVE, otherViewId);
            } else {
                otherViewId = params.getRule(RelativeLayout.ABOVE);
                params.removeRule(RelativeLayout.ABOVE);
                params.addRule(RelativeLayout.BELOW, otherViewId);
            }

            // Switch the top and bottom paddings on the other view.
            final View otherView = mRadialTimePickerHeader.findViewById(otherViewId);
            final int top = otherView.getPaddingTop();
            final int bottom = otherView.getPaddingBottom();
            final int left = otherView.getPaddingLeft();
            final int right = otherView.getPaddingRight();
            otherView.setPadding(left, bottom, right, top);

            mIsAmPmAtTop = isAmPmAtStart;
        }

        mAmPmLayout.setLayoutParams(params);
    }

    /**
+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:paddingTop="@dimen/timepicker_radial_picker_top_margin"
            android:orientation="horizontal">