
하나의 화면에 하나의 Item만 들어간다
화면을 항목으로 본다, 한 화면에 항목 하나가 온다는 개념
책 넘기는 느낌이 나는 것
가로페이지만 지원하던 것이었는데 ViewPager2가 나오면서 세로도 지원


ViewPager2 로 Layout 만들어야함!
가로세로 정할 수 있어서 orientation 설정
<?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"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        />
    <Button
        android:id="@+id/btn_prev"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="PREV"/>
    <Button
        android:id="@+id/btn_next"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="NEXT"
        />
</RelativeLayout>
package com.bsj0420.ex29viewpager;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
    ArrayList<Integer> imgIds = new ArrayList<>(); //그림 식별자 넣을것
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //데이터 임의로 넣기
        imgIds.add(R.drawable.bg_one01);
        imgIds.add(R.drawable.bg_one02);
        imgIds.add(R.drawable.bg_one03);
        imgIds.add(R.drawable.bg_one04);
        imgIds.add(R.drawable.bg_one05);
        imgIds.add(R.drawable.bg_one06);
        imgIds.add(R.drawable.bg_one07);
        imgIds.add(R.drawable.bg_one08);
        imgIds.add(R.drawable.bg_one09);
        imgIds.add(R.drawable.bg_one10);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/bg_one01" />
</RelativeLayout>
adpter 만들어서 데이터와 레이아웃을 합치기
1.Adapter 상속받기 (extends RecyclerView.Adapter<제네릭>)
2.제네릭으로 쓸 뷰홀더 이너클래스로 ViewHolder 클래스 만들기
🧨 ViewHolder : View페이지 안의 나열되어 있는 아이템들을 참조변수로 가지고 있는 애
package com.bsj0420.ex29viewpager;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
//1. extends Adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.VH> {
    //3. context와 데이터 받아올 변수 준비 + 생성자 초기화
     Context context;
     ArrayList<Integer> imgIds;
    public MyAdapter(Context context, ArrayList<Integer> imgIds) {
        this.context = context;
        this.imgIds = imgIds;
    }
    //4. 아이템뷰를 xml시안대로 만드는 곳
    @NonNull
    @Override
    public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //3-1) xml에 Layout을 LayoutInflater로 쭉쭉 읽어 와서 View로 리턴받기
        View itemView = LayoutInflater.from(context).inflate(R.layout.page, parent,false);
        //4-2) 
        VH holder = new VH(itemView); //뷰 홀더는 itemView의 안의 아이템들을 참조변수로 가지 고 있는 애
        
        return holder;
    }
    //5. 셋팅 당담
    @Override
    public void onBindViewHolder(@NonNull VH holder, int position) {
        holder.iv.setImageResource(imgIds.get(position)); 
        // holder = 현재 레이아웃을 붙잡고 있는 애
    }
    @Override
    public int getItemCount() {
        return imgIds.size();
    }
    //2.제네릭으로 쓸 뷰홀더 이너클래스로 ViewHolder 클래스 만들기
    class VH extends RecyclerView.ViewHolder {
        //2-1 ) 아이템 페이지에 있는 View 나열
        ImageView iv;
        public VH(@NonNull View itemView) { //무조건 itemView하나는 받도록 해서 implement
            super(itemView);
            iv = itemView.findViewById(R.id.iv); //연결해주기
        }
    }
}
아답터 나와야 하는 adaperView와 내가 만든 아답터 참조변수로 가져와서 set해주기!
이전페이지와 다음페이지 보여주는 버튼도 붙여보자
package com.bsj0420.ex29viewpager;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
    ArrayList<Integer> imgIds = new ArrayList<>(); //그림 식별자 넣을것
    //4. 아답터 페이지에 보이기
    //아답터 나와야 하는 adaperView와 내가 만든 아답터 가져오기
    ViewPager2 pager2;
    MyAdapter adapter;
    Button btn_prev, btn_next;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //데이터 임의로 넣기
        imgIds.add(R.drawable.bg_one01);
        imgIds.add(R.drawable.bg_one02);
        imgIds.add(R.drawable.bg_one03);
        imgIds.add(R.drawable.bg_one04);
        imgIds.add(R.drawable.bg_one05);
        imgIds.add(R.drawable.bg_one06);
        imgIds.add(R.drawable.bg_one07);
        imgIds.add(R.drawable.bg_one08);
        imgIds.add(R.drawable.bg_one09);
        imgIds.add(R.drawable.bg_one10);
        pager2 = findViewById(R.id.pager);
        adapter = new MyAdapter(this, imgIds);
        pager2.setAdapter(adapter);
        //
        btn_prev = findViewById(R.id.btn_prev);
        btn_prev.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //뷰페이저의 현재 위치 인덱스 얻어오기
                int position = pager2.getCurrentItem();
                //현재 위치 이전 번호로 지정
                pager2.setCurrentItem(position-1, true);
            }
        });
        btn_next = findViewById(R.id.btn_next);
        btn_next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int position = pager2.getCurrentItem();
                pager2.setCurrentItem(position+1, false);
            }
        });
    }
}
페이지를 넘겼을때마다 viewLayout의 모양이 다르게 할때 사용
Fragment는 뷰의 특징을 가지고 있음
Fragment가 리턴해주는 걸 액티비티가 보여준다 뷰를 여러개 만들면 그것을 제어할 참조변수들을 나열해야하는데 별도의 xml 에 따로 만들어서 제어
Fragment가 Activity의 일부분처럼 자리를 차지하는데 참조변수를 제어할 수 있는 java를 가질수 있다 메인 Activity에서 분리해서 역할 분담을 하는 느낌
Activity 안엔 다른  Activity가 들어갈 수 없음

이 Fragment가 화면에 보여줄 뷰를 만들어서 리턴해주면 액티비티가 보여줌
1) extends Fragment 하기
2) 콜백메소드 onCreateView() 만들기
package com.bsj0420.ex30fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class MyFragment extends Fragment {
    TextView tv;
    Button btn;
    //이 Fragment가 화면에 보여줄 뷰를 만들어서 리턴해주면 액티비티가 보여줌
    //이를 위해 자동으로 호출되는 콜백메소드 : onCreateView
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //fragment_my.xml 에 설계한 뷰를 객체를 생성하여 리턴
        //ViewGroup container = 플래그먼트가 붙을 곳
        View view = inflater.inflate(R.layout.fagment_my, container, false);
        
        return view;
    }
}
<?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"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">
    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView inside MainAtivity"
        android:textColor="@color/black"
        android:padding="8dp"
        />
    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="chage Text"/>
    <!--
     fragment로 화면의 한 조각을 만들기
     -->
    <fragment
        android:id="@+id/frag_my"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.bsj0420.ex30fragment.MyFragment
        tools:layout="@layout/fagment_my""/>
</LinearLayout>
💡 플래그먼트 미리보기 속성
tools:layout="@layout/fagment_my"
Fragment.java 에 가서 내거 제어
package com.bsj0420.ex30fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class MyFragment extends Fragment {
    TextView tv;
    Button btn;
    //이 Fragment가 화면에 보여줄 뷰를 만들어서 리턴해주면 액티비티가 보여줌
    //이를 위해 자동으로 호출되는 콜백메소드 : onCreateView
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //fragment_my.xml 에 설계한 뷰를 객체를 생성하여 리턴
        //ViewGroup container = 플래그먼트가 붙을 곳
        View view = inflater.inflate(R.layout.fagment_my, container, false);
        //view = LinearLayout
        tv = view.findViewById(R.id.tv);
        btn = view.findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tv.setText("플래그먼트 나 바뀐다");
            }
        });
        
        return view;
    }
}

MainActivity ma = (MainActivity) getActivity();
플래그 먼트 안에서 액티비티 부르는 법
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:background="#FFFFFF00">
    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView inside MyFragment"
        android:textColor="@color/black"
        android:padding="8dp"/>
    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="change Text"/>
    <Button
        android:id="@+id/btn2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="chage Text for MainActivity"
        android:backgroundTint="@color/black"/>
</LinearLayout>
package com.bsj0420.ex30fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class MyFragment extends Fragment {
    TextView tv;
    Button btn, btn2;
    //이 Fragment가 화면에 보여줄 뷰를 만들어서 리턴해주면 액티비티가 보여줌
    //이를 위해 자동으로 호출되는 콜백메소드 : onCreateView
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //fragment_my.xml 에 설계한 뷰를 객체를 생성하여 리턴
        //ViewGroup container = 플래그먼트가 붙을 곳
        View view = inflater.inflate(R.layout.fagment_my, container, false);
        //view = LinearLayout
        tv = view.findViewById(R.id.tv);
        btn = view.findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tv.setText("플래그먼트 나 바뀐다");
            }
        });
        //Main에 있는 Text 바꾸기
        btn2 = view.findViewById(R.id.btn2);
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //플래그먼트.java 안에서 액티비티를 소환해야한다
                MainActivity ma = (MainActivity) getActivity(); //플래그 먼트 안에서 액티비티 부르는 법
                ma.tv.setText("Good");
            }
        });
        
        return view;
    }
}

FragmentManager manager = getSupportFragmentManager();
반드시 서포트 버전!
<?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"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">
    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView inside MainAtivity"
        android:textColor="@color/black"
        android:padding="8dp"
        />
    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="chage Text"/>
    <!--
    fragment의 것 제어하기 위한 버튼
    -->
    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="change my Fragment"
        android:backgroundTint="#FFFF0000"
        />
    <!--
     fragment로 화면의 한 조각을 만들기 : XML에 붙이기
     => 이 액티비티와 완전 한몸이 돼서 뜯어낼 수 없다, 동적제어 불가
     add, remove, replace 안됨
     -->
    <fragment
        android:id="@+id/frag_my"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.bsj0420.ex30fragment.MyFragment"
        tools:layout="@layout/fagment_my"/>
</LinearLayout>
package com.bsj0420.ex30fragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
    TextView tv;
    Button btn, btn2;
    //플래그먼트
    MyFragment myFragment;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = findViewById(R.id.tv);
        btn = findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tv.setText("Nice to meet you");
            }
        });
        //플래그먼트 제어하기
        btn2 = findViewById(R.id.btn2);
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //내 플래그먼트 찾아서 참조
                //플래그먼트는 새로 추가된 기능임 화면에 보여줄 것들이 많이지면서 뷰를 여러개 나눠 제어 할 필요성 때문에 나옴
                //액티비티는 플래그먼트와 완전 분리, 그래서 플래그먼트 관리하는 별도의 관리자 따로 줌
                //Fragment 관리자 소환 : FragmentManager
                FragmentManager manager = getSupportFragmentManager(); //반드시 서포트 버전!
                myFragment = (MyFragment) manager.findFragmentById(R.id.frag_my);
                myFragment.tv.setText("메인에서 바꾸기!");
            }
        });
    }
}
💡 Transaction
롤백 기능이 있는 프로세스
중간에 코드가 실행이 안되면 처음으로 돌아감
ex) 송금

fragment 보일 공간 ViewGrop으로 준비****
<?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:orientation="vertical"
    android:padding="16dp"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="추가"
        android:textAllCaps="false"/>
    <!--
        프래그먼트가 보여질 ViewGrop 준비
     -->
    <LinearLayout
        android:id="@+id/container_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    </LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <AnalogClock
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>
package com.bsj0420.ex31fragmentwithjava;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class MyFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_my, container, false);
            return view;
    }
}
① 프래그 먼트 시작
FragmentTransaction transaction =manager.beginTransaction();
② 하고 싶은 프래그 먼트 동작 추가 (add, remove, replace)
③ 작업 완료
transaction.commit();
package com.bsj0420.ex31fragmentwithjava;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
    Button btn;
    //플래그먼트 제어용 매니저
    FragmentManager manager ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //프래그먼트 관리자 소환
        manager = getSupportFragmentManager();
        btn = findViewById(R.id.btn);
        //버튼 누르면 플래그 먼트 추가!
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //아이디가 container_fragment인 뷰 그룹에 myFragment붙이기
                //프래그먼트에 동적(add, remove, replace) 작업 시작
                //add 해보기
                FragmentTransaction transaction =manager.beginTransaction(); //롤백 기능이 있는 프로세스
                //프래그 먼트 동작 추가
                transaction.add(R.id.container_fragment, new MyFragment());
                //(프래그먼트 붙을곳, 내가 만든 프래그먼트 객체)
                //뒤로가기 버튼 눌렀을 떄 추가 이전 상태로 돌아가려면
                transaction.addToBackStack(null);
                //작업 완료
                transaction.commit();
            }
        });
    }
}

① tab누르면 나올 Fragment 화면과 자바파일 만들기
② FragmentStateAdapter 를 상속받은 Adapter.java 만들기
③ MainActivity.layout에서 Adapter로 만든 Fragment 들어올 자리 만들어주기
④ TabLayoutMediator (tab레이아웃과 pager의 중재자)를 이용해서 화면 set하기
tab레이아웃과 pager의 중재자

현재 각각 3개씩 생성

① extends Fragment
② onCreateView() 메소드에서 inflater로 xml 파일 읽어옴
③ onCreateView가 실행 된 후 만들어진 view에 여러가지 설정 작업을 위해 실행되는 콜백 메소드 :: onViewCreated()

package com.bsj0420.ex32fragmentpager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class Tab1Fragment extends Fragment {
    TextView tv;
    Button btn;
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_tab1, container,false);
        return view;
    }
    //onCreateView가 실행 된 후 만들어진 view에 여러가지 설정 작업을 위해 실행되는 콜백 메소드 :: onViewCreated
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        tv = view.findViewById(R.id.tv);
        btn = view.findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tv.setText("안녕하세요");
            }
        });
    }
}
package com.bsj0420.ex32fragmentpager;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
public class MyAdapter extends FragmentStateAdapter {
    //bind는 필요없음
    //반드시 생성자로 FragmentMAnager를 꼭 받아야함!!!!
    //현재 이 코드는 대량의 데이터를 만드는 게 아니고 프래그먼트 3개만 생성하는 adapter 
    //프래그먼트 3개 받을 배열 만들어 놓기
    Fragment[] fragments = new Fragment[3];
    
    public MyAdapter(@NonNull FragmentActivity fragmentActivity) {
        super(fragmentActivity);
		// 생성자에서 배열 초기화 
        // 탭화면을 각각 연결해줌!
        fragments[0] = new Tab1Fragment();
        fragments[1] = new Tab2Fragment();
        fragments[2] = new Tab3Fragment();
    }
    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return fragments[position]; //position 은 현재 만들어야할 index번호
    }
    @Override
    public int getItemCount() {
        return fragments.length;
    }
}
또한 Tab레이아웃 (com.google.android.material.tabs.TabLayout) 키워드를 통해 탭 레이아웃 지정
<?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"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <!-- Tab만들기   -->
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
    <!-- 프레그먼트 들어올 곳 -->
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"/>
</LinearLayout>
① 참조변수로 불러오기
② 참조변수와 layout id 연결
③  TabLayoutMediator 탭 레이아웃과 뷰 페이저를 연동 
onConfigureTab() 메소드는 탭의 숫자만큼 호출된다
④ mediator.attach(); 탭과 뷰 붙여주기!
package com.bsj0420.ex32fragmentpager;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
public class MainActivity extends AppCompatActivity {
    ViewPager2 pager2;
    MyAdapter adapter;
    TabLayout tabLayout;
    //문자열 배열 만들기 (탭의 타이틀 넣을 배열)
    String[] tabTitle = {"TAB1","TAB2","TAB3"};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pager2 = findViewById(R.id.pager);
        adapter = new MyAdapter(this);
        pager2.setAdapter(adapter);
        tabLayout= findViewById(R.id.tab_layout);
        //*** 탭 레이아웃과 뷰 페이저를 연동하기 - 중재자(TabLayoutMediator) 객체이용
        TabLayoutMediator mediator = new TabLayoutMediator(tabLayout, pager2, new TabLayoutMediator.TabConfigurationStrategy() {
            @Override
            public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) { //pager가 만든 탭 숫자만큼 호출
                //탭 이름 설정 하는 곳
                tab.setText(tabTitle[position]);
            }
        });
        //중재자 객체를 붙이기
        mediator.attach();
    }
}