2014-11-14 7 views
16

Ich habe ein Problem mit dem TimePicker Widget auf API 21. Bis API 19 war die TimePicker eine Up-/Down-Liste wie iOS, aber in 21+ ist es rund, wie die in die Kalender AppAndroid API 21 - TimePicker Widget

Wie kann ich das alte in 21+ verwenden, weil es mein Design bricht, wenn es das neue Widget ist.

+0

Ich empfehle diesen Stackoverflow Link für eine programmatisch und XML-Antwort: http://stackoverflow.com/questions/24449723/is-it-possible-to-change-the-style-of-an-android- l-timepickerdialog – Zhang

Antwort

39

Sie können die Spinner-Stil-Zeitauswahl angeben, indem Sie das Attribut timePickerMode auf "Spinner" setzen. Der Standardwert für Material ist "Uhr".

<TimePicker 
    ... 
    android:timePickerMode="spinner" /> 
+3

Wie würde das programmatisch gemacht? –

+1

Sie können defStyleAttr oder defStyleRes beim Erstellen Ihrer Zeitauswahl übergeben. – alanv

+0

Ist es möglich, diesen neuen API 21 Zeitpicker auf Pre-Lollipop zu verwenden? – fpopic

0

Sie können den Spinner-Modus programmgesteuert mit der benutzerdefinierten Klasse verwenden. Für frühere Versionen Von lolipop wird der Zeitspanmodus von Uhr zu Spinner geändert und es ist auch möglich die Zeitauswahl nach einer bestimmten Zeit zu deaktivieren (mit setmax() & setmin()). Im folgenden Code habe ich set max() verwendet, um die maximale Zeit zu begrenzen.

public class RangeTimePickerDialog extends TimePickerDialog { 

    private int minHour = -1; 
    private int minMinute = -1; 

    private int maxHour = 25; 
    private int maxMinute = 25; 

    private int currentHour = 0; 
    private int currentMinute = 0; 

    private Calendar calendar = Calendar.getInstance(); 
    private DateFormat dateFormat; 


    public RangeTimePickerDialog(Context context, int dialogTheme, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) { 
     super(context, callBack, hourOfDay, minute, is24HourView); 
     currentHour = hourOfDay; 
     currentMinute = minute; 
     dateFormat = DateFormat.getTimeInstance(DateFormat.SHORT); 
     fixSpinner(context, hourOfDay, minute, is24HourView); 

     try { 
      Class<?> superclass = getClass().getSuperclass(); 
      Field mTimePickerField = superclass.getDeclaredField("mTimePicker"); 
      mTimePickerField.setAccessible(true); 
      TimePicker mTimePicker = (TimePicker) mTimePickerField.get(this); 
      mTimePicker.setOnTimeChangedListener(this); 
     } catch (NoSuchFieldException e) { 
     } catch (IllegalArgumentException e) { 
     } catch (IllegalAccessException e) { 
     } 
    } 

    public void setMin(int hour, int minute) { 
     minHour = hour; 
     minMinute = minute; 
    } 

    public void setMax(int hour, int minute) { 
     maxHour = hour; 
     maxMinute = minute; 
    } 

    @Override 
    public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { 

     boolean validTime = true; 
     if (hourOfDay < minHour || (hourOfDay == minHour && minute < minMinute)){ 
      validTime = false; 
     } 

     if (hourOfDay > maxHour || (hourOfDay == maxHour && minute > maxMinute)){ 
      validTime = false; 
     } 

     if (validTime) { 
      currentHour = hourOfDay; 
      currentMinute = minute; 
     } 

     updateTime(currentHour, currentMinute); 
     updateDialogTitle(view, currentHour, currentMinute); 
    } 

    private void updateDialogTitle(TimePicker timePicker, int hourOfDay, int minute) { 
     calendar.set(Calendar.HOUR_OF_DAY, hourOfDay); 
     calendar.set(Calendar.MINUTE, minute); 
     String title = dateFormat.format(calendar.getTime()); 
     setTitle(title); 
    } 


    private void fixSpinner(Context context, int hourOfDay, int minute, boolean is24HourView) { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // android:timePickerMode spinner and clock began in Lollipop 
      try { 
       // Get the theme's android:timePickerMode 
       //two modes are available clock mode and spinner mode ... selecting spinner mode for latest versions 
       final int MODE_SPINNER = 2; 
       Class<?> styleableClass = Class.forName("com.android.internal.R$styleable"); 
       Field timePickerStyleableField = styleableClass.getField("TimePicker"); 
       int[] timePickerStyleable = (int[]) timePickerStyleableField.get(null); 
       final TypedArray a = context.obtainStyledAttributes(null, timePickerStyleable, android.R.attr.timePickerStyle, 0); 
       Field timePickerModeStyleableField = styleableClass.getField("TimePicker_timePickerMode"); 
       int timePickerModeStyleable = timePickerModeStyleableField.getInt(null); 
       final int mode = a.getInt(timePickerModeStyleable, MODE_SPINNER); 
       a.recycle(); 
       if (mode == MODE_SPINNER) { 
        TimePicker timePicker = (TimePicker) findField(TimePickerDialog.class, TimePicker.class, "mTimePicker").get(this); 
        Class<?> delegateClass = Class.forName("android.widget.TimePicker$TimePickerDelegate"); 
        Field delegateField = findField(TimePicker.class, delegateClass, "mDelegate"); 
        Object delegate = delegateField.get(timePicker); 
        Class<?> spinnerDelegateClass; 
        if (Build.VERSION.SDK_INT != Build.VERSION_CODES.LOLLIPOP) { 
         spinnerDelegateClass = Class.forName("android.widget.TimePickerSpinnerDelegate"); 
        } else { 

         spinnerDelegateClass = Class.forName("android.widget.TimePickerClockDelegate"); 
        } 
        if (delegate.getClass() != spinnerDelegateClass) { 
         delegateField.set(timePicker, null); // throw out the TimePickerClockDelegate! 
         timePicker.removeAllViews(); // remove the TimePickerClockDelegate views 
         Constructor spinnerDelegateConstructor = spinnerDelegateClass.getConstructor(TimePicker.class, Context.class, AttributeSet.class, int.class, int.class); 
         spinnerDelegateConstructor.setAccessible(true); 
         // Instantiate a TimePickerSpinnerDelegate 
         delegate = spinnerDelegateConstructor.newInstance(timePicker, context, null, android.R.attr.timePickerStyle, 0); 
         delegateField.set(timePicker, delegate); // set the TimePicker.mDelegate to the spinner delegate 
         // Set up the TimePicker again, with the TimePickerSpinnerDelegate 
         timePicker.setIs24HourView(is24HourView); 
         timePicker.setCurrentHour(hourOfDay); 
         timePicker.setCurrentMinute(minute); 
         timePicker.setOnTimeChangedListener(this); 
        } 
       } 
      } catch (Exception e) { 
       throw new RuntimeException(e); 
      } 
     } 
    } 
    private static Field findField(Class objectClass, Class fieldClass, String expectedName) { 
     try { 
      Field field = objectClass.getDeclaredField(expectedName); 
      field.setAccessible(true); 
      return field; 
     } catch (NoSuchFieldException e) {} // ignore 
     // search for it if it wasn't found under the expected ivar name 
     for (Field searchField : objectClass.getDeclaredFields()) { 
      if (searchField.getType() == fieldClass) { 
       searchField.setAccessible(true); 
       return searchField; 
      } 
     } 
     return null; 
    } 
} 
+0

Die Verwendung von Reflektion ist nicht zukunftssicher. Ich würde das nicht benutzen. – mars3142