오늘 구성할 화면이다. 보는 것 처럼 3개의 탭 버튼 중 하나를 클릭했을 때, 연결된 화면을 하나씩 보여주는 형태이다. 오늘은 이 화면을FrameLayout 클래스와 TabHost 클래스를 이용하여 구성하려 한다.
액티비티를 생성하고 탭 버튼을 이미지로 출력하기 위해 아이콘 이미지 3개를 res/drawable 폴더에 복사한다. 나는 아이콘 이미지라서 36x36 크기로 사용하였다.
FrameLayout은 레이아웃에 포함된 뷰들을 같은 영역에 겹쳐서 배치할 때 사용한다. 레이아웃 자체의 특별한 속성은 없다. FrameLayout 안에 뷰를 배치할 때, 포함된 순서대로 배치되기 때문에 맨 마지막에 포함한 뷰가 가장 위에 보인다.
FrameLayout을 이용하는 목적은 대부분 같은 영역에 여러 뷰를 겹치게 한 다음, 한 순간에 하나의 뷰만 보이기 위함이다.
UI 프로그램에서 가장 많이 제공하는 화면 중 하나이다. 화면 여러 개를 준비한 다음, 사용자가 버튼을 누를 때 버튼과 연결된 화면을 하나씩 보여주는 형태이다.
TabHost로 탭 화면을 구성하면 TabHost 하위에는 꼭 TabWidget과 FrameLayout으로 구성해야 한다.
∙ TabHost: 탭 전체 영역을 지칭
∙ TabWidget: 탭 버튼이 들어갈 영역을 지칭
∙ FrameLayout: 탭 버튼 클릭 시 나올 화면 영역을 지칭
레이아웃 XML
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/host">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TabWidget
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@android:id/tabs"
android:background="#B15656"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@android:id/tabcontent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tab_content1"
android:text="Tab 1"
android:textSize="30sp"
android:textStyle="bold"
android:gravity="center" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tab_content2"
android:textSize="30sp"
android:textStyle="bold"
android:text="tab 2"
android:gravity="center" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tab_content3"
android:text="tab 3"
android:textStyle="bold"
android:textSize="30sp"
android:gravity="center"/>
</FrameLayout>
</LinearLayout>
</TabHost>
위에서 전체 화면 영역은 TabHost 클래스를 이용하여 지칭하였고, LinearLayout으로 나열 방향을 세로로 표현하였다. LinearLayout 아래 TabWidget을 포함하여 탭 버튼이 들어갈 자리를 지정하였으며, 탭 본문에 들어갈 자리는 FrameLayout을 이용하여 지정하였다.
여기서 중요한 점은 TabHost 하위에는 무조건 탭 버튼을 위해 TabWidget, 탭 본문을 위해 FrameLayout을 선언해야 한다. 본문은 FrameLayout이 아닌 다른 레이아웃 클래스로 선언할 수 없다.
자바 코드
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frame_layout);
TabHost tabhost = findViewById(R.id.host);
tabhost.setup();
// 각 TabSpec을 만들 때 매게변수의 문자열은 각 TabSpec의 식별자 문자열
TabHost.TabSpec spec = tabhost.newTabSpec("tab1");
// tab button 구성
spec.setIndicator(null, ResourcesCompat.getDrawable(
getResources(), R.drawable.tab_icon1, null));
// tab의 본문 구성
spec.setContent(R.id.tab_content1);
tabhost.addTab(spec);
spec = tabhost.newTabSpec("tab2");
spec.setIndicator(null, ResourcesCompat.getDrawable(
getResources(), R.drawable.tab_icon2, null));
spec.setContent(R.id.tab_content2);
tabhost.addTab(spec);
spec = tabhost.newTabSpec("tab3");
spec.setIndicator(null, ResourcesCompat.getDrawable(
getResources(), R.drawable.tab_icon3, null));
spec.setContent(R.id.tab_content3);
tabhost.addTab(spec);
}
TabHost를 레이아웃 XML에서 획득하여 setup() 함수로 초기화한다. 탭 하나를 구성하기 위해 TabSpec을 newTabSpec() 함수로 생성해 준다. newTabSpec() 함수의 매개변수를 "tab1"로 지정하였는데, 이 문자열은 내가 지정한 임의의 문자열이며, 각 탭 화면을 코드에서 식별할 때 사용된다.
그리고 하나의 TabSpec에 탭 버튼을 구성하고자 setIndicator() 함수를 이용하였으며, 탭 버튼을 문장열이나 이미지로 구성할 수 있다.
또한, TabSpec의 본문을 지정하고자 setContent() 함수를 이용하였다.
이렇게 만들어진 TabSpec을 최종 TabHost에 host.addTab() 함수로 포함해 주면 된다.
✏️ 하.. 오늘 엄마가 냉장고 청소 시켜서 세시간이 공중 분해 됐다.. 그래도 난 효년이 되었으니.. 오늘의 벨로그도 완료 . 태그가 늘어 갈 때 마다 뿌듯하다.
첨엔 그렇게 어렵고 하나도 이해가 안 됐는데, 이렇게 정리해서 글을 올리게 될 날이 온게 너무 신기하다.. 물론 나도 많이 더 배워야 하지만 ㅎㅎ..
오늘은 대청소로 체력을 너무 소모해서 음주 공부를 했다.. 이런거 말하면 안 되낭 ㅎㅎㅎㅎ 뭐 할 일만 하면되지.. 아.. 아닌가..ㅎㅎㅋㅋㅋㅋ
근데 1시간이면 끝 날 일이 좀 길어져서 다음부터는 그냥 빡 집중해서 해야 겠다. 그래도 기분 좋게 마무으리~