Нет панели действий в PreferenceActivity после обновления до поддержки библиотеки v21
после обновления до библиотеки поддержки v21 моя панель действий в моем PreferenceActivity
ушел.
я пропустил некоторые атрибуты в моей теме, чтобы активировать его снова? У меня были некоторые подобные проблемы с черная панель действий.
Я также попытался добавить его немного hackish, добавив Toolbar
к корневой макет, но это не сработало, как ожидалось.
6 ответов:
пожалуйста, найдите репозиторий GitHub:здесь
очень похоже на ваш собственный код, но добавлен xml, чтобы разрешить установить заголовок:
продолжает использовать
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 :
обновление (совместимость с пряниками):
как отметил здесь, пряничные устройства возвращают NullPointerException на этой строке:
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
исправления:
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.JELLY_BEAN) { 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(); } }); } }
любые проблемы с вышеизложенным дайте мне знать!
ОБНОВЛЕНИЕ 2: ТОНИРОВКА ОБХОДНОЙ ПУТЬ
как указано во многих заметках dev
PreferenceActivity
не поддерживает тонировку элементов, однако, используя несколько внутренних классов, вы можете добиться этого. То есть пока эти классы не будут удаленный. (Работает поддержка-В7 совместимости приложений в21.0.3).добавить следующий импорт:
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;
затем переопределить
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 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 представил новые тонированные элементы, что означает, что больше нет необходимости использовать внутренние классы для достижения того же эффекта, что и последнее обновление. Вместо этого следуйте этому (все еще переопределяя
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.JELLY_BEAN) { // 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; }
ВЛОЖЕННЫЕ ЭКРАНЫ ПРЕДПОЧТЕНИЙ
многие люди испытывают проблемы с включением панели инструментов во вложенные
<PreferenceScreen />
s однако, я нашел решение!! - После долгих проб и ошибок!добавьте к вашему
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(); } }); }
причина в том, что
PreferenceScreen
это такая боль, потому что они основаны как диалог обертки, поэтому нам нужно захватить диалог макет для добавления к нему панели инструментов.
Тень Панели Инструментов
по дизайну импортируя
Toolbar
не допускает возвышения и затенения в устройствах pre-v21, поэтому, если вы хотите иметь возвышение на своемToolbar
вы должны обернуть его вAppBarLayout
:' settings_toolbar.XML-код :
<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar .../> </android.support.design.widget.AppBarLayout>
не забывая добавить добавить библиотеку поддержки дизайна в качестве зависимости в
build.gradle
file: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
я исследовал сообщенную перекрывающуюся проблему, и я не могу воспроизвести проблему.
полный код, используемый выше, дает следующее:
если я чего-то не хватает, пожалуйста, дайте мне знать через этот РЕПО и я проведу расследование.
используйте AppCompatActivity & PreferenceFragment, чтобы решить эту проблему:
AppCompatActivity:
public class SettingsActivity extends AppCompatActivity { @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit(); }}
PreferenceFragment:
public class SettingsFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.settings_preferences); }}
Я закончил тем, что сам добавил панель инструментов с помощью этого простого кода:
// get the root container of the preferences list LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent(); Toolbar bar = (Toolbar)LayoutInflater.from(this).inflate(R.layout.preferences_toolbar, root, false); root.addView(bar, 0); // insert at top bar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } });
вот мой preferences_toolbar.XML-код:
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_height="wrap_content" android:layout_width="match_parent" android:minHeight="?attr/actionBarSize" app:navigationContentDescription="@string/abc_action_bar_up_description" android:background="?attr/colorPrimary" app:navigationIcon="?attr/homeAsUpIndicator" app:theme="@style/Theme.Toolbar" />
лучшее решение, чем "сворачивание собственной" панели действий, - использовать AppCompatDelegate класс, который позволяет ввести панель фактических действий из библиотеки поддержки. Вот пример кода, чтобы использовать его, берется из ответа Ľubomír Кучера к этот вопрос.
... 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; } }
Привет я не если вы все еще есть эта проблема. Но я думаю, что я опубликую то, что я сделал, чтобы решить эту проблему, и надеюсь, что это поможет кому-то.
1) Во-первых, вы могли заметить, что PreferenceActivity расширяет ListActivity, который, в свою очередь, простирается от Activity.
по комментариям в блоге разработчиков (http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html), чтобы использовать v21, все ваши действия должны наследовать ActionBarActivity. Так что это ваша проблема.
2) шаги, которые я использовал для решения являются :
a) Make sure that you set the Theme of your PreferenceActivity to inherits one ot the Theme.AppCompat Themes. b) Make your class PreferenceActivity extends ActionBarActivity. c) Use the PreferenceFragment as your container for all your preferences.
Это должно решить эту проблему.
Ура!
простой способ, который я понял, переопределяет:
@android:style/Theme.Material.Light.DarkActionBar
в вашем стиле:
<style name="SettingsTheme" parent="@android:style/Theme.Material.Light.DarkActionBar"> <item name="android:colorPrimary">@color/sunshine_blue</item> <item name="android:colorPrimaryDark">@color/sunshine_dark_blue</item> </style>