Android - 상단 탭 만들기

유의선·2023년 6월 20일
0

탭(Tab)은 몇 개의 버튼을 두고 그중 하나의 버튼을 눌러 화면을 전환하는 방식으로, 하나의 뷰에서 여러 개의 정보를 볼 때 일반적으로 사용하는 뷰이다.

이러한 탭에는 상단 탭과 하단 탭으로 구분할 수 있다.


상단 탭 만들기

activity_main.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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?colorPrimaryDark"
                android:elevation="1dp"
                android:theme="@style/ThemeOverlay.AppCompat.Dark">

                <TextView
                    android:id="@+id/titleText"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="타이틀"
                    android:textAppearance="@style/Base.TextAppearance.Widget.AppCompat.Toolbar.Title"/>

            </androidx.appcompat.widget.Toolbar>

            <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@android:color/background_light"
                android:elevation="1dp"
                app:tabGravity="fill"
                app:tabMode="fixed"
                app:tabSelectedTextColor="?colorAccent"
                app:tabTextColor="?colorPrimary"/>

        </com.google.android.material.appbar.AppBarLayout>


        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

</RelativeLayout>

구성을 보면

<CoordinatorLayout>

	<AppBarLayout>
    
    	<ToolBar>
        	<TextView>
              
        <TabLayout>
        
    </AppBarLayout>
    
    <FrameLayout>
    
</CoordinatorLayout>

으로 되어 있다.

CoordinatorLayout은 액션바 영역을 포함한 전체 화면의 위치를 잡아주는 역할을 한다.
CoordinatorLayout 안에 AppBarLayout과 함께 다른 레이아웃을 넣으면 그 둘 간의 위치가 자동으로 결정된다.

AppBarLayout은 액션바를 가리키는데 이 안에 ToolBar가 들어갈 수 있으며, 탭을 사용하는 경우에는 탭의 버튼들이 들어가는 TabLayout을 추가할 수 있다.

FrameLayout에는 화면의 내용을 구성할 수 있다.

ToolBar 안에는 텍스트뷰를 하나 넣어 제목을 표시할 수 있도록 하였다.

TabLayout 에서는
tabMode 값을 fixed로 하여 스크롤 없이 한 화면에 모든 탭 버튼들이 보이도록 하였고,
tabGravity 값을 fill로 설정하여 탭 버튼들이 동일한 크기를 갖도록 하였다.

FrameLayout으로 확보한 하단의 공간에는 탭 버튼들에 따른 프래그먼트들을 넣을 예정이다.


FrameLayout에 넣을 세 개의 프래그먼트를 만든다.
버튼 하나를 넣고 배경색을 바꿔 세 프래그먼트가 구분되게 만든다.

그 후 각각 java 파일을 만들어 각각의 프래그먼트 파일을 인플레이션 시킨다.

public class Fragment1 extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment1, container, false);
    }
}

MainActivity.java 파일을 수정한다.

public class MainActivity extends AppCompatActivity {

    Toolbar toolbar;
    Fragment1 fragment1;
    Fragment2 fragment2;
    Fragment3 fragment3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayShowTitleEnabled(false);    // 액션바의 타이틀 제거

        fragment1 = new Fragment1();
        fragment2 = new Fragment2();
        fragment3 = new Fragment3();

        getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment1).commit();

        TabLayout tabs = findViewById(R.id.tabs);
        tabs.addTab(tabs.newTab().setText("Fragment1"));
        tabs.addTab(tabs.newTab().setText("Fragment2"));
        tabs.addTab(tabs.newTab().setText("Fragment3"));

        tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                int position = tab.getPosition();
                Toast.makeText(getApplicationContext(), "선택된 탭 : " + position, Toast.LENGTH_SHORT).show();

                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();
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
    }
}

XML 레이아웃에서 정의한 Toolbar 객체를 참조해서
setSupportActionBar 메소드를 통해 액션바로 설정한다.

		toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

그런데 setSupportActionBar 메소드는 액티비티에 디폴트로 만들어진 액션바가 없을 경우에만 동작한다.
하지만 프로젝트가 만들어질 때 메인 액티비티에는 자동으로 액션바가 만들어진다.
이것은 테마(theme)를 액션바가 들어 있는 테마로 설정했기 때문이다.

액티비티에 설정된 테마를 변경하기 위해서는 res/value 폴더 안의 theme.xml 파일을 수정해야 한다.
여기서 style 태그의 parent 속성의 값으로 API에서 미리 정의한 테마 중의 하나가 지정되어 있다.
style 태그의 parent 속성을 NoActionBar로 변경하면 이 스타일을 적용한 액티비티에는 액션바가 만들어지지 않는다.

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.SampleTab" parent="Theme.MaterialComponents.DayNight.NoActionBar">

getSupportActionBar 메소드로 액션바 객체를 참조한 후
setDisplayShowTitleEnabled 메소드에 false 값을 넘겨주에 액션바의 타이틀을 제거한다.

		ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayShowTitleEnabled(false);    // 액션바의 타이틀 제거

Fragment 객체들을 생성한 후 fragment1 이 보이도록 설정한다.

		fragment1 = new Fragment1();
        fragment2 = new Fragment2();
        fragment3 = new Fragment3();

        getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment1).commit();

TabLayout 객체를 참조한 후 addTab 메소드를 사용해 탭에 버튼들을 추가한다.

		TabLayout tabs = findViewById(R.id.tabs);
        tabs.addTab(tabs.newTab().setText("Fragment1"));
        tabs.addTab(tabs.newTab().setText("Fragment2"));
        tabs.addTab(tabs.newTab().setText("Fragment3"));

tabLayout 객체에 onTabSelectedListener을 설정하여 탭 버튼이 선택될 때마다 onTabSelected 메소드가 호출되도록 한다.
각 탭 버튼이 선택될때마다 탭 버튼의 positon을 출력하도록 하며, Fragment를 변경한다.

		tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                int position = tab.getPosition();
                Toast.makeText(getApplicationContext(), "선택된 탭 : " + position, Toast.LENGTH_SHORT).show();

                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();
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });


0개의 댓글