상단에 탭 버튼이 있고 버튼을 누를 때마다 가운데 부분에 중첩되어 있는 화면이 바뀌어 보이는 구조로, 가운데 부분은 여러 화면을 중첩시킬 수 있도록 프레임 레이아웃을 사용하게 됩니다.
레이아웃에 추가
메인 액티비티의 XML 레이아웃에 상단 타이틀 부분의 레이아웃을 직접 정의할 수 있습니다.
자동으로 만들어지는 메인 액티비티의 레이아웃에는 타이틀 부분이 빠져있고 액션바가 들어간 스타일이 지정되어 있지만 액션바가 들어가 있지 않은 스타일로 바꾸는 경우에는 직접 상단의 타이틀 부분 레이아웃을 만들 수 있습니다.
레이아웃의 구조는 다음과 같습니다.
<CoordinatorLayout>
<AppBarLayout>
<Toolbar>
</Toolbar>
<TabLayout>
</TabLayout>
</AppBarLayout>
<FrameLayout>
</FrameLayout>
</CoordinatorLayout>
상단의 액션바 부분과 가운데 내용이 보이는 부분이 함께 들어간 구조에서는 두 부분의 크기가 잘 맞게 보여야 하므로 CoordinatorLayout이 사용됩니다.
그리고 그 안에 AppBarLayout과 FrameLayout이 들어갑니다.
AppBarLayout이 상단의 액션바 영역, FrameLayout이 내용이 보이는 화면 부분이 됩니다.
Toobar는 액션바 안에서 타이틀이 메뉴 아이콘이 보일 영역을 말하며 탭 버튼이 그 아래에 보일 수 있도록 TabLayout이 들어가 있습니다.
탭 버튼을 보이지 않게 하고 싶다면 TabLayout을 넣지 않으면 됩니다.
소스에서 탭 추가
이 레이아웃을 메인 액티비티에 설정하려면 액션바가 없는 스타일로 변경해야 합니다.
/res/values 폴더 안에 있는 styles.xml 파일을 열고 AppTheme이라는 이름을 가진 스타일 정보를 Theme.AppCompat.Light.NoActionBar 로 변경합니다.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
메인 액티비티의 스타일이 AppTheme으로 설정되어 있기 때문에 NoActionBar 스타일로 바꾸면 메인 액티비티에는 액션바가 만들어지지 않습니다.
이제 소스에서 프래그먼트를 세 개 만들고 각각의 프래그먼트가 상단의 탭 버튼을 누를 때마다 가운데 프레임레이아웃 안에 보일 수 있도록 만듭니다.
먼저 TabLayout에 탭 버튼을 추가합니다.
TabLayout tabs = (TabLayout) findViewById(R.id.tabs);
tabs.addTab(tabs.newTab().setText("통화기록"));
tabs.addTab(tabs.newTab().setText("스팸기록"));
tabs.addTab(tabs.newTab().setText("연락처"));
탭 버튼을 눌렀을 때 각각의 프래그먼트가 보이도록 합니다.
프래그먼트를 바꾸어 보이게 하려면 프레임 레이아웃에 중첩시켰다가 가시성 속성으로 보이도록 할 수도 있지만 여기에서는 프래그먼트 매니저를 이용해 변경합니다.
tabs.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int position = tab.getPosition();
Log.d("MainActivity", "선택된 탭 : " + position);
Fragment selected = null;
if (position == 0) {
selected = fragment1;
} else if (position == 1) {
selected = fragment2;
} else if (position == 2) {
selected = fragment3;
}
getSupportFragmentManager().beginTransaction().replace(R.id.container, selected).commit();
}
이렇게 하면 탭 버튼을 누를 때마다 각 버튼에 해당하는 프래그먼트로 교체되어 보이게 됩니다.
생각해보기
- 탭 버튼에 아이콘 이미지가 보이게 하려면 어떻게 해야 할까요?
- 첫 번째 탭 안에 있는 버튼을 눌렀을 때 두 번째 탭 화면이 보이도록 하고 싶다면 어떻게 하면 될까요?
참고 자료
comment
맞게 한 건지는 모르겠는데... 이렇게 했음.
2. 각 fragment 의 OnClickNext는
public void OnClickNext(View view) {
MainActivity actitivity = (MainActivity) getActivity();
activity.selectTabByPosition(1); /// 프래그먼트에 따라 0, 1, 또는 3
}
MainActivity 안의 selectTabByPosition(int position) 은
public void selectTabByPosition(int position) {
tabs.selectTab(tabs.getTabAt(position);
}
tabs 를 멤버변수로 바꿔야 함.
ㅠㅠ api28부터 androidx로 바껴서 관련소스코드로 강의 수정해주셨으면
좋을 것같네요 삽질만 계속하고 있어요
android x 쓰시는 분들은 MainActivity에서
제가 초보라 잘 모르겠지만 개발자 문서에 의하면 support.v7은 사용을 권장하지 않고 있습니다. 그래서 design이라고 라이브러리를 검색해도 support.v7이 나오지 않더라고요. 그래서 design이라고 쳤을 때 google이라고 딱 하나 나와있어서 그 라이브러리를 추가했습니다. 그리고
activity_main.xml 에서 <androidx.coordinatorlayout.widget.CoordinatorLayout>,<androidx.appcompat.widget.Toolbar>,<com.google.android.material.tabs.TabLayout> 이 태그를 이용해서 강의랑 똑같이 했더니 잘 됐습니다. 참고바랍니다.
⭐️생각해보기⭐️
1. TabLayout을 커스텀하여 보이게 할 수 있을 것 같습니다.
2. OnTabSelectedListener 메소드에서 첫번째 탭을 눌렀을 때 두번째 프래그먼트를 지정해주면 될 것 같습니다.
error: attribute 'com.idh.songk.danang:tapMode' not found.
Message{kind=ERROR, text=error: attribute 'com.idh.songk.danang:tapMode' not found., sources=[C:\Users\songk\AndroidStudioProjects\Danang\app\src\main\res\layout\activity_main.xml:29], original message=, tool name=Optional.of(AAPT)}
무슨에러인지 잘모르겠습니다.
design 을나중에 추가하면 에러가 발생하나요? R글자는 다 빨갛게 뜨네요 어떻게해결해야되나요?
2) 저는 interface를 이용해 이벤트를 전달해보았는데요, 프래그먼트 전환은 잘 되지만 탭 레이아웃 선택은 바뀌지않습니다. 그리고 첫번째 탭을 눌러도 첫번째 화면이 나오지않고 두번째 탭을 누른 뒤 다시 첫번째 탭을 눌러야하더라구요.. 이벤트 전달 방식이 잘못됐거나 아니면 탭에서 다른 처리를 해주어야하나요?
생각해보기
1. tabs.newTab()의 method중 setIcon() 메소드가 있는걸로 보아 이 메소드를 호출하면 아이콘을 설정할 수 있을 것 같습니다.
2.1) MainActivity내에서 input index에 따라 Fragment를 바꾸어주는 method를 만든다.
2) 첫 번째 탭에 해당하는 Fragment의 onAttach method 내에서 MainActivity를 가져온다. (처음에 이 부분을 까먹어서막혔습니다. 혹시 해보실 분들은 강의 4-1) 프래그먼트 이해하기 참조하세요 !)
3) onCreateView method 내에서 rootGroup에서 button을 가져온 후, onClick 함수 내에서 MainActivity내에 만들어둔 Fragment를 바꿔주는 method를 호출한다.