기록장
[안드로이드] Fragment 이해하기(2) / 상단 탭, 하단 탭 본문
앞서 글에서는 Fragement의 개념에 대해 알아보았다.(부족한 점이 매우 많았을 것 같지만..) 앞의 포스팅을 이해했다면 fragment를 이용한 상단 탭, 하단 탭을 구현하는 것도 어렵지 않을 것이다.
요즈음 여러 앱을 보면 상단 탭, 하단 탭을 이용하여 구현한 앱들이 매우 많다. 카카오톡, 쿠팡 등 상단, 하단 탭이 유용하게 사용되고 있다. 이유는 그만큼 기능성? 사용성? 면에서 좋다. 메뉴버튼을 누르고 고른 후 선택하여 정보를 얻고 다시 나와서 메뉴버튼을 누르고 고르는 방식은 불편할 수 있다. 그러나 이 탭 기능을 사용하면 한 화면에서 화면을 전환하여 보여줌으로써 좀 더 직관적이고 편리함을 사용자에게 줄 수 있다.
탭은 TabLayout을 사용하여 구현하는데 사용 전에 먼저 외부 라이브러리를 추가해주어야 한다.
dependency 추가할 때
API 28 이하는
implementation 'com.android.support:design:28.0.0'
API 29 부터는
implementation 'com.google.android.material:material:1.0.0'
앞의 포스팅을 보셨거나 Fragment를 대충 아신다면 어떻게 구성될지 바로 아실 것이다. 메인 액티비티와 메인xml에 탭과 프래그먼트를 만들어주고 프래그먼트 화면을 구성할 fragment를 상속하는 액티비티와 xml을 넣어주면 된다.
그리고 상단 탭은 액션 바에 만들어주는 것과 액션 바를 없애거나 그대로 두고 만드는 방법이 있는데 난 그대로 두고 만들겠다. 액션 바에 관한 것은 나중에 포스팅 해보도록 하고 나머지는 코드를 보면서 설명하도록 하겠다.
코드
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tab"
//fixed는 화면 넓이에 딱 맞게 표시
app:tabMode="fixed" //scrollable로 선택하면 스크롤 가능(탭 버튼이 많을 시..)
app:tabGravity="fill"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment"/>
</LinearLayout>
이렇게 구성하면 위에는 탭 아래는 프래그먼트로 구성될 것이다.
MainActivity.xml
public class MainActivity extends AppCompatActivity {
fragment1 f1;
fragment2 f2;
fragment3 f3;
FragmentManager fm;
TabLayout tabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
f1 = new fragment1();
f2 = new fragment2();
f3 = new fragment3();
fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.fragment, f1).commit(); //첫 화면 띄우기
tabLayout = findViewById(R.id.tab);
//addTab() 메소드를 사용하여 탭 버튼 추가
tabLayout.addTab(tabLayout.newTab().setText("1"));
tabLayout.addTab(tabLayout.newTab().setText("2"));
tabLayout.addTab(tabLayout.newTab().setText("3"));
//탭 버튼 이벤트 처리를 위한 리스너 생성 후 3개 메소드 오버라이드
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
//선택되지 않았던 탭이 선택되었을 경우
int position = tab.getPosition();
Fragment selected = null;
if(position == 0){
selected = f1;
}
else if(position == 1){
selected = f2;
}
else if(position == 2){
selected = f3;
}
fm.beginTransaction().replace(R.id.fragment,selected).commit();
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
//탭이 선택된 상태에서 선택되지 않음으로 변경될 경우
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
//이미 선택된 탭이 다시 선택되었을 경우
}
});
}
}
* 탭 식별을 위한 4가지 메소드
int getPosition(): 탭의 순서를 리턴
Object getTag(): 탭에 지정된 태그 객체를 리턴
CharSequence getText(): 탭에 표시된 텍스트 문자열 리턴
boolean isSelected(): 탭 선택 여부 리턴
아래 코드는 전환되면서 보여질 화면들인데 이 방식으로 2개 더 만들면 된다.(복붙으로 숫자만 바꿔주면 된다)
fragment_fragment1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment1"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp"
android:text="첫번째"/>
</LinearLayout>
fragment1.java
public class fragment1 extends Fragment {
ViewGroup viewGroup;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
viewGroup = (ViewGroup) inflater.inflate(R.layout.fragment_fragment1, container, false);
return viewGroup;
}
}
결과
여기까지 상단 탭 만들기를 알아보았다.
이어서 하단 탭을 만들어 보도록 하겠다.
하단 탭 생성에 있어서는 BottomNavigationView 위젯을 사용한다. 상단 탭과 같이 같은 외부 라이브러리를 사용하므로 이미 추가하셨으면 안해도 되고, 안했다면 추가해주시면 된다.
BottomNavigationView는 TabLayout과 다르게 xml을 만들어서 제목(아이템 항목)을 정해준다.
xml 만드는 과정
디렉토리를 만드는데 Resource type을 menu로 해준다.
디렉토리가 만들어졌다면 만들어진 디렉토리에서 마우스 오른쪽 버튼으로 목록창을 띄운 후 메뉴 리소스 파일을 생성한다.
파일을 만들었으면 나머지는 코드 부분에서 설명하도록 하겠다.
코드
bottom_nav_menu.xml (방금 위에서 만든 xml 파일이다)
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/tab1"
app:showAsAction="always"
android:icon="@drawable/ic_launcher_foreground"
android:enabled="true"
android:title="1" />
<item android:id="@+id/tab2"
app:showAsAction="always"
android:icon="@drawable/ic_launcher_background"
android:enabled="true"
android:title="2"/>
<item
android:id="@+id/tab3"
app:showAsAction="always"
android:icon="@mipmap/ic_launcher_round"
android:enabled="true"
android:title="3"/>
</menu>
- android:id - 고유 id로 이 id를 통해 어떤 탭이 눌렸는지 식별
- android:icon - 아이콘 넣기
- android:title - 아이템 항목의 제목
- android:showAsAction - 항목이 앱 바에서 작업 항목으로 나타나는 시기와 방법을 지정
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:weightSum="10">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/framelayout"
android:layout_weight="9"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/bottomnavigationview"
app:menu="@menu/bottom_nav_menu"
android:layout_weight="1"/>
</LinearLayout>
app:menu="" 에서 아까 만든 메뉴 xml 파일을 가져온다.
MainActivity.java
public class MainActivity extends AppCompatActivity {
fragment1 f1;
fragment2 f2;
fragment3 f3;
FragmentManager fm;
BottomNavigationView bottomNavigationView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
f1 = new fragment1();
f2 = new fragment2();
f3 = new fragment3();
fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.framelayout, f1).commit();
bottomNavigationView = findViewById(R.id.bottomnavigationview);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
//munuItem.getItemID()로 menu.xml에 있는 id를 가져와서 어떤 버튼이 눌렸는지 식별 가능하다.
switch (menuItem.getItemId()){
case R.id.tab1:
fm.beginTransaction().replace(R.id.framelayout, f1).commit();
return true;
case R.id.tab2:
fm.beginTransaction().replace(R.id.framelayout, f2).commit();
return true;
case R.id.tab3:
fm.beginTransaction().replace(R.id.framelayout, f3).commit();
return true;
}
return false;
}
});
}
}
결과
상단 탭, 하단 탭을 만들어 보았다.
프래그먼트만 이해하고 있다면 쉽게 만들 수 있을 것이라 생각된다.
부족한 점, 피드백 환영합니다.
감사합니다.
참고
정재곤, 『Do it! 안드로이드 앱 프로그래밍 - 개정 6판』, 이지스퍼블리싱(주)
'안드로이드' 카테고리의 다른 글
[안드로이드] Fragment 이해하기(4) / NavigationDrawer 네비게이션 드로어 (0) | 2021.01.04 |
---|---|
[안드로이드] Fragment 이해하기(3) / ViewPager 뷰페이저 (0) | 2021.01.04 |
[안드로이드] Fragment 이해하기(1) (0) | 2021.01.03 |
[안드로이드] SharedPreferences / 데이터 저장, 복원 (0) | 2021.01.01 |
[안드로이드] 액티비티의 생명주기 (0) | 2021.01.01 |