ActionBar в PreferenceActivity

Example: Android Market

В моем приложении я использую образец совместимости с Action Bar от Google (расположенный в <sdk>/samples/android-<version>/ActionBarCompat), который отлично работает. Единственная проблема, с которой я сталкиваюсь, - это применить это к моему PreferenceActivity, чтобы получить экран, подобный настройкам в Android Market (см. Рисунок).

Чтобы заполнить ActionBar значками, каждый Activity должен расширить класс ActionBarActivity. Проблема в том, что мой Activity уже расширяет PreferenceActivity, а в Java-классах не может распространяться более одного класса.

Должен быть способ получить ActionBar вместе с PreferenceScreen. Я был бы рад, если бы кто-нибудь мог предложить решение этой общей проблемы.

PS: Решение, подобное в Как добавить кнопку в PreferenceScreen, не подходит, потому что ActionBar на самом деле является строкой заголовка, и это больше похоже на Java чем макет.

Ответ 1

Изменить: Мой ответ ниже довольно взломан, и кажется, что он устарел (для Android 3.0). Посмотрите на другие ответы для менее хакерских и более современных решений. ~ pyko 2014- 09-01


Мне удалось заставить его работать - не уверен, что это самое приятное/чистое решение, но оно работает.

Пришлось внести следующие изменения:

  • Сделайте копию ActionBarActivity и добавьте новый класс PreferenceActivity

    public abstract class ActionBarPreferenceActivity extends PreferenceActivity {
        // contents exactly the same as 'ActionBarActivity'
    }
    
  • Немного измените onCreate() в ActionBarHelperBase.java - сделайте специальный случай для PreferenceActivity классов

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // If the activity is a PreferenceActivity, don't make the request
        if (!(mActivity instanceof PreferenceActivity)) {
            mActivity.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        }
    
  • Расширьте свой класс PreferenceActivity и добавьте запрос для FEATURE_CUSTOM_TITLE до, который вы вызываете super.onCreate()

    public class MyPreferenceActivity extends ActionBarPreferenceActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); // add this line
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);
            // etc etc
        }
    
        // etc etc
    }
    

Насколько я могу судить, необходимы изменения 2 и 3, потому что для PreferenceActivity:

"Как только вы вызовете super.onCreate(), будет создана группа ViewGroup, и поэтому вам не разрешено изменять параметры окна". (см. комментарий Оливера к ответу)

Я предполагаю, что порядок работы компонентов в действиях PreferenceActivity отличается от обычных действий Activity.

Ответ 2

Если вы хотите попробовать реализацию PreferenceFragment на основе фрагмента поддержки-v4:

https://github.com/kolavar/android-support-v4-preferencefragment

Я использую его сам, и это не очень помогает превратить PreferenceActivity в PreferenceFragment.

Ответ 3

Можете ли вы просто клонировать код для ActionBarActivity и изменить "extends Activity" на "extends PreferenceActivity"? Затем расширьте свой новый класс вместо ActionBarActivity.

Из всех приложений Google, которые я видел, кажется, необычно вводить кнопки в панели действий PreferenceActivity. Если вы не нажимаете на него кнопки, вы можете просто использовать ресурс альтернативного стиля значений-v11, чтобы показать голографическую тему, и установить этот стиль в манифесте для своей PreferenceActivity.

Ответ 5

Я хотел бы поблагодарить @pyko за отличный ответ, но у него есть проблема, что он не будет работать хорошо на HoneyComb и выше. хорошо, вы можете взломать способ получить его, как @AndroidDev сказал;  Но @pyko собирается загрязнить класс ActionBarHelperBase, а @AndroidDev не очень прозрачен. Лучший способ - создать ActionBarActivityPreferences, который распространяется из PreferenceActivity; и в методе onCreate измените порядок вызова родительского метода:

@Override
protected void onCreate(Bundle savedInstanceState) {
    //IMPORTATNT: MAKE SURE actionBarHelper called before super;
    //as super oncreate of prefenceactivity is actuallying setting the content view
    mActionBarHelper.onCreate(savedInstanceState);
    super.onCreate(savedInstanceState);
}

зачем вызывается "mActionBarHelper.onCreate(savedInstanceState)"; перед 'super.onCreate(savedInstanceState);', потому что super (т.е. PreferenceActivity) на самом деле устанавливает представление содержимого в свой метод onCreate, что вызовет сбой ( "requestFeature() должен быть вызван перед добавлением контента" ). Так что вам нужно сделать это, чтобы поменять порядок, сделать sure 'mActionBarHelper.onCreate(savedInstanceState);' вызывается перед супер.  Таким образом, нам не нужно загрязнять "ActionBarHelperBase", но мы сохраняем SettingActivity очень чистым, потому что мы инкапсулируем сложную деталь в "ActionBarActivityPreferences" и bang!

Ответ 6

Вы можете легко добавить панель действий в действие предпочтения с помощью следующих изменений:

В AndroidManifest.xml:

<activity
        android:name=".activity.SettingsActivity"
        android:theme="@style/SettingsTheme"
        android:label="Settings"/>

В v21/styles.xml

<style name="SettingsTheme" parent="@android:style/Theme.Material.Light.DarkActionBar">
    <item name="android:colorPrimary">@color/colorPrimary</item>
    <item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
</style>

В v14/styles.xml для поддержки Back API:

<style name="SettingsTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
    <item name="android:actionBarStyle">@style/ActionBar.V14.Movie.NoTitle</item>
</style>

Ответ 7

Спасибо, просто обновление, вам нужно добавить оператор if перед строкой Custom Title для поддержки HoneyComb и выше.

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
   requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); 

Ответ 8

Вы можете получить ActionBarSherlock lib и позволить коду расширять SherlockPreference;