Chcę napisać preferencje, które można zastosować zarówno do urządzeń 3.0, jak i starszych. Odkrywając, że PreferenceActivity
zawiera przestarzałe metody (chociaż są one używane w towarzyszącym przykładowym kodzie), przyjrzałem się PreferenceFragement
i pakietowi zgodności, aby rozwiązać moje problemy.
Wydaje się jednak, że PreferenceFragment
nie ma tego w pakiecie zgodności. Czy ktoś może mi powiedzieć, czy to było zamierzone? Jeśli tak, czy mogę łatwo wybrać zakres urządzeń (np. <3.0 i> = 3.0), czy też będę musiał przeskakiwać przez przeszkody? Jeśli nie zostało to celowo wykluczone, czy możemy spodziewać się nowej wersji pakietu kompatybilności? A może istnieje inne obejście, które jest bezpieczne w użyciu?
Twoje zdrowie
James
PreferenceFragment
, o której zapomnisz, że nawet tam jest. Zobacz moją odpowiedź ."Because most of Preferences' implementation is hidden, therefore impossible to backport without lots of hackery."
PreferenceFragmentCompat
został niedawno dodany do biblioteki wsparcia.Odpowiedzi:
Przestarzałe metody są przestarzałe w systemie Android 3.0. Działają doskonale na wszystkich wersjach Androida, ale kierunek jest taki, aby używać
PreferenceFragment
na Androidzie 3.0 i nowszych.Domyślam się, że jest to kwestia czasu inżynieryjnego, ale to tylko przypuszczenie.
Uważam to za „łatwe”. Miej dwie oddzielne
PreferenceActivity
implementacje, jedną używającą nagłówków preferencjiPreferenceFragments
, a drugą używającą oryginalnego podejścia. Wybierz właściwy w momencie, w którym chcesz (np. Gdy użytkownik kliknie element menu opcji). Oto przykładowy projekt demonstrujący to. Lub mieć pojedynczy,PreferenceActivity
który obsługuje oba przypadki, jak w tym przykładowym projekcie .Dowiesz się, kiedy reszta z nas się dowie, to znaczy, czy i kiedy zostanie wysłany.
Patrz wyżej.
źródło
<include>
działa z XML preferencji. Przy okazji, jeśli jesteś subskrybentem, aktualizacja książki odnosząca się do tego projektu została ogłoszona kilka minut temu.Subtelna konsekwencja odpowiedzi z @CommonsWare jest taka, że - Twoja aplikacja musi wybierać między interfejsem API zgodności lub wbudowanym interfejsem API fragmentów (od SDK 11 lub tak dalej). W rzeczywistości to właśnie spowodowało zalecenie „łatwo”. Innymi słowy, jeśli chcesz używać PreferenceFragment, Twoja aplikacja musi korzystać z wbudowanego interfejsu API fragmentów i obsługiwać przestarzałe metody w PreferenceActivity. I odwrotnie, jeśli ważne jest, aby Twoja aplikacja korzystała z kompatybilności. API będziesz mieć do czynienia z brakiem klasy PreferenceFragment. W związku z tym urządzenia celownicze nie stanowią problemu, ale przeskakiwanie ma miejsce, gdy musisz wybrać jeden lub drugi interfejs API, a tym samym poddać projekt nieprzewidzianemu obejściu. Potrzebuję kompatybil. API, więc utworzę własną klasę PreferenceFragment i zobaczę, jak to działa. W najgorszym przypadku I '
EDYCJA: po wypróbowaniu i obejrzeniu kodu na http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/preference/PreferenceFragment.java? av = h - tworzenie własnego elementu PreferenceFragment nie nastąpi. Wydaje się, że głównym blokerem jest liberalne użycie prywatnego pakietu w PreferenceManager zamiast „chronionego”. Naprawdę nie wygląda na to, że jest jakieś zabezpieczenie lub naprawdę dobra motywacja, aby to zrobić, i nie jest to dobre do testowania jednostkowego, ale cóż ... mniej pisania chyba ...
EDYCJA v2: Właściwie to się wydarzyło i zadziałało. Z pewnością ból głowy sprawił, że kod działał z plikiem JAR interfejsu Compatibility API. Musiałem skopiować około 70% pakietu com.android.preference z SDK do mojej aplikacji, a następnie zmagać się z typowo przeciętnej jakości kodem Java w systemie Android. Użyłem wersji 14 SDK. Inżynierowi Google byłoby znacznie łatwiej zrobić to, co ja, w przeciwieństwie do tego, co słyszałem od niektórych czołowych inżynierów Androida, którzy mówią na ten temat.
BTW - czy powiedziałem, że „kierowanie na urządzenia to nie problem”? To jest całkowicie ... jeśli używasz com.android.preference, nie będziesz mógł zamienić się z interfejsem Compatibility API bez poważnej refaktoryzacji. Zabawny dziennik!
źródło
Opierając się na odpowiedzi CommonsWare, a także obserwacjach Tenacious ', wymyśliłem rozwiązanie klasy potomnej, zdolne do kierowania wszystkich obecnych wersji Android API przy minimalnym zamieszaniu i bez duplikacji kodu lub zasobów. Zobacz moją odpowiedź na powiązane pytanie tutaj: PreferenceActivity Android 4.0 i starsze
lub na moim blogu: http://www.blackmoonit.com/2012/07/all_api_prefsactivity/
Przetestowano na dwóch tabletach z systemem 4.0.3 i 4.0.4, a także telefonie z systemem 4.0.4 i 2.3.3 oraz emulatorze z wersją 1.6.
źródło
Zobacz PreferenceFragment-Compat z Machinarius. Łatwo było wpaść z gradle i zapominam, że nawet tam jest.
compile 'com.github.machinarius:preferencefragment:0.1.1'
Ważna aktualizacja: najnowsza wersja z
v7 support library
obecnie posiada natywną PreferenceFragmentCompat .źródło
W sierpniu 2015 firma Google wydała nową bibliotekę obsługi preferencji v7 .
Teraz możesz użyć PreferenceFragmentCompat z dowolnym
Activity
lubAppCompatActivity
Musisz ustawić
preferenceTheme
w swoim motywie:W ten sposób możesz dostosować
preferenceTheme
styl układów używanych dla każdego typu preferencji bez wpływu na inne części działania.źródło
Odpowiedź Wytrwałego jest poprawna, ale oto więcej szczegółów.
Powodem, dla którego nie można „utworzyć normalnego układu i ręcznie powiązać składniki widoku z Sharedprefs” jest fakt, że w API android.preferences występują zaskakujące pominięcia. PreferenceActivity i PreferenceFragment mają dostęp do krytycznych niepublicznych metod PreferenceManager, bez których nie można zaimplementować własnego interfejsu użytkownika preferencji.
W szczególności, aby skonstruować hierarchię preferencji z pliku XML, musisz użyć PreferenceManager, ale wszystkie konstruktory PreferenceManager są albo prywatne, albo ukryte. Metoda dołączania detektorów Preference onClick do twojego działania jest również prywatna dla pakietu.
Nie można tego obejść, podstępnie umieszczając swoją implementację w pakiecie android.preferences, ponieważ niepubliczne metody w Android API są w rzeczywistości pomijane w SDK. Przy odrobinie kreatywności obejmującej refleksję i dynamiczne proxy, nadal możesz się do nich dostać. Jedyną alternatywą, jak mówi Tenacious, jest rozwidlenie całego pakietu android.preference, w tym co najmniej 15 klas, 5 układów i podobną liczbę elementów style.xml i attrs.xml.
Odpowiadając na pierwotne pytanie, powodem, dla którego Google nie uwzględnił PreferenceFragment w pakiecie zgodności, jest to, że mieliby dokładnie taką samą trudność jak Tenacious i ja. Nawet Google nie może cofnąć się w czasie i upublicznić tych metod na starych platformach (chociaż mam nadzieję, że zrobią to w przyszłych wydaniach).
źródło
Celem mojej aplikacji jest API +14, ale ze względu na korzystanie z biblioteki wsparcia dla jakiejś wymyślnej nawigacji nie mogłem używać
android.app.Fragment
i musiałem używaćandroid.support.v4.app.Fragment
, ale musiałem również mieć toPreferenceFragment
miejsce bez dużych zmian w kodzie.Więc moja łatwa poprawka do posiadania obu światów biblioteki wsparcia i
PreferenceFragment
:źródło
Musiałem zintegrować Preferencje z projektem aplikacji i zachować wsparcie dla Androida 2.3. Więc nadal potrzebowałem PreferencesFragment.
Po kilku poszukiwaniach znalazłem android-support-v4-preferencefragment lib. Ta biblioteka oszczędza dużo czasu na kopiowanie i refaktoryzację oryginalnego PreferencesFragment, jak powiedział Tenacious. Działa dobrze, a użytkownicy lubią preferencje.
źródło