跟 ActionBarSherlock 不同,在 AppCompat 底下沒有對應 PreferenceActivityAppCompatPreferenceActivity,我們只能使用老舊的 PreferenceActivity。沒有加進可能是為了鼓勵使用 PreferenceFragment?確實的原因不知道,我們只能接受苦果。

自從 appcompat-v7 21.0 加進 Toolbar 的支援,要為 PreferenceActivity 加上 ActionBar 變得非常容易。雖然有人寫了相關的 library,不過當然是自己動手寫比較好玩啦。

沒加工的 PreferenceActivity 在 Lollipop 和 JellyBean 底下的模樣
在 AppCompat 底下沒加工的 PrefenenceActivity

PreferenceActivity 加上 Toolbar

SettingsActivity 的 layout 上加入 Toolbar

 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent">

      <android.support.v7.widget.Toolbar
                android:id="@+id/action_bar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:minHeight="?attr/actionBarSize" />

      <FrameLayout
                android:id="@+id/content_wrapper"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1" />

 </LinearLayout>

要設定 Toolbar 的 style,在 style.xml 加進 Theme.SettingsWidget.Toolbar,記得要在 AndroidManifest.xmlSettingsActivity 用上 Theme.Settings

 <?xml version="1.0" encoding="utf-8"?>
 <resources>

      <style name="Theme.Application" parent="@style/Theme.AppCompat" />

      <style name="Theme.Settings" parent="@style/Theme.Application">
           <item name="android:windowNoTitle">true</item>
           <item name="android:windowActionBar">false</item>

           <item name="toolbarStyle">@style/Widget.Toolbar</item>
      </style>

      <style name="Widget.Toolbar" parent="@style/Widget.AppCompat.Toolbar">
           <item name="android:background">?attr/colorPrimary</item>
           <item name="android:navigationIcon">?attr/homeAsUpIndicator</item>
           <item name="navigationIcon">?attr/homeAsUpIndicator</item>
      </style>

 </resources>

然後到 SettingsActivity

 import android.support.v7.widget.Toolbar;
 ...

 public class SettingsActivity extends PreferenceActivity {

      private Toolbar mActionBar;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);

           addPreferencesFromResource(R.xml.settings);
           //other preference initialization

           mActionBar.setTitle(getTitle());
      }

      @Override
      public void setContentView(int layoutResID) {
           ViewGroup contentView = (ViewGroup) LayoutInflater.from(this).inflate(
                     R.layout.settings_activity, new LinearLayout(this), false);

           mActionBar = (Toolbar) contentView.findViewById(R.id.action_bar);
           mActionBar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                     finish();
                }
           });

           ViewGroup contentWrapper = (ViewGroup) contentView.findViewById(R.id.content_wrapper);
           LayoutInflater.from(this).inflate(layoutResID, contentWrapper, true);

           getWindow().setContentView(contentView);
      }
 }

主要是在 setContentView() 設定 Toolbar,為它加入對應的功能 (按 icon 就 finished() 和設定 title)

這樣便完成了。

加了 Toolbar 的 PreferenceActivity
加上 Toolbar 的 PreferenceActivity

顏色問題

但好像有問題!

留意到 Checkbox 的底色嗎?太黑了,完全看不清!

這是 themeTheme.AppCompat,在 Theme.AppCompat 底下, Checkbox 的顏色是黑色的。

那麼要改 Checkbox 的顏色嗎? 好像不簡單呀。

幸好, appcompat support-v7 v21.0.3 新增了 TintCheckBox,工作又變得更簡單。

Override SettingsActivitypublic View onCreateView(String name, Context context, AttributeSet attrs):

@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;
}

這樣所有 input 都會使用主題的顏色,整個 PreferenceActivity 的外觀在 Lollipop 或 JellyBean 都是一樣了。

完美的 PreferenceActivity
完美的 PreferenceActivity

相關連結: