15

En az 10 no'lu desteği istiyorum, tercihlerimi güzel bir şekilde şekillendirmek istiyorum, üstbilgi sahibi olmak istiyorum (ya da PreferenceScreen numaralı telefonu). Görünüşe göre AppCompat 'un tamamen desteklemediği PreferenceActivity, uymuyor. Yani AppCompatActivity ve PreferenceFragmentCompat kullanmayı deniyorum.android.support.v7.preference kütüphanesini kullanarak nasıl özel tercihler oluştururum?

public class Prefs extends AppCompatActivity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     if (savedInstanceState == null) 
      getSupportFragmentManager().beginTransaction() 
        .replace(android.R.id.content, new PreferencesFragment()) 
        .commit(); 
    } 

    public static class PreferencesFragment extends PreferenceFragmentCompat { 
     @Override public void onCreate(final Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      addPreferencesFromResource(R.xml.preferences); 
     } 

     @Override 
     public void onDisplayPreferenceDialog(Preference preference) { 
      // the following call results in a dialogue being shown 
      super.onDisplayPreferenceDialog(preference); 
     } 

     @Override public void onNavigateToScreen(PreferenceScreen preferenceScreen) { 
      // I can probably use this to go to to a nested preference screen 
      // I'm not sure... 
     } 
    } 
} 

Şimdi, yazı tipi seçimi sağlayacak özel bir tercih oluşturmak istiyorum. PreferenceActivity, ben sadece

import android.preference.DialogPreference; 

public class FontPreference extends DialogPreference { 

    public FontPreference(Context context, AttributeSet attrs) {super(context, attrs);} 

    @Override protected void onPrepareDialogBuilder(Builder builder) { 
     super.onPrepareDialogBuilder(builder); 
     // do something with builder and make a nice cute dialogue, for example, like this 
     builder.setSingleChoiceItems(new FontAdapter(), 0, null); 
    } 
} 

yapabileceğini ve bunu

<my.app.FontPreference android:title="Choose font" android:summary="Unnecessary summary" /> 

görüntülemek için bu gibi xml kullanmak Ama şimdi, android.support.v7.preference.DialogPreference hiçbir onPrepareDialogBuilder yoktur. Bunun yerine, PreferenceDialogFragmentCompat'a taşındı. Bu şeyi nasıl kullanacağım konusunda çok az bilgi buldum ve xml'den nasıl görüntüleneceğine emin değilim.

public void onDisplayPreferenceDialog(Preference preference) { 
    ... 

    final DialogFragment f; 
    if (preference instanceof EditTextPreference) 
     f = EditTextPreferenceDialogFragment.newInstance(preference.getKey()); 
    ... 
    f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG); 
} 

I android.support.v7.preference.DialogPreference sınıflara ve onDisplayPreferenceDialog boş bir FontPreferenceFragment örneğini Benzer bir kod parçasını kullanmak ancak şu istisna ile başarısız olan denedik: V14 tercih fragmanı, aşağıdaki kodu vardır.

java.lang.IllegalStateException: Target fragment must implement TargetFragment interface 

Bu noktada, karmaşanın çok derinliğindeyim ve daha fazla kazmak istemiyorum. Google bu istisna hakkında hiçbir şey bilmiyor. Her neyse, bu yöntem aşırı karmaşık görünüyor. Peki, android.support.v7.preference kütüphanesini kullanarak özel tercihler oluşturmanın en iyi yolu nedir?

cevap

28

Önemli not: Şu (v23.0.1 v7 kütüphanesinin) 'PreferenceThemeOverlay' ile teması-birçok konu hala vardır (this issue bakınız). Örneğin, Lollipop'ta, Holo tarzı kategori başlıklarıyla sona erersiniz.

Bazı sinir bozucu saatler geçtikten sonra, özel bir v7 Tercihi oluşturmayı başardım. Kendi Preference'u oluşturmak, gerekli olduğunu düşündüğünüzden daha zor görünüyor. Bu yüzden biraz zaman ayırdığınızdan emin olun.

İlk başta, her tercih türü için neden bir DialogPreference ve bir PreferenceDialogFragmentCompat bulacağınızı merak ediyor olabilirsiniz. Anlaşıldığı gibi, ilki gerçek tercihtir, ikincisi ise tercihin gösterileceği DialogFragment'dur. Ne yazık ki, 'u bunlardan alt sınıfına ayırmanız gerekir.

Endişelenme, herhangi bir kod parçasını değiştirmeniz gerekmez. Yalnızca bazı yöntemler taşınmaya gerek: (setTitle() veya persist*() gibi)

  • Tüm tercihi düzenleme yöntemleri DialogPreference sınıfta bulunabilir.
  • Tüm iletişim (düzenleme yöntemleri) yöntemleri (onBindDialogView(View) & onDialogClosed(boolean)) PreferenceDialogFragmentCompat'a taşındı.

Varolan sınıfınızın ilkini genişletmesini isteyebilirsiniz, bu şekilde bence çok fazla değişiklik yapmanız gerekmez. Otomatik tamamlama, eksik yöntemleri bulmanıza yardımcı olmalıdır.

Yukarıdaki adımları tamamladığınızda, bu iki sınıfı birbirine bağlamanın zamanı gelmiştir. Xml dosyanızda tercih kısmına başvuracaksınız. Ancak, Android, özel tercihinizin olması gerektiğinde hangi şişirmenin gerektiğini şişirmek için henüz Fragment olduğunu bilmiyor. Bu nedenle, onDisplayPreferenceDialog(Preference) geçersiz kılmak gerekir: Ayrıca

@Override 
public void onDisplayPreferenceDialog(Preference preference) { 
    DialogFragment fragment; 
    if (preference instanceof LocationChooserDialog) { 
     fragment = LocationChooserFragmentCompat.newInstance(preference); 
     fragment.setTargetFragment(this, 0); 
     fragment.show(getFragmentManager(), 
       "android.support.v7.preference.PreferenceFragment.DIALOG"); 
    } else super.onDisplayPreferenceDialog(preference); 
} 

ve DialogFragment ihtiyaçları 'anahtar' işlemek için:

public static YourPreferenceDialogFragmentCompat newInstance(Preference preference) { 
    YourPreferenceDialogFragmentCompat fragment = new YourPreferenceDialogFragmentCompat(); 
    Bundle bundle = new Bundle(1); 
    bundle.putString("key", preference.getKey()); 
    fragment.setArguments(bundle); 
    return fragment; 
} 

hile yapmak gerektiğini. Sorunlarla karşılaşırsanız, varolan alt sınıflara bir göz atmayı deneyin ve Android'in nasıl çözdüğünü görün (Android Studio'da: 'name' yazın ve decompiled sınıfı görmek için Ctrl + b tuşlarına basın). Umarım yardımcı olur.

+2

Neredeyse mükemmel bir çözüm! PreDisplayPreferenceDialog'un tercih parçasında (PreferenceFragmentCompat'ı devralarak) geçersiz kılınması gerektiğini farketmem biraz zaman aldı. Çok teşekkürler! –

+2

Bunu okuyan herkes için bir not: PreferenceDialogFragmentCompat.java:57/58 içinde bir ClassCastException alırsanız, bundle.putString ("key", preference.getKey()); satır yukarıdaki gibi "anahtar" diyor. Aksi halde getArguments(). GetString (ARG_KEY) ClassCastException ile başarısız olur. – MCLLC

+0

Eğer bir örneğiniz varsa lütfen tam bir örnek gönderir misiniz? Yeni destek Tercihleri ​​uygulamak başardı, ancak DialogPreferences bir kabus. Google, bu konuda herhangi bir doküman sağlamaz. –

0

FontPreferenceFragment, DialogPreference.TargetFragment uygulanmadığında istisna neden olur. Fragmanınızın bu arayüzü uyguladığıdan emin olmanız gerekir.

+0

DialogPreference.TargetFragment işlevini uygular. Ancak bu, bir şeyi çözmüş olsa bile, hala bir çözüm olacaktır. Doğru yol daha basit olmalı. – squirrel

İlgili konular