BottomNavigationViewとTablayout+ViewPagerを関連付ける．(メモ)

# はじめに

BottomNavigationViewとTablayoutを組み合わせたサンプルを置いておきます．
こういう機能を実装したアプリはよく見かけるので参考になれば幸いです．

<img width="300dp" alt="device.gif" src="https://qiita-image-store.s3.amazonaws.com/0/129578/fc87620d-9c21-5ebe-1f0b-f891cc859516.gif">

# 参考
今回のBottomNavigationViewのライブラリ
https://github.com/sephiroth74/Material-BottomNavigation

BottomNavigationViewとTablayout+ViewPagerの結合
https://medium.com/@maydin/nested-viewpager-in-bottomnavigationview-a384b7068e92



# 実装

## build.gradle

```xml:build.gradle(app)
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support:design:25.3.1'
    compile 'com.android.support:support-vector-drawable:25.3.1'
    compile 'com.android.support:support-v4:25.3.1'
    testCompile 'junit:junit:4.12'
    compile 'it.sephiroth.android.library.bottomnavigation:bottom-navigation:2.0.1-rc1'
}
```
## BottomNavigationView
今回はライブラリを用いさせていただきました．
デザインがかわいらしいですね！
まず，BottomNavigationViewのアイコンやら(menu)を定義します．

```xml:menu/navigation.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"
    app:bbn_rippleColor="#33ffffff"
    app:bbn_badgeColor="#FFFF0000">

    <item
        android:color="@color/colorPrimary"
        android:id="@+id/navigation_home"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/title_home" />

    <item
        android:color="@android:color/holo_green_dark"
        android:id="@+id/navigation_dashboard"
        android:icon="@drawable/ic_dashboard_black_24dp"
        android:title="@string/title_dashboard" />

    <item
        android:color="@android:color/holo_orange_dark"
        android:id="@+id/navigation_notifications"
        android:icon="@drawable/ic_notifications_black_24dp"
        android:title="@string/title_notifications" />
</menu>
```

載せるアイコンは何でもいいですが，今回はdrawable以下に配置しています．
以下のサイトはIconがいっぱいあります．

Material Design Icons
https://materialdesignicons.com/icon/fire

これで，BottomNavigationViewの設定は出来ました．
次はこれをMain画面に配置しましょう．

## Main画面

```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:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.bnviewpager.viewpageriteminbnv.MainActivity">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <FrameLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/navigation" />
        <it.sephiroth.android.library.bottomnavigation.BottomNavigation
            app:bbn_badgeProvider="@string/bbn_badgeProvider"
            app:layout_behavior="@string/bbn_phone_view_behavior"
            android:id="@+id/navigation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            app:bbn_entries="@menu/navigation" />
    </RelativeLayout>
</LinearLayout>
```

`it.sephiroth.android.library.bottomnavigation.BottomNavigation`が今回利用するBottomNavigationViewです．

つぎに本文です．

```java:MainActivity.java
package com.bnviewpager.viewpageriteminbnv;

import android.os.Bundle;
import android.support.annotation.IdRes;
import it.sephiroth.android.library.bottomnavigation.BottomNavigation;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private BottomNavigation BottomNavigationView;

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

        BottomNavigationView = (BottomNavigation) findViewById(R.id.navigation);
        BottomNavigationView.setOnMenuItemClickListener(new BottomNavigation.OnMenuItemSelectionListener() {
            @Override
            public void onMenuItemSelect(@IdRes int i, int i1, boolean b) {
                switch (i1) {
                    case 0:
                        replaceFragment(FirstFragment.newInstance());//Fragmentを入れ替える
                        break;
                    case 1:
                        replaceFragment(SecondFragment.newInstance());//Fragmentを入れ替える
                        break;
                    case 2:
                        replaceFragment(ViewPagerFragment.newInstance());//Fragmentを入れ替える
                        break;
                }
            }
            @Override
            public void onMenuItemReselect(@IdRes int i, int i1, boolean b) {
            }
        });

        addFragment(FirstFragment.newInstance());//最初はadd

    }

    private void addFragment(Fragment newFragment){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.add(R.id.fragment_container, newFragment).commit();
    }

    private void replaceFragment(Fragment newFragment) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.fragment_container, newFragment).commit();//R.id.fragment_containerのを代える
    }
}
```

BottomNavigationViewが押されたらFragmentを交換します．
このMainが一番重要です．
後はFragmentを結びつけるだけです．
replaceするFragmentを以下に示します．

**BottomNavigationView　1つめのボタン**

```java:FirstFragment.java
package com.bnviewpager.viewpageriteminbnv;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FirstFragment extends Fragment {

    public static FirstFragment newInstance() {
        FirstFragment fragment = new FirstFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_first, container, false);
    }
}
```

```xml:fragment_first.xml
<FrameLayout 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="com.bnviewpager.viewpageriteminbnv.FirstFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Home" />

</FrameLayout>
```

**BottomNavigationView　2つめのボタン**

```java:SecondFragment.java
package com.bnviewpager.viewpageriteminbnv;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class SecondFragment extends Fragment {

    public static SecondFragment newInstance() {
        SecondFragment fragment = new SecondFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_second, container, false);
    }
}
```

```xml:fragment_second.xml
<FrameLayout 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="com.bnviewpager.viewpageriteminbnv.SecondFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Dashboard" />

</FrameLayout>
```

**BottomNavigationView　3つめのボタン**
ここでは，Fragmentの中にtablayoutとviewpagerを実装します．

```java:ViewPagerFragment.java
package com.bnviewpager.viewpageriteminbnv;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class ViewPagerFragment extends Fragment {

    ViewPager viewPager;
    ViewPagerAdapter viewPagerAdapter;

    public static ViewPagerFragment newInstance() {
        ViewPagerFragment fragment = new ViewPagerFragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_view_pager, container, false);
        viewPager = (ViewPager) view.findViewById(R.id.viewpager);
        viewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
        viewPager.setAdapter(viewPagerAdapter);
        return view;
    }


    public static class ViewPagerAdapter extends FragmentStatePagerAdapter {
        private static final int NUM_ITEMS = 2;

        public ViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public int getCount() {
            return NUM_ITEMS;
        }

        @Override
        public Fragment getItem(int position) {
            if(position == 0){
                return Fragment1.newInstance();
            }
            else {
                return Fragment2.newInstance();
            }
        }

        @Override
        public CharSequence getPageTitle(int position) {

            if(position == 0){
                return "flagment1";
            }
            else {
                return "flagment2";
            }
        }
    }
}
```

tablayoutとviewpagerを定義します．

```xml:fragment_view_pager.xml
<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.TabLayout
        android:id="@+id/pager_title_strip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:background="#EEEEEE"
        android:paddingBottom="4dp"
        android:paddingTop="4dp"
        android:textColor="#fff" />
</android.support.v4.view.ViewPager>
```

今回はtab2つです．
次に，tablayoutと結びつけるFragmentです．

**tab 1つめ**

```java:Fragment1.java
package com.bnviewpager.viewpageriteminbnv;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment1 extends Fragment {

    public static Fragment1 newInstance() {
        Fragment1 fragment = new Fragment1();
        return fragment;
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_fragment1, container, false);
    }
}
```

```xml:fragment_fragment1.xml
<?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">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Fragment1" />

</LinearLayout>
```


**tab 2つめ**

```java:Fragment2.java
package com.bnviewpager.viewpageriteminbnv;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class Fragment2 extends Fragment {

    public static Fragment2 newInstance() {
        Fragment2 fragment = new Fragment2();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_fragment2, container, false);
    }
}
```

```xml:fragment_fragment1.xml
<?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">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Fragment2" />

</LinearLayout>
```

以上です．

# おわりに
Tablayoutを全て実装終えてから，親要素?のBottomNavigationViewを**新たに**関連付けるのに本当に苦戦しました...
アプリを作成していく上では一回全体像を把握した方がいいですね(わかりきったことですが...):cloud::disappointed_relieved:

今回のコードの全貌です！
https://github.com/hisakioomae/BottomNavigationView_Nested_Viewpager
最後までお付き合いいただきありがとうございました．