안드로이드 탭 기본 사용법. [TabWidget, TabHost, TabSpec] (Android Tab)
1. 안드로이드 탭(Tab) 위젯
탭(Tab) 위젯은 다양한 UI 프레임워크에서 기본적으로 제공되는 UI 구성요소입니다. 화면에 표시되는 기본 형태는 프레임워크에 따라 차이가 있지만, "여러 페이지로 구성된 UI 레이아웃을 화면의 동일한 영역에 번갈아 표시할 때 사용"하는 것과, "각 페이지의 전환이 탭(Tab) 위젯 안에 있는 탭(버튼 역할)을 통해 수행"된다는 공통점이 있습니다.
안드로이드에도 탭(Tab) 위젯을 위한 UI 요소가 제공됩니다. 특히 모바일 기기처럼 작은 화면에서는 여러 페이지를 하나의 영역에 번갈아 가며 표시할 수 있으므로 공간 효율성을 높일 수 있는 장점이 있죠.
2. TabWidget과 TabHost 그리고 FrameLayout.
2.1 TabWidget 클래스 (android.widget.TabWidget)
안드로이드에서 제공되는 탭(Tab) 위젯 기능을 위한 클래스는 TabWidget
(android.widget.TabWidget) 클래스입니다.
TabWidget
클래스에는 탭 위젯 안에 표시되는 탭을 추가하거나, 수정, 삭제하기 위한 함수들이 정의되어 있으며, 해당 함수를 통해 추가된 탭은 탭 위젯의 영역 내에 가로 방향으로 나란히 표시됩니다.
그런데 막상 TabWidget
클래스를 사용하여 탭 위젯 기능을 구현하려고 하면, TabWidget
클래스 단독으로는 탭 기능 구현이 불가능하다는 사실을 발견할 수 있습니다. 그 이유는 바로, 탭 위젯 내부의 탭이 눌려질 때 표시되는 내용을 위한 페이지 화면 때문입니다.
안드로이드의 탭 위젯 구현 방식은 다른 UI 프레임워크와는 조금 다르게, 버튼 역할을 하는 탭(Tab)과 각 탭이 눌려졌을 때 표시될 내용(Content)을 한번에 지정하게끔 만들어져 있습니다. 즉, 탭을 관리하는 TabWidget
에 더하여, 내용(Content)으로 표시될 페이지 뷰(View)까지 관리하는 추가적인 요소가 필요하다는 것이죠.
이렇게 TabWidget
과 TabWidget
의 탭 선택에 따라 표시될 내용(Content)을 관리하는 호스트(Host:주인,관리자) 역할을 수행하는 클래스는 바로 TabHost
(android.widget.TabHost) 클래스입니다.
2.2 TabHost 클래스 (android.widget.TabHost)
TabHost 클래스는 앞서 설명한대로, 탭 버튼을 표시하는 TabWidget
과, 각 탭의 선택에 따라 표시될 페이지 화면을 관리하는 클래스입니다. 안드로이드 탭(Tab) 기능과 관련된 모든 내용을 포함하고 있는 컨테이너(Container) 역할을 수행하는 것이죠.
TabWidget
외에, TabHost
가 관리하는 페이지 화면은 반드시 FrameLayout
을 사용하여 구성해야 합니다. 이는 TabWidget
의 탭 선택에 따라 표시될 페이지 화면이 이전 페이지를 완벽히 덮는 형태로 표시되어야 하는, 지극히 당연한 이유 때문이죠.
TabHost
에 TabWidget
과 FrameLayout
이 배치되는 기본 구조는 아래와 같습니다.
그리고 TabHost
를 구성하는 레이아웃 리소스 XML의 기본 구조는 아래와 같이 작성됩니다.
<TabHost
...>
<LinearLayout
...
android:orientation="vertical">
<TabWidget
...
android:id="@android:id/tabs" />
<FrameLayout
...
android:id="@android:id/tabcontent">
<!-- TAB CONTENT 1 -->
...
<!-- TAB CONTENT 2 -->
...
<!-- TAB CONTENT 2 -->
...
</FrameLayout>
</LinearLayout>
</TabHost>
위의 레이아웃 리소스 XML 코드 중 TabHost
에 TabWidget
과 FrameLayout
을 추가할 때, LinearLayout
을 사용한 것에 주의하세요. 클래스 계층 관계를 보면 알겠지만, TabHost
는 FrameLayout
에서 상속된, 뷰 그룹으로써의 역할을 수행하는 위젯입니다.
그래서 TabHost
의 자식으로 뷰그룹(LinearLayout과 같은)을 사용하지 않고 TabWidget
과 FrameLayout
을 배치하면, 일반적인 상황에서 FrameLayout
을 사용할 때 처럼, 추가된 자식들(Children)이 중첩되어버리는 문제가 발생하죠. 이를 해결하기 위해 LinearLayout
사용한 것입니다.
2.3 TabHost 사용 제약 사항.
앞서 설명한 내용을 포함하여 TabHost
를 사용할 때 주의해야 할 몇 가지 제약 사항이 있습니다. 주로 레이아웃 리소스 XML과 관련된 내용인데요. 정리하자면 다음과 같습니다.
TabHost
는FrameLayout
을 상속하였으므로, 뷰그룹을 사용하여 자식(Children)들을 배치해야 합니다. (예제에서는LinearLayout
사용)TabWidget
의 id 속성에는 반드시 "@android:id/tabs" 값을 지정해야 합니다.TabHost
내에서 내용(Contents)을 표시할 곳은 반드시FrameLayout
을 사용해야 합니다.- 내용(Contents) 표시를 위한
FrameLayout
의 id 속성 값은 반드시 "@android:id/tabcontent"이어야 합니다. - findViewById() 함수를 통해
TabHost
를 설정하는 경우,TabHost
의 참조를 가져온 다음 반드시 setup() 함수를 호출해야 합니다. (예제 소스의 [STEP-2]에서 확인)
3. 안드로이드 탭(Tab) 사용하기.
그럼 이제 앱 만들기 예제를 통해 안드로이드 탭(Tab) 위젯을 사용하는 방법에 대해 살펴보겠습니다.
예제에서는, 앞서 설명한 방법대로 TabHost
내에 TabWidget
과 FrameLayout
을 표시합니다. 그리고 TabWidget
의 각 탭 버튼이 눌려지면, FrameLayout
안에 선언된 자식 뷰를 바꿔가며 표시하도록 만들겠습니다.
3.1 MainActivity 레이아웃 구성.
예제의 첫 번째 단계는 Mainactivity에 표시될 Layout 리소스 XML을 작성하는 것입니다. 이 때 앞에서 언급한 주의사항의 내용에 따라, TabWidget
의 "id"가 "@android:id/tabs"이어야 한다는 것과, FrameLayout
의 "id"는 "@android:id/tabcontent"이어야 한다는 것에 주의하세요.
그리고 FrameLayout
의 자식들(Children)은 LinearLayout
을 사용하였습니다.
[STEP-1] "activity_main.xml" - MainActivity의 Layout 리소스 XML.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/content_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.recipes4dev.examples.tabwidgetbasicexample.MainActivity"
tools:showIn="@layout/activity_main">
<TabHost
android:id="@+id/tabHost1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- TabWidget의 id값이 반드시 "tabs"로 지정되어야 함. -->
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- FrameLayout의 id값이 반드시 "tabcontent"로 지정되어야 함. -->
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- 첫 번째 페이지. content1 -->
<LinearLayout
android:id="@+id/content1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#8BC34A"
android:gravity="center"
android:padding="8dp"
android:text="TAB CONTENT 1" />
</LinearLayout>
<!-- 두 번째 페이지. content2 -->
<LinearLayout
android:id="@+id/content2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#009688"
android:gravity="center"
android:padding="8dp"
android:text="TAB CONTENT 2" />
</LinearLayout>
<!-- 세 번째 페이지. content3 -->
<LinearLayout
android:id="@+id/content3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#2196F3"
android:gravity="center"
android:padding="8dp"
android:text="TAB CONTENT 3" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
</RelativeLayout>
3.2 TabHost에 탭 추가.
이제, TabHost
에 탭을 추가하고, 각 탭이 눌려졌을 때 표시될 페이지 뷰에 대한 정보를 추가합니다. 이 과정은 TabHost.TapSpec
클래스의 객체를 만들고, TabHost.addTab()
함수를 사용하여 객체를 전달함으로써 수행됩니다.
TabHost.TapSpec
을 통해 하나의 탭이 추가되는 과정은 아래와 같습니다.
// "Tab Spec" 태그(Tag)를 가진 TabSpec 객체 생성.
TabHost.TabSpec ts = tabHost.newTabSpec("Tab Spec") ;
// 탭이 눌려졌을 때 FrameLayout에 표시될 Content 뷰에 대한 리소스 id 지정.
ts.setContent(R.id.content) ;
// 탭에 표시될 문자열 지정.
ts.setIndicator("TAB") ;
// TabHost에 탭 추가.
tabHost.addTab(ts) ;
TabHost.TapSpec
의 객체를 생성할 때는 new 키워드가 아닌, TabHost
의 newTabSpec()
함수를 호출해야 한다는 것을 주의하세요. 그리고 newTabSpec()
함수에 전달되는 태그(Tag)는 탭 버튼을 식별할 때 사용되는 값입니다.
위에서 설명한 방법을 사용하여 탭 버튼을 추가하는 예제 소스는 아래와 같습니다.
[STEP-2] "MainActivity.java" - TabHost.TabSpec을 사용하여 탭 추가.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// ... 코드 계속
TabHost tabHost1 = (TabHost) findViewById(R.id.tabHost1) ;
tabHost1.setup() ;
// 첫 번째 Tab. (탭 표시 텍스트:"TAB 1"), (페이지 뷰:"content1")
TabHost.TabSpec ts1 = tabHost1.newTabSpec("Tab Spec 1") ;
ts1.setContent(R.id.content1) ;
ts1.setIndicator("TAB 1") ;
tabHost1.addTab(ts1) ;
// 두 번째 Tab. (탭 표시 텍스트:"TAB 2"), (페이지 뷰:"content2")
TabHost.TabSpec ts2 = tabHost1.newTabSpec("Tab Spec 2") ;
ts2.setContent(R.id.content2) ;
ts2.setIndicator("TAB 2") ;
tabHost1.addTab(ts2) ;
// 세 번째 Tab. (탭 표시 텍스트:"TAB 3"), (페이지 뷰:"content3")
TabHost.TabSpec ts3 = tabHost1.newTabSpec("Tab Spec 3") ;
ts3.setContent(R.id.content3) ;
ts3.setIndicator("TAB 3") ;
tabHost1.addTab(ts3) ;
}
}
예제의 내용 중 findViewById()
함수를 사용해 TabHost
의 참조를 가져온 다음, TabHost.setup()
함수를 호출한 것에 주의하세요. 만약 setup()
함수를 호출하지 않으면 TabWidget
이 정상적으로 표시되지 않습니다.
이제 안드로이드 탭 예제 작성은 완료되었습니다.
4. 안드로이드 탭(Tab) 예제 실행 화면.
예제를 실행하면, 아래 그림과 같이 안드로이드 탭 화면이 표시됩니다.
각 탭 버튼을 선택하면, 버튼 선택에 따라 페이지 뷰가 바뀌는 것을 확인할 수 있습니다.
5. 참고
- TabHost 클래스 도움말
- [안드로이드 개발 참조문서 TabHost 항목]을 참고하세요.
- TabWidget 클래스 도움말
- [안드로이드 개발 참조문서 TabWidget 항목]을 참고하세요.
.END.
'ANDROID 프로그래밍 > TAB' 카테고리의 다른 글
안드로이드 탭 만들기. [TabLayout] (Android TabLayout) (22) | 2019.01.19 |
---|