Kompatybilność z paskiem akcji została dodana do biblioteki obsługi w wersji 18. Posiada ona teraz ActionBarActivity
klasę do tworzenia działań z paskiem akcji na starszych wersjach Androida.
Czy jest jakiś sposób na dodanie paska akcji z biblioteki wsparcia do PreferenceActivity
?
Wcześniej korzystałem z ActionBarSherlock i ma SherlockPreferenceActivity
.
Odpowiedzi:
EDYCJA: W appcompat-v7 22.1.0 Google dodał klasę abstrakcyjną AppCompatDelegate jako delegata, którego można użyć do rozszerzenia obsługi AppCompat na dowolną aktywność.
Użyj tego w ten sposób:
... import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatDelegate; import android.support.v7.widget.Toolbar; ... public class SettingsActivity extends PreferenceActivity { private AppCompatDelegate mDelegate; @Override protected void onCreate(Bundle savedInstanceState) { getDelegate().installViewFactory(); getDelegate().onCreate(savedInstanceState); super.onCreate(savedInstanceState); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); getDelegate().onPostCreate(savedInstanceState); } public ActionBar getSupportActionBar() { return getDelegate().getSupportActionBar(); } public void setSupportActionBar(@Nullable Toolbar toolbar) { getDelegate().setSupportActionBar(toolbar); } @Override public MenuInflater getMenuInflater() { return getDelegate().getMenuInflater(); } @Override public void setContentView(@LayoutRes int layoutResID) { getDelegate().setContentView(layoutResID); } @Override public void setContentView(View view) { getDelegate().setContentView(view); } @Override public void setContentView(View view, ViewGroup.LayoutParams params) { getDelegate().setContentView(view, params); } @Override public void addContentView(View view, ViewGroup.LayoutParams params) { getDelegate().addContentView(view, params); } @Override protected void onPostResume() { super.onPostResume(); getDelegate().onPostResume(); } @Override protected void onTitleChanged(CharSequence title, int color) { super.onTitleChanged(title, color); getDelegate().setTitle(title); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); getDelegate().onConfigurationChanged(newConfig); } @Override protected void onStop() { super.onStop(); getDelegate().onStop(); } @Override protected void onDestroy() { super.onDestroy(); getDelegate().onDestroy(); } public void invalidateOptionsMenu() { getDelegate().invalidateOptionsMenu(); } private AppCompatDelegate getDelegate() { if (mDelegate == null) { mDelegate = AppCompatDelegate.create(this, null); } return mDelegate; } }
Nigdy więcej hakowania. Kod pobrany z AppCompatPreferenceActivity.java .
źródło
(ViewGroup) getWindow().getDecorView().getRootView()
Obecnie nie ma sposobu, aby to osiągnąć za pomocą AppCompat. Otworzyłem błąd wewnętrznie.
źródło
PreferenceActivity
że zostaniemy dodani doActionBarCompat
?Udało mi się stworzyć obejście podobne do tego, którego używa Sklep Google Play. Link do oryginalnej odpowiedzi
Znajdź repozytorium GitHub: tutaj
Bardzo podobny do twojego własnego kodu, ale dodano XML, aby umożliwić ustawienie tytułu:
Kontynuacja użytkowania
PreferenceActivity
:settings_toolbar.xml :
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/toolbar" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?attr/actionBarSize" app:navigationContentDescription="@string/abc_action_bar_up_description" android:background="?attr/colorPrimary" app:navigationIcon="?attr/homeAsUpIndicator" app:title="@string/action_settings" />
SettingsActivity.java :
public class SettingsActivity extends PreferenceActivity { @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent(); Toolbar bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); root.addView(bar, 0); // insert at top bar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } }
Result :
UPDATE (zgodność z piernikami):
Jak wskazano tutaj , Gingerbread Devices zwracają NullPointerException w tej linii:
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
NAPRAWIĆ:
SettingsActivity.java :
public class SettingsActivity extends PreferenceActivity { @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); Toolbar bar; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { LinearLayout root = (LinearLayout) findViewById(android.R.id.list).getParent().getParent().getParent(); bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); root.addView(bar, 0); // insert at top } else { ViewGroup root = (ViewGroup) findViewById(android.R.id.content); ListView content = (ListView) root.getChildAt(0); root.removeAllViews(); bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); int height; TypedValue tv = new TypedValue(); if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) { height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics()); }else{ height = bar.getHeight(); } content.setPadding(0, height, 0, 0); root.addView(content); root.addView(bar); } bar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } }
Wszelkie problemy z powyższym daj mi znać!
AKTUALIZACJA 2: OBEJŚCIE BARWIENIA
Jak wskazano w wielu notatkach deweloperów,
PreferenceActivity
nie obsługuje barwienia elementów, jednak używając kilku wewnętrznych klas MOŻESZ to osiągnąć. Dzieje się tak do momentu usunięcia tych klas. (Działa przy użyciu appCompat support-v7 v21.0.3).Dodaj następujące importy:
import android.support.v7.internal.widget.TintCheckBox; import android.support.v7.internal.widget.TintCheckedTextView; import android.support.v7.internal.widget.TintEditText; import android.support.v7.internal.widget.TintRadioButton; import android.support.v7.internal.widget.TintSpinner;
Następnie nadpisz
onCreateView
metodę:@Override public View onCreateView(String name, Context context, AttributeSet attrs) { // Allow super to try and create a view first final View result = super.onCreateView(name, context, attrs); if (result != null) { return result; } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { // If we're running pre-L, we need to 'inject' our tint aware Views in place of the // standard framework versions switch (name) { case "EditText": return new TintEditText(this, attrs); case "Spinner": return new TintSpinner(this, attrs); case "CheckBox": return new TintCheckBox(this, attrs); case "RadioButton": return new TintRadioButton(this, attrs); case "CheckedTextView": return new TintCheckedTextView(this, attrs); } } return null; }
Result:
AppCompat 22.1
AppCompat 22.1 wprowadził nowe przyciemniane elementy, co oznacza, że nie ma już potrzeby wykorzystywania klas wewnętrznych, aby osiągnąć ten sam efekt, co podczas ostatniej aktualizacji. Zamiast tego wykonaj następujące czynności (nadal nadrzędne
onCreateView
):@Override public View onCreateView(String name, Context context, AttributeSet attrs) { // Allow super to try and create a view first final View result = super.onCreateView(name, context, attrs); if (result != null) { return result; } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { // If we're running pre-L, we need to 'inject' our tint aware Views in place of the // standard framework versions switch (name) { case "EditText": return new AppCompatEditText(this, attrs); case "Spinner": return new AppCompatSpinner(this, attrs); case "CheckBox": return new AppCompatCheckBox(this, attrs); case "RadioButton": return new AppCompatRadioButton(this, attrs); case "CheckedTextView": return new AppCompatCheckedTextView(this, attrs); } } return null; }
EKRANY PREFERENCYJNE ZAGNIEŻDŻONE
Wiele osób ma problemy z włączaniem paska narzędzi do zagnieżdżonych
<PreferenceScreen />
s, jednak znalazłem rozwiązanie! - Po wielu próbach i błędach!Dodaj do swojego
SettingsActivity
:@SuppressWarnings("deprecation") @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { super.onPreferenceTreeClick(preferenceScreen, preference); // If the user has clicked on a preference screen, set up the screen if (preference instanceof PreferenceScreen) { setUpNestedScreen((PreferenceScreen) preference); } return false; } public void setUpNestedScreen(PreferenceScreen preferenceScreen) { final Dialog dialog = preferenceScreen.getDialog(); Toolbar bar; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { LinearLayout root = (LinearLayout) dialog.findViewById(android.R.id.list).getParent(); bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); root.addView(bar, 0); // insert at top } else { ViewGroup root = (ViewGroup) dialog.findViewById(android.R.id.content); ListView content = (ListView) root.getChildAt(0); root.removeAllViews(); bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); int height; TypedValue tv = new TypedValue(); if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) { height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics()); }else{ height = bar.getHeight(); } content.setPadding(0, height, 0, 0); root.addView(content); root.addView(bar); } bar.setTitle(preferenceScreen.getTitle()); bar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); }
Powodem tego
PreferenceScreen
jest to, że są one oparte na oknach opakowujących, więc musimy uchwycić układ okna dialogowego, aby dodać do niego pasek narzędzi.Cień paska narzędzi
Zgodnie z projektem importowanie
Toolbar
nie pozwala na elewację i cieniowanie w urządzeniach starszych niż 21, więc jeśli chcesz mieć elewację na swoimToolbar
, musisz owinąć ją wAppBarLayout
:`settings_toolbar.xml:
<android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar .../> </android.support.design.widget.AppBarLayout>
Nie zapominając o dodaniu biblioteki Design Support jako zależności w
build.gradle
pliku:compile 'com.android.support:support-v4:22.2.0' compile 'com.android.support:appcompat-v7:22.2.0' compile 'com.android.support:design:22.2.0'
Android 6.0
Zbadałem zgłoszony problem nakładania się i nie mogę go odtworzyć.
Pełny kod używany, jak powyżej, daje następujące wyniki:
Jeśli czegoś brakuje, daj mi znać za pośrednictwem tego repozytorium, a zbadam sprawę.
źródło
:)
PreferenceActivity
takie upierdliwe używanie ??? ma zaoszczędzić czas. Równie dobrze mógłbym wykonywać regularne czynności i samodzielnie układać wszystkie ustawienia w układzie liniowym. Fuuuuck!Znaleziono implementację PreferenceFragment opartą na fragmencie support-v4:
https://github.com/kolavar/android-support-v4-preferencefragment
Edycja: właśnie go przetestowałem i działa świetnie!
źródło
Integracja
PreferenceActivity
z ABC nie jest możliwa, przynajmniej dla mnie. Wypróbowałem dwie możliwości, które mogłem znaleźć, ale żadna nie działała:Opcja 1:
ActionBarPreferenceActivity
rozciąga sięPreferenceActivity
. Kiedy to robisz, zostajesz ograniczonyActionBarActivityDelegate.createDelegate(ActionBarActivity activity)
. Musisz również wdrożyć,ActionBar.Callbacks
które nie jest dostępneOpcja 2:
ActionBarPreferenceActivity
rozciąga sięActionBarActivity
. Takie podejście wymaga przepisywania zupełnie nowyPreferenceActivity
,PreferenceManager
a może byćPreferenceFragment
co oznacza, że muszą mieć dostęp do ukrytych klas jakcom.android.internal.util.XmlUtils
Rozwiązaniem tego problemu może pochodzić tylko od Google DEVS wdrożeniaActionBarWrapper
, które mogą być dodawane do każdej działalności.Jeśli naprawdę potrzebujesz aktywności preferencyjnej, na razie radzę
ActionBarSherlock
.Jednak udało mi się to tutaj zaimplementować .
źródło
Tło problemu:
PO chce wiedzieć, w jaki sposób możemy umieścić
MenuItem
swActionBar
odPreferenceActivity
wstępnego Honeycomb ponieważ biblioteka wsparcie Android ma błąd, który nie może do tego dopuścić.Moje rozwiązanie:
Znalazłem znacznie czystszy sposób, niż już proponowano, na osiągnięcie celu (i znalazłem go w Android Docs ):
Teraz zrób to, co normalnie zrobiłbyś w swoim
onOptionsItemSelected()
. Ponieważ jest częścią Android Docs, nie ma żadnych skutków ubocznych.Miłego kodowania. :)
Aktualizacja:
To rozwiązanie nie działa już, jeśli celujesz w Lollipopa. Jeśli używasz AppCompat, ta odpowiedź jest tym, czego powinieneś szukać.
źródło
PreferencesActivity
że nie mieli żadnego sposobu na umieszczenie przedmiotówActionBar
, zwłaszcza przycisku Wstecz. Moja odpowiedź to dobre rozwiązanie.:)
Udało mi się uzyskać
android.app.Actionbar
za pomocągetActionBar()
. Na początku zwróciło wartość null ... potem przeszedłem do manifestu i zmieniłem motyw na:android:theme="@style/Theme.AppCompat"
Wtedy znów mogłem mieć pasek akcji. Zakładam, że to zadziała tylko na niektórych poziomach kompilacji. Więc możesz chcieć sprawdzić numer kompilacji lub sprawdzić, czy zwrócona wartość jest pusta.
Dla mnie będzie dobrze, ponieważ aplikacja, nad którą pracuję, jest przeznaczona dla
ICS/4.0
+.źródło
Teraz została wydana oficjalna odpowiedź na ten problem. Jest to biblioteka obsługi preferencji v7 / v14 .
Zobacz Jak korzystać z biblioteki obsługi preferencji w wersji 7/14? do dyskusji, jak go używać.
źródło