--- title: 【Android/Java】下タブで遷移するレイアウト tags: android --- # はじめに タブを使った画面を作成する. # プロジェクトの作成 まず,普通にEmpty Activityで画面を作成する. # タブに配置するアイコンの生成 タブに配置するアイコンは,drawableから読み込む必要がある.Android studioには,タブに配置するためのアイコンがたくさん用意されているため,今回はそれを使ってみる.drawableフォルダを右クリックし,NewからImage Assetを選択する.Image Assetを以下のように設定した. ![](https://i.imgur.com/hPVRLsX.png) Nextをクリックし,次の画面では保存する場所を聞かれるが,デフォルトのままでよい. 同様にして,表示したいタブの数だけアイコンを設定し,保存する. # 下タブに表示するメニューを作成 app/res/menu/navigation.xml を作成する.android:iconには下タブに表示する項目のアイコン,android:titleには、下タブに表示する項目のタイトルを指定する. ```xml <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/navigation_home" android:icon="@drawable/ic_tab_home" android:title="home" /> <item android:id="@+id/navigation_search" android:icon="@drawable/ic_tab_search" android:title="search"/> </menu> ``` # タブのアイコンの色を設定 そのまま配置してしまうと,デフォルトの色(紫)になってしまう.ここでは,アイコンの色をTwitterの色に合わせてみる.colorディレクトリを作成し,その中にbottom_nav_color.xmlを作成する. ```xml <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="#00acee" android:state_checked="true"/> <item android:color="#777777" android:state_checked="false"/> </selector> ``` これを,BottomNavigationViewに設定する.次で説明する. # BottomNavigationViewを配置 gradleに以下を追加 ``` implementation 'com.google.android.material:material:1.2.1' ``` activity_main.xmlにBottomNavigationViewを配置する. ```xml <androidx.constraintlayout.widget.ConstraintLayout 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"> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottomNavigation" android:layout_height="64dp" android:layout_width="0dp" android:background="@android:color/white" app:menu="@menu/navigation" app:itemIconTint="@color/bottom_nav_color" app:itemTextColor="@color/bottom_nav_color" app:labelVisibilityMode="labeled" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout> ``` # ViewPagerの配置 今回は,下タブの選択でViewPagerを切り替えたいため,ViewPagerを配置する.先ほどのレイアウトに追加する. ```xml <androidx.constraintlayout.widget.ConstraintLayout 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.viewpager.widget.ViewPager android:id="@+id/viewPager" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toTopOf="@+id/bottomNavigation" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottomNavigation" android:layout_height="64dp" android:layout_width="0dp" android:background="@android:color/white" app:menu="@menu/navigation" app:itemIconTint="@color/bottom_nav_color" app:itemTextColor="@color/bottom_nav_color" app:labelVisibilityMode="labeled" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout> ``` # Fragmentの用意 ViewPagerで切り替えて表示するためのFragmentを用意する.今回は特に機能は実装していない.Fragmentは,レイアウトファイルとjavaクラスをそれぞれ普通に作成する.Activityは,`[New] > [Activity]`のように作成するが,Fragmentの場合は,普通にJavaクラスとレイアウトファイルをそれぞれ作成する. fragment_home.xml ```xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Home" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> ``` XMLで定義したウィジェットをプログラムで使う場合,Activityではなく,以下のようにフラグメントから呼び出す.少し呼び出し方がActivityのときと違うので注意する. HomeFragment.java ```java public class HomeFragment extends Fragment { private TextView textView; @Override public void onAttach(@NonNull Context context) { super.onAttach(context); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_home, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // textView = view.findViewById(R.id.textView); // textView.setText("こんにちは"); } } ``` ViewPagerでFragmentを表示するために,アダプターを定義する. MainFragmentStatePagerAdapter.java ```java public class MainFragmentStatePagerAdapter extends FragmentStatePagerAdapter { public MainFragmentStatePagerAdapter(@NonNull FragmentManager fm, int behavior) { super(fm, behavior); } @NonNull @Override public Fragment getItem(int position) { if (position == 0){ return new HomeFragment(); } else { return new SearchFragment(); } } // Fragmentの数を戻り値として指定する. @Override public int getCount() { return 2; } } ``` Fragmentの作り方は上で説明したが,検索画面のフラグメントも同様に用意する. fragment_search.xml ```xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="SEARCH" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> ``` SearchFragment.java ```java public class SearchFragment extends Fragment { @Override public void onAttach(@NonNull Context context) { super.onAttach(context); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_search, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); } } ``` # ViewPagerとBottomNavigationを設定 呼び出し元から,ViewPagerとBottomNavigationを設定する.ViewPagerの設定では,スワイプでFragmentを切り替えた際に、下タブの選択されている項目が切り替わるようにしている.BottomNavigationの設定では、下タブを選択した際に、Fragmentが切り替わるようにしている. MainActivity.java ```java public class MainActivity extends AppCompatActivity { private BottomNavigationView navigationView; private ViewPager viewPager; private FragmentManager manager; private MainFragmentStatePagerAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); supportRequestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); navigationView = findViewById(R.id.bottomNavigation); manager = getSupportFragmentManager(); viewPager = findViewById(R.id.viewPager); adapter = new MainFragmentStatePagerAdapter(manager, FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if (position == 0){ navigationView.getMenu().findItem(R.id.navigation_home).setChecked(true); } else if (position == 1){ navigationView.getMenu().findItem(R.id.navigation_search).setChecked(true); } } @Override public void onPageScrollStateChanged(int state) { } }); navigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { int id = item.getItemId(); switch (id){ case R.id.navigation_home: viewPager.setCurrentItem(0); break; case R.id.navigation_search: viewPager.setCurrentItem(1); break; } return true; } }); viewPager.setAdapter(adapter); } } ```