Merge "Ensure time picker dialog fits on small screens" into lmp-mr1-dev

This commit is contained in:
Alan Viverette
2014-11-12 17:32:30 +00:00
committed by Android (Google) Code Review
6 changed files with 58 additions and 70 deletions

View File

@@ -353,7 +353,7 @@ public class ColorStateList implements Parcelable {
for (int i = 0; i < inputStates.length; i++) { for (int i = 0; i < inputStates.length; i++) {
final int[] inputState = inputStates[i]; final int[] inputState = inputStates[i];
for (int j = 0; j < inputState.length; j++) { for (int j = 0; j < inputState.length; j++) {
if (inputState[i] == state) { if (inputState[j] == state) {
return colorStateList; return colorStateList;
} }
} }

View File

@@ -23,7 +23,6 @@ import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.text.TextUtils;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
@@ -100,9 +99,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
private int mPmKeyCode; private int mPmKeyCode;
// Accessibility strings. // Accessibility strings.
private String mHourPickerDescription;
private String mSelectHours; private String mSelectHours;
private String mMinutePickerDescription;
private String mSelectMinutes; private String mSelectMinutes;
// Most recent time announcement values for accessibility. // Most recent time announcement values for accessibility.
@@ -122,9 +119,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
Context.LAYOUT_INFLATER_SERVICE); Context.LAYOUT_INFLATER_SERVICE);
final Resources res = mContext.getResources(); final Resources res = mContext.getResources();
mHourPickerDescription = res.getString(R.string.hour_picker_description);
mSelectHours = res.getString(R.string.select_hours); mSelectHours = res.getString(R.string.select_hours);
mMinutePickerDescription = res.getString(R.string.minute_picker_description);
mSelectMinutes = res.getString(R.string.select_minutes); mSelectMinutes = res.getString(R.string.select_minutes);
String[] amPmStrings = TimePickerSpinnerDelegate.getAmPmStrings(context); String[] amPmStrings = TimePickerSpinnerDelegate.getAmPmStrings(context);
@@ -153,6 +148,11 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
mMinuteView.setTextAppearance(context, headerTimeTextAppearance); mMinuteView.setTextAppearance(context, headerTimeTextAppearance);
} }
// Now that we have text appearances out of the way, make sure the hour
// and minute views are correctly sized.
mHourView.setMinWidth(computeStableWidth(mHourView, 24));
mMinuteView.setMinWidth(computeStableWidth(mMinuteView, 60));
// TODO: This can be removed once we support themed color state lists. // TODO: This can be removed once we support themed color state lists.
final int headerSelectedTextColor = a.getColor( final int headerSelectedTextColor = a.getColor(
R.styleable.TimePicker_headerSelectedTextColor, R.styleable.TimePicker_headerSelectedTextColor,
@@ -206,6 +206,23 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX); initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX);
} }
private int computeStableWidth(TextView v, int maxNumber) {
int maxWidth = 0;
for (int i = 0; i < maxNumber; i++) {
final String text = String.format("%02d", i);
v.setText(text);
v.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
final int width = v.getMeasuredWidth();
if (width > maxWidth) {
maxWidth = width;
}
}
return maxWidth;
}
private void initialize(int hourOfDay, int minute, boolean is24HourView, int index) { private void initialize(int hourOfDay, int minute, boolean is24HourView, int index) {
mInitialHourOfDay = hourOfDay; mInitialHourOfDay = hourOfDay;
mInitialMinute = minute; mInitialMinute = minute;
@@ -242,48 +259,21 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
setCurrentItemShowing(index, false, true); setCurrentItemShowing(index, false, true);
} }
private int computeMaxWidthOfNumbers(int max) {
TextView tempView = new TextView(mContext);
tempView.setTextAppearance(mContext, R.style.TextAppearance_Material_TimePicker_TimeLabel);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
tempView.setLayoutParams(lp);
int maxWidth = 0;
for (int minutes = 0; minutes < max; minutes++) {
final String text = String.format("%02d", minutes);
tempView.setText(text);
tempView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
maxWidth = Math.max(maxWidth, tempView.getMeasuredWidth());
}
return maxWidth;
}
private void updateHeaderAmPm() { private void updateHeaderAmPm() {
if (mIs24HourView) { if (mIs24HourView) {
mAmPmLayout.setVisibility(View.GONE); mAmPmLayout.setVisibility(View.GONE);
} else { } else {
final String bestDateTimePattern = DateFormat.getBestDateTimePattern( // Ensure that AM/PM layout is in the correct position.
mCurrentLocale, "hm"); final String dateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, "hm");
boolean amPmOnLeft = bestDateTimePattern.startsWith("a"); final boolean amPmAtStart = dateTimePattern.startsWith("a");
if (TextUtils.getLayoutDirectionFromLocale(mCurrentLocale) == final ViewGroup parent = (ViewGroup) mAmPmLayout.getParent();
View.LAYOUT_DIRECTION_RTL) { final int targetIndex = amPmAtStart ? 0 : parent.getChildCount() - 1;
amPmOnLeft = !amPmOnLeft; final int currentIndex = parent.indexOfChild(mAmPmLayout);
if (targetIndex != currentIndex) {
parent.removeView(mAmPmLayout);
parent.addView(mAmPmLayout, targetIndex);
} }
final ViewGroup.MarginLayoutParams params =
(ViewGroup.MarginLayoutParams) mAmPmLayout.getLayoutParams();
if (amPmOnLeft) {
params.leftMargin = 0;
params.rightMargin = computeMaxWidthOfNumbers(12 /* for hours */);
} else {
params.leftMargin = computeMaxWidthOfNumbers(60 /* for minutes */);
params.rightMargin = 0;
}
mAmPmLayout.setLayoutParams(params);
mAmPmLayout.setVisibility(View.VISIBLE);
updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM); updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM);
} }
} }

View File

@@ -20,11 +20,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="horizontal" android:orientation="horizontal">
android:layout_marginLeft="@dimen/timepicker_minimum_margin_sides"
android:layout_marginRight="@dimen/timepicker_minimum_margin_sides"
android:layout_marginTop="@dimen/timepicker_minimum_margin_top_bottom"
android:layout_marginBottom="@dimen/timepicker_minimum_margin_top_bottom">
<FrameLayout <FrameLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@@ -17,46 +17,50 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/time_header" android:id="@+id/time_header"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
<RelativeLayout android:padding="@dimen/timepicker_separator_padding"
android:layout_width="match_parent" android:gravity="center">
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="bottom"
android:orientation="horizontal">
<TextView <TextView
android:id="@+id/hours" android:id="@+id/hours"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/separator" android:gravity="end" />
android:layout_centerVertical="true" />
<TextView <TextView
android:id="@+id/separator" android:id="@+id/separator"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="@dimen/timepicker_separator_padding" android:layout_marginLeft="@dimen/timepicker_separator_padding"
android:paddingRight="@dimen/timepicker_separator_padding" android:layout_marginRight="@dimen/timepicker_separator_padding"
android:layout_centerInParent="true"
android:importantForAccessibility="no" /> android:importantForAccessibility="no" />
<TextView <TextView
android:id="@+id/minutes" android:id="@+id/minutes"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_toRightOf="@+id/separator" android:gravity="start" />
android:layout_centerVertical="true" />
<LinearLayout <LinearLayout
android:id="@+id/ampm_layout" android:id="@+id/ampm_layout"
android:layout_alignBaseline="@+id/minutes"
android:layout_toEndOf="@+id/separator"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:baselineAlignedChildIndex="1" android:orientation="vertical"
android:orientation="vertical"> android:baselineAlignedChildIndex="1">
<CheckedTextView <CheckedTextView
android:id="@+id/am_label" android:id="@+id/am_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="@dimen/timepicker_ampm_horizontal_padding" android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
android:paddingTop="@dimen/timepicker_ampm_vertical_padding"
android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding" android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
android:paddingBottom="@dimen/timepicker_am_bottom_padding" android:paddingTop="@dimen/timepicker_ampm_vertical_padding"
android:lines="1" android:lines="1"
android:ellipsize="none" /> android:ellipsize="none" />
<CheckedTextView <CheckedTextView
@@ -64,11 +68,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="@dimen/timepicker_ampm_horizontal_padding" android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
android:paddingTop="@dimen/timepicker_pm_top_padding"
android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding" android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
android:paddingBottom="@dimen/timepicker_ampm_vertical_padding" android:paddingTop="@dimen/timepicker_pm_top_padding"
android:lines="1" android:lines="1"
android:ellipsize="none" /> android:ellipsize="none" />
</LinearLayout> </LinearLayout>
</RelativeLayout> </LinearLayout>
</FrameLayout> </FrameLayout>

View File

@@ -18,7 +18,7 @@
--> -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<include <include

View File

@@ -372,8 +372,7 @@
<dimen name="timepicker_ampm_label_size">16sp</dimen> <dimen name="timepicker_ampm_label_size">16sp</dimen>
<dimen name="timepicker_ampm_horizontal_padding">12dp</dimen> <dimen name="timepicker_ampm_horizontal_padding">12dp</dimen>
<dimen name="timepicker_ampm_vertical_padding">16dp</dimen> <dimen name="timepicker_ampm_vertical_padding">16dp</dimen>
<dimen name="timepicker_am_bottom_padding">1dp</dimen> <dimen name="timepicker_pm_top_padding">3dp</dimen>
<dimen name="timepicker_pm_top_padding">2dp</dimen>
<dimen name="timepicker_separator_padding">4dp</dimen> <dimen name="timepicker_separator_padding">4dp</dimen>
<dimen name="timepicker_header_height">96dp</dimen> <dimen name="timepicker_header_height">96dp</dimen>
<dimen name="timepicker_minimum_margin_sides">48dp</dimen> <dimen name="timepicker_minimum_margin_sides">48dp</dimen>