Как добавить панель действий из библиотеки поддержки в PreferenceActivity?
совместимость панели действий была добавлена в библиотеку поддержки, версия 18. Теперь он имеет ActionBarActivity
класс для создания действий с панелью действий на старых версиях Android.
есть ли способ добавить панель действий из библиотеки поддержки в PreferenceActivity
?
ранее я использовал ActionBarSherlock и SherlockPreferenceActivity
.
8 ответов
EDIT: в appcompat-v7 22.1.0 Google добавил абстрактный класс AppCompatDelegate в качестве делегата, который вы можете использовать для расширения поддержки AppCompat на любую деятельность.
используйте его следующим образом:
...
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;
}
}
нет больше взлома. Код взят из AppCompatPreferenceActivity.java.
мне удалось создать обходной путь, аналогичный тому, что использует Google Play Store. ссылка на оригинальный ответ
пожалуйста, найдите репозиторий 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.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();
}
});
}
}
любые проблемы с вышеизложенным дайте мне знать!
обновление 2: ТОНИРОВКА ОБХОДНОЙ ПУТЬ
как указано во многих dev notes PreferenceActivity
не поддерживает тонирование элементов, однако, используя несколько внутренних классов, вы можете достичь этого. То есть до тех пор, пока эти классы не будут удалены. (Работает с помощью поддержки appCompat-v7 v21.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:
совместимости приложений 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.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;
}
ВЛОЖЕННЫЕ ЭКРАНЫ ПРЕДПОЧТЕНИЙ
много людей возникают проблемы с включением панели инструментов во вложенные <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
:
<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>
не забывая добавить добавить библиотеку поддержки дизайна в качестве зависимости в :
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
я исследовал сообщенную перекрывающуюся проблему, и я не могу воспроизвести эту проблему.
полный код в использовании как выше приводится следующее:
если я чего-то не хватает, пожалуйста, дайте мне знать через этот РЕПО и я проведу расследование.
найдена реализация PreferenceFragment на основе фрагмента support-v4:
https://github.com/kolavar/android-support-v4-preferencefragment
Edit: я только что протестировал его и отлично работает!
интеграция PreferenceActivity
с ABC невозможно, по крайней мере для меня. Я попробовал две возможности, которые смог найти, но ни одна не сработала:
Вариант 1:
ActionBarPreferenceActivity
выходит PreferenceActivity
. Когда вы делаете это, вы ограничиваетесь ActionBarActivityDelegate.createDelegate(ActionBarActivity activity)
. Также вам нужно реализовать ActionBar.Callbacks
которая не работает
Вариант 2:
ActionBarPreferenceActivity
выходит ActionBarActivity
. Этот подход требует переписывания совершенно нового PreferenceActivity
, PreferenceManager
и может быть PreferenceFragment
что значит нужно доступ к скрытым классам, таким как com.android.internal.util.XmlUtils
Решение этого может прийти только от разработчиков Google, реализующих ActionBarWrapper
это можно добавить к любой деятельности.
Если вам действительно нужно предпочтение деятельности, мой совет сейчас ActionBarSherlock
.
однако, мне удалось его реализовать здесь.
История Вопроса:
ОП хочет знать, как мы можем положить MenuItem
s в ActionBar
of PreferenceActivity
для pre-Honeycomb, потому что библиотека поддержки Android имеет ошибку, которая не позволяет этому произойти.
Мое Решение:
я нашел гораздо более чистый способ, чем уже предлагалось, для достижения цели (и нашел его в Android Docs):
android:parentActivityName
имя класса логического родителя этот деятельность. Имя должно совпадать с именем класса дано атрибут android:name соответствующего элемента.
система считывает этот атрибут, чтобы определить, какое действие должно быть запускается при нажатии кнопки вверх на панели действий. Этот система также может использовать эту информацию для синтеза заднего стека действия с TaskStackBuilder.
для поддержки уровней API 4-16 вы также можете объявить родительскую активность с элементом, который указывает значение для "андроид.поддержка.PARENT_ACTIVITY". Например:
<activity android:name="com.example.app.ChildActivity" android:label="@string/title_child_activity" android:parentActivityName="com.example.myfirstapp.MainActivity" > <!-- Parent activity meta-data to support API level 4+ --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.app.MainActivity" /> </activity>
теперь сделайте то, что вы обычно делаете в своем onOptionsItemSelected()
. Поскольку он является частью Android Docs, он не имеет побочных эффектов.
удачи в кодировании. :)
обновление:
это решение больше не работает, если вы нацелены на леденец. Если вы используете AppCompat, этой ответ, что вы должны искать.
я смог получить android.app.Actionbar
С помощью getActionBar()
. Сначала он вернул значение null... затем я подошел к манифесту и сменил тему на:--5-->
android:theme="@style/Theme.AppCompat"
затем я снова смог получить actionbar. Я предполагаю, что это будет работать только для определенных уровней построения. Поэтому вы можете проверить номер сборки или проверить, является ли возвращаемое значение нулевым.
это будет хорошо для меня, потому что приложение, над которым я работаю, для ICS/4.0
+.
теперь официальный ответ на эту проблему был выпущен. Это поддержка предпочтений v7/v14 библиотека.
посмотреть как использовать библиотеку поддержки предпочтений v7/v14? для обсуждения того, как его использовать.