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

Commit 8817aa93 authored by Alan Viverette's avatar Alan Viverette
Browse files

Allow developer to override Material-style modes in picker dialogs

A recent fix prevented developers from specifying Holo-style mode when
displaying a date or time picker dialog. This CL also cleans up unused
code in TimePickerDialog and documents how themeResId will be used.

Adds hidden @TestApi methods for use in CTS tests. These may be made
public later, but it's too late in MR1 for API changes.

Bug: 31586821
Test: Ice2e203983769f1ea1cfa93105eb97b6fa5176b9
Change-Id: I1b7512b7647ddd7ab987beac2c0aef4fe7cc16bc
parent 488ca21f
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -5631,6 +5631,7 @@ package android.app {
  public class TimePickerDialog extends android.app.AlertDialog implements android.content.DialogInterface.OnClickListener android.widget.TimePicker.OnTimeChangedListener {
    ctor public TimePickerDialog(android.content.Context, android.app.TimePickerDialog.OnTimeSetListener, int, int, boolean);
    ctor public TimePickerDialog(android.content.Context, int, android.app.TimePickerDialog.OnTimeSetListener, int, int, boolean);
    method public android.widget.TimePicker getTimePicker();
    method public void onClick(android.content.DialogInterface, int);
    method public void onTimeChanged(android.widget.TimePicker, int, int);
    method public void updateTime(int, int);
@@ -46605,6 +46606,7 @@ package android.widget {
    method public int getFirstDayOfWeek();
    method public long getMaxDate();
    method public long getMinDate();
    method public int getMode();
    method public int getMonth();
    method public deprecated boolean getSpinnersShown();
    method public int getYear();
@@ -46615,6 +46617,8 @@ package android.widget {
    method public void setMinDate(long);
    method public deprecated void setSpinnersShown(boolean);
    method public void updateDate(int, int, int);
    field public static final int MODE_CALENDAR = 2; // 0x2
    field public static final int MODE_SPINNER = 1; // 0x1
  }
  public static abstract interface DatePicker.OnDateChangedListener {
@@ -48379,6 +48383,7 @@ package android.widget {
    method public deprecated java.lang.Integer getCurrentMinute();
    method public int getHour();
    method public int getMinute();
    method public int getMode();
    method public boolean is24HourView();
    method public deprecated void setCurrentHour(java.lang.Integer);
    method public deprecated void setCurrentMinute(java.lang.Integer);
@@ -48386,6 +48391,8 @@ package android.widget {
    method public void setIs24HourView(java.lang.Boolean);
    method public void setMinute(int);
    method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
    field public static final int MODE_CLOCK = 2; // 0x2
    field public static final int MODE_SPINNER = 1; // 0x1
  }
  public static abstract interface TimePicker.OnTimeChangedListener {
+16 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.app;

import android.annotation.TestApi;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
@@ -91,6 +92,12 @@ public class TimePickerDialog extends AlertDialog implements OnClickListener,

    /**
     * Creates a new time picker dialog with the specified theme.
     * <p>
     * The theme is overlaid on top of the theme of the parent {@code context}.
     * If {@code themeResId} is 0, the dialog will be inflated using the theme
     * specified by the
     * {@link android.R.attr#timePickerDialogTheme android:timePickerDialogTheme}
     * attribute on the parent {@code context}'s theme.
     *
     * @param context the parent context
     * @param themeResId the resource ID of the theme to apply to this dialog
@@ -109,11 +116,6 @@ public class TimePickerDialog extends AlertDialog implements OnClickListener,
        mIs24HourView = is24HourView;

        final Context themeContext = getContext();


        final TypedValue outValue = new TypedValue();
        context.getTheme().resolveAttribute(R.attr.timePickerDialogTheme, outValue, true);

        final LayoutInflater inflater = LayoutInflater.from(themeContext);
        final View view = inflater.inflate(R.layout.time_picker_dialog, null);
        setView(view);
@@ -128,6 +130,15 @@ public class TimePickerDialog extends AlertDialog implements OnClickListener,
        mTimePicker.setOnTimeChangedListener(this);
    }

    /**
     * @return the time picker displayed in the dialog
     * @hide For testing only.
     */
    @TestApi
    public TimePicker getTimePicker() {
        return mTimePicker;
    }

    @Override
    public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
        /* do nothing */
+54 −4
Original line number Diff line number Diff line
@@ -18,7 +18,9 @@ package android.widget;

import com.android.internal.R;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.annotation.Widget;
import android.content.Context;
import android.content.res.Configuration;
@@ -32,6 +34,8 @@ import android.util.SparseArray;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;

/**
@@ -75,11 +79,36 @@ import java.util.Locale;
 */
@Widget
public class DatePicker extends FrameLayout {
    private static final int MODE_SPINNER = 1;
    private static final int MODE_CALENDAR = 2;
    /**
     * Presentation mode for the Holo-style date picker that uses a set of
     * {@link android.widget.NumberPicker}s.
     *
     * @see #getMode()
     * @hide Visible for testing only.
     */
    @TestApi
    public static final int MODE_SPINNER = 1;

    /**
     * Presentation mode for the Material-style date picker that uses a
     * calendar.
     *
     * @see #getMode()
     * @hide Visible for testing only.
     */
    @TestApi
    public static final int MODE_CALENDAR = 2;

    /** @hide */
    @IntDef({MODE_SPINNER, MODE_CALENDAR})
    @Retention(RetentionPolicy.SOURCE)
    public @interface DatePickerMode {}

    private final DatePickerDelegate mDelegate;

    @DatePickerMode
    private final int mMode;

    /**
     * The callback used to indicate the user changed the date.
     */
@@ -114,11 +143,20 @@ public class DatePicker extends FrameLayout {

        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
                defStyleAttr, defStyleRes);
        final int mode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER);
        final boolean isDialogMode = a.getBoolean(R.styleable.DatePicker_dialogMode, false);
        final int requestedMode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER);
        final int firstDayOfWeek = a.getInt(R.styleable.DatePicker_firstDayOfWeek, 0);
        a.recycle();

        switch (mode) {
        if (requestedMode == MODE_CALENDAR && isDialogMode) {
            // You want MODE_CALENDAR? YOU CAN'T HANDLE MODE_CALENDAR! Well,
            // maybe you can depending on your screen size. Let's check...
            mMode = context.getResources().getInteger(R.integer.date_picker_mode);
        } else {
            mMode = requestedMode;
        }

        switch (mMode) {
            case MODE_CALENDAR:
                mDelegate = createCalendarUIDelegate(context, attrs, defStyleAttr, defStyleRes);
                break;
@@ -144,6 +182,18 @@ public class DatePicker extends FrameLayout {
                defStyleRes);
    }

    /**
     * @return the picker's presentation mode, one of {@link #MODE_CALENDAR} or
     *         {@link #MODE_SPINNER}
     * @attr ref android.R.styleable#DatePicker_datePickerMode
     * @hide Visible for testing only.
     */
    @DatePickerMode
    @TestApi
    public int getMode() {
        return mMode;
    }

    /**
     * Initialize the state. If the provided values designate an inconsistent
     * date the values are normalized before updating the spinners.
+54 −4
Original line number Diff line number Diff line
@@ -18,8 +18,10 @@ package android.widget;

import com.android.internal.R;

import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.annotation.Widget;
import android.content.Context;
import android.content.res.TypedArray;
@@ -30,6 +32,8 @@ import android.util.MathUtils;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;

import libcore.icu.LocaleData;
@@ -45,11 +49,36 @@ import libcore.icu.LocaleData;
 */
@Widget
public class TimePicker extends FrameLayout {
    private static final int MODE_SPINNER = 1;
    private static final int MODE_CLOCK = 2;
    /**
     * Presentation mode for the Holo-style time picker that uses a set of
     * {@link android.widget.NumberPicker}s.
     *
     * @see #getMode()
     * @hide Visible for testing only.
     */
    @TestApi
    public static final int MODE_SPINNER = 1;

    /**
     * Presentation mode for the Material-style time picker that uses a clock
     * face.
     *
     * @see #getMode()
     * @hide Visible for testing only.
     */
    @TestApi
    public static final int MODE_CLOCK = 2;

    /** @hide */
    @IntDef({MODE_SPINNER, MODE_CLOCK})
    @Retention(RetentionPolicy.SOURCE)
    public @interface TimePickerMode {}

    private final TimePickerDelegate mDelegate;

    @TimePickerMode
    private final int mMode;

    /**
     * The callback interface used to indicate the time has been adjusted.
     */
@@ -80,10 +109,19 @@ public class TimePicker extends FrameLayout {

        final TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
        final int mode = a.getInt(R.styleable.TimePicker_timePickerMode, MODE_SPINNER);
        final boolean isDialogMode = a.getBoolean(R.styleable.TimePicker_dialogMode, false);
        final int requestedMode = a.getInt(R.styleable.TimePicker_timePickerMode, MODE_SPINNER);
        a.recycle();

        switch (mode) {
        if (requestedMode == MODE_CLOCK && isDialogMode) {
            // You want MODE_CLOCK? YOU CAN'T HANDLE MODE_CLOCK! Well, maybe
            // you can depending on your screen size. Let's check...
            mMode = context.getResources().getInteger(R.integer.time_picker_mode);
        } else {
            mMode = requestedMode;
        }

        switch (mMode) {
            case MODE_CLOCK:
                mDelegate = new TimePickerClockDelegate(
                        this, context, attrs, defStyleAttr, defStyleRes);
@@ -96,6 +134,18 @@ public class TimePicker extends FrameLayout {
        }
    }

    /**
     * @return the picker's presentation mode, one of {@link #MODE_CLOCK} or
     *         {@link #MODE_SPINNER}
     * @attr ref android.R.styleable#TimePicker_timePickerMode
     * @hide Visible for testing only.
     */
    @TimePickerMode
    @TestApi
    public int getMode() {
        return mMode;
    }

    /**
     * Sets the currently selected hour using 24-hour time.
     *
+1 −1
Original line number Diff line number Diff line
@@ -22,4 +22,4 @@
    android:layout_height="wrap_content"
    android:spinnersShown="true"
    android:calendarViewShown="true"
    android:datePickerMode="@integer/date_picker_mode" />
    android:dialogMode="true" />
Loading