2016-10-05 8 views
8

に失敗しました: DatePicker on Android 7-DatePickerDialogホロスタイリングは、私たちのようなSTH、すべてのAndroid OSのバージョンのDatePickerDialogにHOLOのスタイルを維持したい私たちの顧客の需要から、アンドロイド7ヌガー

しかし、Android上で正しく動作しないようです7:私の実装から

DatePicker on Android 7

new DatePickerDialog(getContext(), AlertDialog.THEME_HOLO_LIGHT, 
         mCalendarPickerListener, 
         calendar.get(Calendar.YEAR), 
         calendar.get(Calendar.MONTH), 
         calendar.get(Calendar.DAY_OF_MONTH)); 

これは、以前のアンドロイド7のためにうまくいきます。誰も同じ問題がありますか?

編集:溶液はAPIで固定されることがわかっている25 https://code.google.com/u/106133255289400340786/

+0

サポートライブラリを更新しましたか? – Shuddh

+0

@Shuddhは既に試しましたが、それでも同じです:)私は'24 .2.1 'を試しましたhttps://developer.android.com/topic/libraries/support-library/revisions.html –

+0

私はこの問題にも取り組んでいます。誰にでも解決策がありますか? – FinalFive

答えて

16

私はDatePickerDialogを使用して、誕生日のためにユーザーの入力を求めます。残念ながら、試したときにMaterial-themedダイアログについて多くのユーザーからの苦情がありましたので、それに切り替えることは選択肢ではありません。ホロをテーマにしたダイアログに固執する必要があります。このプラットフォーム上でホロのテーマを使用しようとすると、代わりにバックDatePickerDialogため壊れ素材のテーマを使用してにフォール:

それは、Android 7.0がバグに同梱されていることが判明しました。これら二つのバグレポートを参照してください:

  • Issue 222808
  • Issue 222208が、私はそれらのバグレポートで参照this workaround by Jeff Lockhartの修飾型を使用:これは何

    private static final class FixedHoloDatePickerDialog extends DatePickerDialog { 
        private FixedHoloDatePickerDialog(Context context, OnDateSetListener callBack, 
                 int year, int monthOfYear, int dayOfMonth) { 
         super(context, callBack, year, monthOfYear, dayOfMonth); 
    
         // Force spinners on Android 7.0 only (SDK 24). 
         // Note: I'm using a naked SDK value of 24 here, because I'm 
         // targeting SDK 23, and Build.VERSION_CODES.N is not available yet. 
         // But if you target SDK >= 24, you should have it. 
         if (Build.VERSION.SDK_INT == 24) { 
          try { 
           final Field field = this.findField(
             DatePickerDialog.class, 
             DatePicker.class, 
             "mDatePicker" 
           ); 
    
           final DatePicker datePicker = (DatePicker) field.get(this); 
           final Class<?> delegateClass = Class.forName(
             "android.widget.DatePicker$DatePickerDelegate" 
           ); 
           final Field delegateField = this.findField(
             DatePicker.class, 
             delegateClass, 
             "mDelegate" 
           ); 
    
           final Object delegate = delegateField.get(datePicker); 
           final Class<?> spinnerDelegateClass = Class.forName(
             "android.widget.DatePickerSpinnerDelegate" 
           ); 
    
           if (delegate.getClass() != spinnerDelegateClass) { 
            delegateField.set(datePicker, null); 
            datePicker.removeAllViews(); 
    
            final Constructor spinnerDelegateConstructor = 
              spinnerDelegateClass.getDeclaredConstructor(
                DatePicker.class, 
                Context.class, 
                AttributeSet.class, 
                int.class, 
                int.class 
              ); 
            spinnerDelegateConstructor.setAccessible(true); 
    
            final Object spinnerDelegate = spinnerDelegateConstructor.newInstance(
              datePicker, 
              context, 
              null, 
              android.R.attr.datePickerStyle, 
              0 
            ); 
            delegateField.set(datePicker, spinnerDelegate); 
    
            datePicker.init(year, monthOfYear, dayOfMonth, this); 
            datePicker.setCalendarViewShown(false); 
            datePicker.setSpinnersShown(true); 
           } 
          } catch (Exception e) { /* Do nothing */ } 
         } 
        } 
    
        /** 
        * Find Field with expectedName in objectClass. If not found, find first occurrence of 
        * target fieldClass in objectClass. 
        */ 
        private Field findField(Class objectClass, Class fieldClass, String expectedName) { 
         try { 
          final Field field = objectClass.getDeclaredField(expectedName); 
          field.setAccessible(true); 
          return field; 
         } catch (NoSuchFieldException e) { /* Ignore */ } 
    
         // Search for it if it wasn't found under the expectedName. 
         for (final Field field : objectClass.getDeclaredFields()) { 
          if (field.getType() == fieldClass) { 
           field.setAccessible(true); 
           return field; 
          } 
         } 
    
         return null; 
        } 
    } 
    

    は次のとおりです。

    • このダイアログ
    • に属するプライベートDatePicker mDatePickerフィールドは、デリゲートはDatePickerSpinnerDelegateのインスタンス(私たちが望むデリゲートの種類)
    • すべて削除が既にないことを、このダイアログ
    • チェックに属するプライベートDatePickerDelegate mDelegateフィールドをゲットDatePickerからの眺め、彼らは素材のカレンダーウィジェットですので、
    • DatePickerSpinnerDelegateの新しいインスタンスを作成し、このダイアログ
    • 再初期化のmDatePickermDelegateフィールドに代入しますそれは、この回避策を使用するにはスピナー

    を膨らませるために取得するには、カレンダーの情報といくつかのparamsでmDatePickerをialize、私は私がこの場合はホロには、テーマを設定することができます私のContext周りContextThemeWrapperを作成します。

    final Context themedContext = new ContextThemeWrapper(
         this.getContext(), 
         android.R.style.Theme_Holo_Light_Dialog 
    ); 
    
    final DatePickerDialog dialog = new FixedHoloDatePickerDialog(
         themedContext, 
         datePickerListener, 
         calender.get(Calendar.YEAR), 
         calendar.get(Calendar.MONTH), 
         calendar.get(Calendar.DAY_OF_MONTH) 
    ); 
    

    ノート

    • これは、リフレクションを使用してプライベートフィールドにアクセスします。一般的に、これは強固なアプローチではなく、あなたはそれを信じることができません。私は、1)これを1つのSDKバージョンv24に制限することで、リスクを軽減しています。 2)リフレクションコードのビット全体をtry {...} catch (Exception e) {/* NOP */}ブロックにラッピングするので、リフレクションのいずれかが失敗した場合は何も起こらず、(悲しい壊れた)デフォルトのマテリアルフォールバックが使用されます。
    • 上記のバグレポートは、この問題がAndroid 7.1(SDK 25)で修正されたと主張しています。私はこれをテストしていない。
    • original workaround codeは、同様の問題が発生したTimePickerDialogであった。私は代わりにDatePickerDialogと動作するように修正しました。また、ソリューションをより一般的でなくなるように簡略化しました。しかし、より完全なオリジナルバージョンを使用して、の代わりにDateのために調整することができます。
+0

問題を回避しても、とにかく感謝しても、これは実行可能なように聞こえる –

+0

正しいFIXはAPI 25を使用する必要があります。 https://code.google.com/u/106133255289400340786/ –

+0

set date listener does not work開始日 – WolfJee

0

日付ピッカーは、私はあなたがR.style.Widget.Holo.DatePicker代わりのAlertDialog.THEME_HOLO_LIGHT必要があると思う、それは自身の独立したスタイルhttps://developer.android.com/reference/android/R.style.html#Widget_DatePicker

のしています。 @android:style/Widget.Holo.DatePickerが親であり、それを使用する独自の空のスタイルを作成する必要がある可能性があります。

+0

これは正しく動作せず、代わりに空白のギャップを含むフルスクリーンのカレンダーを表示します。 –

関連する問題