Appcompat v21 Material Support

Google 釋出了 v21 的 Appcompat,

讓 Material Design 的某些 Widget 可以向下相容,

並且將 Actionbar 替換為 Toolbar,

這是一個非常大的變動,

以往 Actionbar 跟 整個 Layout 是沒有關係的,

但是在 Material Design 中,Toolbar 就是 Layout 的一部份,

這樣做是為了讓 Toolbar 能夠更容易與其他的 View 做交互,

例如 Toolbar 的顯示與隱藏,以及動畫…等。

#Setup

1
2
3
4
dependencies {  
...
compile "com.android.support:appcompat-v7:21.0.0"
}

小小抱怨一下,Gradle Build 好慢啊!

#第一次整合

最近對於 2.3 向下相容的需求降低很多,

相信應該很多人的新專案不會加入 appcompat,

不過為了 Material Design,

必須做以下改動,

  • 所有的 Activity 都必須繼承 ActionBarActivity
  • App 的 Theme 必須設定為Theme.AppCompat
  • Toolbar 上的 Menu Item Context 必須使用getSupportActionBar().getThemedContext()
  • 使用MenuItemCompat取代所有操作 Menu Item 的 API

#專案已經在使用 Appcompat

如果專案已經在使用 Appcompat,

那應該在style.xml會有 v14 的資料夾,

因為 Actionbar 已經被 Toolbar 取代,

所有內建的 Actionbar 都沒有用了,

因此可以把 v14 直接拿掉了,

對於大部份的 App 來說,

目前應該只需要一個 Theme,

values/themes.xml

1
2
3
4
5
6
7
8
9
10
<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">  
<!-- Here we setting appcompats actionBarStyle -->
<item name="actionBarStyle">@style/MyActionBarStyle</item>

<!-- ...and here we setting appcompat’s color theming attrs -->
<item name="colorPrimary">@color/my_awesome_red</item>
<item name="colorPrimaryDark">@color/my_awesome_darker_red</item>

<!-- The rest of your attributes -->
</style>

#主題

為了符合 Material Design,

必須選定一些主題色,

以下是範例:

values/themes.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">  
<!-- colorPrimary is used for the default action bar background -->
<item name="colorPrimary">@color/my_awesome_color</item>

<!-- colorPrimaryDark is used for the status bar -->
<item name="colorPrimaryDark">@color/my_awesome_darker_color</item>

<!-- colorAccent is used as the default value for colorControlActivated
which is used to tint widgets -->
<item name="colorAccent">@color/accent</item>

<!-- You can also set colorControlNormal, colorControlActivated
colorControlHighlight & colorSwitchThumbNormal. -->
</style>

#Widget 配色

在設定好主題色以後,

以下的 Widget 都會自動套用主題色,

  • Toolbar Item
  • EditText
  • Spinner
  • CheckBox
  • RadioButton
  • SwitchCompat
  • CheckedTextView

#Widget

##Toolbar

android.support.v7.widget.Toolbar

Toolbar 有兩種用途,

  • Actionbar:取代 Actionbar。
  • 單獨使用:有些場合,Actionbar 限制太多,例如你需要多個 Actionbar。

###Actionbar

如果要當成 Actionbar 使用,你必須在layout.xml中加入 Toolbar,

1
2
3
4
5
6
7
<android.support.v7.widget.Toolbar  
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/my_awesome_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary" />

你可以放在任何位置,

然後在 Activity 或 Fragment 中設定,

1
2
3
4
5
6
7
8
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);

Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(toolbar);
}

然後你就可以呼叫原本屬於 Actionbar 的 API 了。

###單獨使用

把它當成一般的 View 使用就好,

簡單的範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);

Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);

// Set an OnMenuItemClickListener to handle menu item clicks
toolbar.setOnMenuItemClickListener(
new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// Handle the menu item
return true;
}
});

// Inflate a menu to be displayed in the toolbar
toolbar.inflateMenu(R.menu.your_toolbar_menu);
}

更多方法請參考文件

###Styling

如果你想像以前那樣設定 Actionbar 的樣式,

你可以使用app:theme

1
2
3
4
5
<android.support.v7.widget.Toolbar  
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
app:theme="@style/ThemeOverlay.AppCompat.ActionBar" />

懷念以前的 DarkActionbar?

1
2
3
4
5
6
<android.support.v7.widget.Toolbar  
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="@dimen/triple_height_toolbar"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

##總結

這次 Actionbar 整個被拔掉,

也是蠻嚇人的,

我還想說為什麼新的專案都沒 Actionbar,

希望這篇文章可以幫助大家快速上手!

##附註

這篇文章的內容與程式碼皆轉載至 Chris Banes 的部落格

他是一位著名的開發者,他的 Github 上有許多非常有名的套件,

非常推薦追蹤!

2014/10/22 Update:

這篇文章有更詳細的程式碼教學。