안드로이드 액션바(ActionBar) 기본 사용법. (Android ActionBar)
1. 안드로이드 액션바(ActionBar)와 앱바(App Bar)
액션바(ActionBar)는 앱바(App Bar)를 만들 때 사용하는 위젯 중 하나입니다. 그리고 앱바(App Bar)는 액티비티의 제목과 앱 레벨의 탐색(navigation)을 위한 액션 버튼 또는 여러 종류의 위젯으로 구성된 액티비티의 기본 도구모음(Toolbar)을 말합니다.
통상적으로 안드로이드에서 앱바(App Bar)와 액션바(ActionBar)는 같은 의미로 사용됩니다. 초기 머티리얼 디자인에서 앱바(App Bar) 레이아웃 구조가 ActionBar
위젯을 통해 구현되었기 때문에 액션바(ActionBar)는 곧 앱바(App Bar)를 의미하죠.
그런데 안드로이드 SDK가 지속적인 발전과 수정을 거쳐옴에 따라 앱바(App Bar)를 만드는 방법 또한 변화되었습니다. 즉, 앱바(App Bar)를 만들기 위해 반드시 ActionBar
위젯을 사용할 필요가 없어진 것입니다. 특히, 최근에는 v7 AppCompat 지원 라이브러리에 포함된 Toolbar
를 사용하여 앱바(App Bar)를 구현합니다. 지원 라이브러리의 Toolbar
를 사용하면, 다양한 종류의 기기에서 일관적인 앱바(App Bar) 동작을 보장할 수 있습니다.
하지만 v7 AppCompat 지원 라이브러리의 Toolbar
를 사용하는 방법을 설명하기에 앞서, ActionBar
위젯으로 앱바(App Bar)를 만드는 방법을 먼저 설명하는 것이 흐름상 적절하다고 생각합니다. 기본적으로 액티비티 내부에서 앱바(App Bar)가 ActionBar
위젯으로 관리되고, 앱바(App Bar)를 제어하는 기능들이 ActionBar
클래스를 통해 제공되기 때문입니다.
1.1 앱바(App Bar)의 레이아웃 구조.
앱바(App Bar)는 기본적으로 화면을 왼쪽/오른쪽 두 부분으로 나눈 다음, 왼쪽에는 탐색에 사용되는 "Nav icon"과 현재 컨텐츠의 제목을 출력하는 "Title"을 표시합니다. 그리고 오른쪽에는 앱의 주요 액션을 버튼 형태로 제공하는 "Action", 주요 액션에 표시되지 않은 기능과 메뉴 아이템들을 보여주기 위한 "Overflow menu" 아이콘이 표시됩니다.
2. 액션바(ActionBar) 사용법.
안드로이드 3.0(API Level 11)부터, 기본 테마를 사용하는 모든 액티비티에서 ActionBar
가 앱바(App Bar)로 사용됩니다. 앱바(App Bar)는 액티비티에 기본으로 포함된 요소이기 때문에, 레이아웃 리소스 XML 파일에 ActionBar
위젯을 별도로 추가하지 않아도, 간단한 설정만으로 액티비티에서 앱바(AppBar)가 표시되도록 만들 수 있습니다.
2.1 앱바(App Bar) 표시하기.
앱바(App Bar)가 화면에 표시되도록 만들기 위해서는, 액티비티가 앱바(App Bar)를 표시하는 테마를 사용하도록 설정하기만 하면 됩니다. 그리고 안드로이드 3.0(API Level 11)부터는 기본 테마들이 앱바(App Bar)를 제공하기 때문에, 아래의 코드와 같이, 앱의 테마 설정을 기본 테마 중 하나로 지정하면, 앱바(App Bar)를 사용하도록 만들 수 있습니다.
"/manifests/AndroidManifest.xml" - 앱 프로젝트의 테마 설정.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ppottasoft.actionbarexample">
<application
...
android:theme="@style/AppTheme">
...
</application>
</manifest>
"/res/values/styles.xml" - 앱바(App Bar)가 포함된 테마 지정.
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
...
</style>
</resources>
그런데 어떤 경우에는 앱바(App Bar)를 사용하지 않게 만들고 싶을 때도 있습니다. 이를 위해서는 액티비티에 액션바를 지원하지 않는 테마를 지정하면 됩니다. 바로 "NoActionBar" 테마입니다.
"/res/values/styles.xml" - 앱바(App Bar)를 사용하지 않는 테마 지정.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
2.2 앱바(App Bar) 액세스하기.
적절한 테마 설정으로 앱바(App Bar)가 화면에 표시되도록 만들고 나면, 액티비티에서 getSupportActionBar() 함수를 호출하여 앱바(App Bar)에 대한 참조를 획득할 수 있습니다. 이 때, getSupportActionBar() 함수에서 리턴되는 타입은 ActionBar
(android.support.v7.app.ActionBar) 클래스입니다.
ActionBar ab = getSupportActionBar() ;
getSupportActionBar() 함수를 통해 액티비티의 ActionBar
객체에 대한 참조를 획득하고나면, ActionBar
클래스에서 제공하는 함수를 통해 앱바(App Bar)의 표시항목을 설정하거나 앱바(App Bar)가 제공하는 여러 기능을 사용할 수 있습니다.
2.3 앱바(App Bar) 제목 텍스트 변경하기.
앱바(App Bar)에 표시되는 제목 텍스트에는 기본적으로 앱의 이름, 즉, AndroidManifest.xml 파일의 "android:label"에 지정된 문자열이 표시됩니다. 그러므로 앱바(App Bar)의 title 영역에 표시되는 텍스트를 변경하기 위해서는 "android:label"의 값을 수정하면 됩니다.
"/manifests/AndroidManifest.xml" - 앱바(App Bar)에 표시되는 제목 텍스트.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ppottasoft.actionbarexample">
<application
...
android:label="@string/app_name"
...
</application>
</manifest>
"/res/values/strings.xml" - 앱바(App Bar) 제목 텍스트 변경.
<resources>
<string name="app_name">Changing ActionBar Text</string>
</resources>
하지만 앱바(App Bar)의 제목 텍스트를 앱의 이름으로 고정시키는 경우는 거의 없죠. 대신, 현재 수행중인 작업에 따라 앱바(App Bar)의 제목 텍스트를 바꿔가면서 표시하는 경우가 많습니다. 이렇게 앱바(App Bar)의 제목 텍스트를 임의의 문자열로 지정하기 위해서는 setTitle() 함수를 사용합니다.
ActionBar ab = getSupportActionBar() ;
ab.setTitle("ActionBar Title by setTitle()") ;
2.4 앱바(App Bar)의 색상 변경하기.
앱바(App Bar)가 화면에 표시될 때는 액티비티의 테마에 따라 그 색상이 결정됩니다. 그러므로 앱바(App Bar)의 색상을 변경하려면, 테마에 설정된 색상 값을 바꿔주면 됩니다.
프로젝트의 "AndroidMenifest.xml" 파일의 내용을 보면 "android:theme"에 앱의 테마가 지정된 것을 확인할 수 있습니다. 그런데 "android:theme"에는 시스템에서 제공하는 테마가 바로 사용되지 않고, 스타일(Style) 리소스의 "AppTheme"가 지정되어 있습니다.
...
<application
...
android:theme="@style/AppTheme">
...
</application>
"/res/values/styles.xml" 파일을 열어보면 "AppTheme"에 대한 내용을 확인할 수 있는데요. 소스의 내용은, "AppTheme"가 "Theme.AppCompat.Light.DarkActionBar"를 상속받았으며, "colorPrimary", "colorPrimaryDark", "colorAccent"를 커스터마이징하고 있다는 내용입니다.
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
바로 여기서, "AppTheme"의 설정 값을 사용하여 앱바(App Bar)의 색상을 변경할 수 있습니다. 그럼 이제 테마 설정 값이 어떤 화면에 영향을 주는지 알아야 하는데요. 아래 그림을 통해 테마 설정 값과 화면 요소의 관계를 확인할 수 있습니다. (좀 더 자세한 내용은 https://developer.android.com/training/material/theme.html?hl=ko#ColorPalette 페이지를 참고하세요.)
자, 이제 앱바(App Bar)의 각 요소에 대한 색상을 어떻게 변경해줘야 하는지 아시겠죠? 아래 예제는 오렌지(Orange) 색상으로 앱바(App Bar)의 색을 변경한 예제입니다.
"/res/values/colors.xml" - 앱 테마 색상 변경.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#FF9800</color>
<color name="colorPrimaryDark">#E65100</color>
<color name="colorAccent">#FF4081</color>
</resources>
https://developer.android.com/training/material/theme.html?hl=ko#ColorPalette 의 그림을 보면, "textColorPrimary"를 사용하여 앱바(App Bar) 제목 텍스트의 색상을 변경하는 것으로 나와 있습니다. 하지만 실제로 "textColorPrimary"를 사용하면, "Error:(312, 21) No resource found that matches the given name: attr 'textColorPrimary'."라는 에러가 발생합니다.
2.5 앱바(App Bar)에 액션(Action) 추가하기
2.5.1 앱바(App Bar) 액션을 위한 메뉴 리소스 XML 작성하기.
앱바(App Bar)에는 사용자 액션을 위한 버튼을 추가할 수 있습니다. 통상적으로 이 버튼을 액션 버튼(Action Button) 또는, 간단히 액션(Action)이라고 부르는데, 앱의 현재 상황에서 가장 중요한 기능들을, 이 액션 버튼이 눌려졌을 때 실행되도록 만듭니다.
앱바(App Bar)는 가로 방향 공간에 대한 제한으로 인해 한정된 수의 액션 버튼만 표시할 수 있습니다. 특히, 화면이 작은 스마트폰의 경우에는 그 갯수가 더욱 제한적일 수 밖에 없죠. 그런데 만약, 앱바(App Bar)에 표시할 수 있는 갯수보다 많은 수의 액션(Action)이 정의되면 어떻게 될까요? 분명, 중요하다고 판단된 액션(Action)이므로 어떤 형태로든 기능을 사용할 수 있게 만들어줘야 할텐데 말이죠.
이런 경우, 앱바(App Bar)에 버튼으로 표시되지 못한 액션들은, 앱바(App Bar) 설정에 따라 오버플로우 메뉴(Overflow Menu)에 추가됩니다. 물론, 처음부터 액션(Action)이 아닌 오버플로우 메뉴에 고정적으로 표시되게 만들 수도 있습니다.
액션 버튼과 오버플로우 메뉴에 추가되는 액션은 메뉴 리소스 XML에 정의합니다. 메뉴 리소스 XML은 "/res/menu/"에 생성하는데, xml 파일을 만든 다음, "<menu>" 요소 아래에 액션 당 하나의 "<item>"을 사용하여 앱바(App Bar)에 표시될 액션을 추가합니다.
아래 코드는 메뉴 리소스 XML에 "actionbar_actions.xml"이라는 파일을 생성한 다음, 액션을 정의한 예제입니다.
"/res/menu/actionbar_actions.xml" - 앱바에 액션 추가하기.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_search"
android:icon="@drawable/ic_search_white_48dp"
android:title="Search"
app:showAsAction="ifRoom"/>
<item
... />
</menu>
메뉴 리소스 XML에서 액션을 정의하기 위해 사용되는 "<item>" 요소의 속성들은 그 의미를 비교적 직관적으로 파악할 수 있습니다. 사용자에 의해 액션이 실행될 때 이벤트 핸들러에서 액션 식별에 사용되는 "id", 앱바(App Bar)의 액션 버튼에 표시될 Drawable 리소스를 지정하기 위한 "icon", 그리고 액션 또는 오버플로우 메뉴에 표시될 텍스트를 의미하는 "title". 이와 같이, 속성의 이름만으로도 그 용도를 쉽게 파악할 수가 있죠.
그런데 마지막 속성은 그 의미가 쉽게 와닿지 않습니다. "showAsAction", 어떤 역할을 하는 속성일까요?
"showAsAction" 속성은, 그 이름에 포함된 단어가 의미하듯, 아이템을 "액션으로 보여줄 때"의 옵션을 나타냅니다. 즉, 지정된 값에 따라 아이템을 "어떻게" 표시할지가 결정되는 것이죠. 먼저, "showAsAction"에 사용할 수 있는 값들은 어떤 것들이 있는지 한번 볼까요? 아래 표를 보시죠.
showAsAction 값 | 의미 |
---|---|
always | 아이템을 항상(always) 앱바(App Bar)의 액션으로 표시. never와 ifRoom보다 우선되며, 공간이 없으면 표시되지 않음. |
never | 아이템을 앱바(App Bar)의 액션으로 표시하지 않고(never) 오버플로우 메뉴에 바로 표시. |
ifRoom | 만약 공간이 있다면(ifRoom), 앱바(App Bar)의 액션으로 표시하고, 공간이 없다면 오버플로우 메뉴에 표시. |
withText | 아이템을 앱바(App Bar)의 액션으로 표시할 때 텍스트와 같이(withText) 표시. 단, 아이콘과 텍스트를 같이 표시할 공간이 있는 경우에만 텍스트 표시. |
collapseActionView | 아이템에 커스텀 액션 뷰가 지정된 경우, 축소된 형태로 표시. |
지정된 값을 속성 이름의 뒤에 붙여보면 그 의미를 좀 더 쉽게 이해할 수 있습니다. "show as action always", "show as action with text" 처럼 말이죠.
showAsAction 속성 값에 따른 표시 결과는 아래 그림을 통해 확인할 수 있습니다.
"collapseActionView" 값에 대한 내용은, 그 설명이 조금 길어질 수 있기 때문에, 다른 글을 통해 설명하겠습니다.
2.5.2 메뉴 리소스 XML을 앱바(App Bar)에 표시하기.
원하는 구성으로 메뉴 리소스 XML을 작성했다면, 작성한 메뉴 리소스 XML이 앱바(App Bar)에서 사용되도록 만들어야 합니다. 이는 액티비티의 onCreateOptionsMenu() 함수를 오버라이딩한 다음, 앞서 작성한 메뉴 리소스 XML을 inflate함으로써 이루어집니다. 음, 앱바(App Bar)를 설명하는데, 갑자기 웬 "OptionsMenu"가 나올까요?
안드로이드에서 "옵션 메뉴(Options Menu)"는 액티비티의 기본 메뉴를 의미합니다. 액티비티가 실행된 후, 현재 액티비티 컨텍스트와 관련된 작업(예. Search, Settings) 등이 바로 이 "옵션 메뉴(Options Menu)"에 표시되는 것이죠.
이전 안드로이드 버전 2.3.x(API Level 10) 이하에서는 사용자가 "Menu" 버튼을 눌렀을 때 별도의 메뉴 항목으로 "옵션 메뉴(Options Menu)"가 표시되었습니다. 하지만 안드로이드 버전 3.0(API Level 11) 이상부터는 "옵션 메뉴(Options Menu)" 항목이 앱바(App Bar)에 표시되도록 바뀌었죠. 그래서 onCreateOptionsMenu() 함수가 앱바(App Bar)에 메뉴 리소스 XML을 표시하는데 사용되는 것입니다.
onCreateOptionsMenu() 함수에서 메뉴 리소스 XML을 앱바(App Bar)에 표시하는 코드는 아래와 같습니다.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.actionbar_actions, menu) ;
return true ;
}
참고로, 작성된 메뉴 아이템이 표시되도록 만드려면, onCreateOptionsMenu() 함수가 반드시 true를 리턴해야 합니다. false를 리턴하면, 메뉴가 표시되지 않습니다.
2.6 앱바(App Bar) 액션 이벤트 처리하기.
앱바(App Bar)에서 액션이 클릭되었을 때의 이벤트는 액티비티의 onOptionsItemSelected() 함수에서 처리합니다. 앞서, 앱바(App Bar)가 액티비티의 "옵션 메뉴(Options Menu)" 역할을 수행하기 때문에 onCreateOptionsMenu() 함수에서 메뉴를 초기화했듯이, 메뉴 리소스 XML에서 "<item>"으로 정의된 액션이 선택되면 onOptionsItemSelected() 함수가 호출되는 것입니다.
어떤 액션이 선택되었는지는 onOptionsItemSelected() 함수의 파라미터인 MenuItem의 getItemId() 함수를 통해 식별할 수 있습니다. getItemId() 함수를 통해 리턴되는 값은, 메뉴 리소스 XML의 "<item>"요소에서 "id" 속성에 지정된 값입니다.
앱바(App Bar) 액션 이벤트 처리하기.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_search :
// TODO : process the click event for action_search item.
return true ;
// ...
// ...
default :
return super.onOptionsItemSelected(item) ;
}
}
onOptionsItemSelected() 함수에서 선택된 아이템에 대한 이벤트를 정상적으로 처리했다면, 그 결과 값을 true로 리턴해야 합니다. 하지만 식별된 id가 여기서 처리될 아이템이 아니라면(switch문의 default), super.onOptionsItemSelected() 함수 실행 결과를 리턴하여 기본적인 메뉴 처리가 수행되도록 만들어줘야 합니다. (기본적으로 false를 리턴.)
2.7 앱바(App Bar)에 앱 아이콘 표시하기.
기본적으로 앱바(App Bar)에는 앱 아이콘이 표시되지 않습니다. 물론, 최근 안드로이드의 앱바(App Bar)에서는 앱 아이콘 대신 네비게이션 아이콘을 주로 사용하지만, 취향에 따라 앱 아이콘을 지정하고싶은 경우도 있겠죠.
앱바(App Bar)에 아이콘을 표시하기 위해서는 ActionBar 클래스의 setIcon() 또는 setLogo() 함수를 사용하여 아이콘으로 표시할 이미지를 지정하면 됩니다. 그런데 한 가지 주의할 점이 있습니다. AppCompat를 사용하는 경우, 단순히 setIcon() 또는 setLogo() 함수를 호출하는 것만으로는 아이콘이 표시되지는 않는다는 것이죠. setDisplayUseLogoEnabled() 함수와 setDisplayShowHomeEnabled() 함수를 호출해야만 앱바(App Bar)에 아이콘이 정상적으로 표시되는 것을 확인할 수 있습니다.
앱바(App Bar)에 아이콘 표시하기.
ActionBar ab = getSupportActionBar() ;
ab.setIcon(R.drawable.app_icon) ;
ab.setDisplayUseLogoEnabled(true) ;
ab.setDisplayShowHomeEnabled(true) ;
2.8 앱바(App Bar) 감추기 및 보이기
앱에서 앱바(App Bar)를 사용할 것인지 여부는 앱에 지정한 테마가 앱바(App Bar)를 지원하는 테마인지 아닌지에 따라 결정된다고 설명했죠. 앞서 테마 이름에 ".NoActionBar"가 포함된 경우, 앱바(App Bar)를 사용하지 않는 테마라고 설명했습니다. 하지만 조금 더 자세하게 들여다보자면, 사실, 테마의 사용 여부는 테마의 이름에 의해 결정되는 것이 아니고, 테마에 지정된 "windowActionBar"라는 플래그의 값에 따라 결정됩니다. 앱바(App Bar)를 사용하는 경우 true, 그렇지 않으면 false 값을 지정하는 것이죠. ".NoActionBar" 테마도 내부적으로는 "windowActionBar" 플래그가 false 값으로 지정된 테마일 뿐입니다.
그러므로 ".NoActionBar"라는 이름이 포함된 테마 대신, 아래와 같이 "windowActionBar" 플래그 값을 false로 지정하여도 앱바(App Bar)가 표시되지 않게 만들 수 있습니다. 참고로, AppCompat에서는 "windowActionBar" 플래그만 사용하는 경우, "AppCompat does not support the current theme features: { windowActionBar: false, ... }"라는 에러가 발생합니다. 이런 경우 "windowNoTitle" 플래그를 같이 사용하면 됩니다.
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
...
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
그런데 ".NoActionBar" 테마를 사용하거나 "windowActionBar" 플래그를 사용하는 방법은 앱바(App Bar)가 앱에서 원천적으로 표시되지 않도록 만듭니다. 단순히 보이고 말고의 문제가 아니라, 사용 자체를 하지 않도록 만든다는 것이죠. 하지만 어떤 경우에는, 기본적으로 앱바(App Bar)를 사용하되, 상황에 따라 앱바(App Bar)가 보이지 않도록 만들고 싶은 경우가 있을 것입니다. 이런 경우는 어떻게 해야 할까요?
방법은 매우 간단합니다. getSupportActionBar()를 통해 획득한 ActionBar 클래스 객체의 show(), hide() 함수를 사용하여 앱바(App Bar)를 보이게 만들거나 감출 수 있습니다.
앱바(App Bar) 보이기 또는 감추기.
ActionBar ab = getSupportActionBar() ;
ab.show() ; // 앱바(App Bar) 보이기.
ab.hide() ; // 앱바(App Bar) 감추기.
3. 참고
- 머티리얼 App bar에 대한 레이아웃 구조
- [App bar]을 참고하세요.
- 안드로이드 개발 API 가이드. 메뉴 리소스.
- [Menu Resource]을 참고하세요.
- 안드로이드 개발 API 가이드. 옵션 메뉴 만들기.
- [옵션 메뉴 만들기]을 참고하세요.
- 안드로이드 개발 참조문서. Activity.onCreateOptionsMenu().
- [Activity.onCreateOptionsMenu()]을 참고하세요.
- 안드로이드 개발 참조문서. Activity.onOptionsItemSelected().
- [Activity.onOptionsItemSelected() "[https://developer.android.com/reference/android/app/Activity.html?hl=ko#onOptionsItemSelected(android.view.MenuItem))] 페이지로 이동합니다.")]을 참고하세요.
.END.