Implementing a Swipeable Bottom Navigation Bar in Android

TheJuniorDeveloper
The Junior Developer
3 min readAug 10, 2024

Most popular Android applications, such as WhatsApp and Instagram, have integrated a swipeable feature with the Bottom Navigation Bar.

In this tutorial, we’ll guide you through the process of implementing a swipeable Bottom Navigation Bar in an Android application using both Kotlin and Java.

1. Declare dependencies

Add this view pager dependency to your project

 implementation ("androidx.viewpager2:viewpager2:1.1.0")

2. Design the Layout

In this step, we will create the main layout for our activity, which will include both the ViewPager2 for swiping and the BottomNavigationView for navigation.

Create the Main Layout

Create a new layout file named activity_main.xml and add the following XML code:

<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">

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/bottom_navigation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:menu="@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>

Create Bottom Navigation Menu

Next, define the items for your Bottom Navigation Bar in a new menu resource file named bottom_nav_menu.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_home"
android:icon="@drawable/ic_home"
android:title="Home" />
<item
android:id="@+id/navigation_dashboard"
android:icon="@drawable/ic_dashboard"
android:title="Dashboard" />
<item
android:id="@+id/navigation_notifications"
android:icon="@drawable/ic_notifications"
android:title="Notifications" />
</menu>

3. Create Fragments for Each Tab

For each tab in the Bottom Navigation Bar, we’ll create a corresponding fragment. In this example, we’ll create three fragments: HomeFragment, DashboardFragment, and NotificationsFragment.

Create Fragment Layouts

Create the layout files for each fragment:

<!-- res/layout/fragment_home.xml -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Home Fragment" />
</LinearLayout>

Repeat this process for fragment_dashboard.xml and fragment_notifications.xml.

Create Fragment Classes

Next, create the Kotlin or Java classes for each fragment:

In Kotlin:

class HomeFragment : Fragment(R.layout.fragment_home)
class DashboardFragment : Fragment(R.layout.fragment_dashboard)
class NotificationsFragment : Fragment(R.layout.fragment_notifications)

In Java:

public class HomeFragment extends Fragment {
public HomeFragment() {
super(R.layout.fragment_home);
}
}

public class DashboardFragment extends Fragment {
public DashboardFragment() {
super(R.layout.fragment_dashboard);
}
}

public class NotificationsFragment extends Fragment {
public NotificationsFragment() {
super(R.layout.fragment_notifications);
}
}

Step 4: Set Up the ViewPager2 Adapter

To manage the fragments in ViewPager2, we’ll create a ViewPagerAdapter. This adapter will handle which fragment to display based on the current tab.

Create the ViewPagerAdapter Class

Create a new Kotlin or Java class named ViewPagerAdapter .

In Kotlin:

class ViewPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
override fun createFragment(position: Int): Fragment {
return when (position) {
0 -> HomeFragment()
1 -> DashboardFragment()
2 -> NotificationsFragment()
else -> HomeFragment()
}
}

override fun getItemCount(): Int {
return 3 // Number of tabs
}
}

In Java:

public class ViewPagerAdapter extends FragmentStateAdapter {

public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}

@NonNull
@Override
public Fragment createFragment(int position) {
switch (position) {
case 0:
return new HomeFragment();
case 1:
return new DashboardFragment();
case 2:
return new NotificationsFragment();
default:
return new HomeFragment();
}
}

@Override
public int getItemCount() {
return 3; // Number of tabs
}
}

Step 5: Implement Navigation Logic in the MainActivity

Now, it’s time to link the ViewPager2 and the BottomNavigationView in the MainActivity.

Set Up the MainActivity

In your MainActivity, initialize the ViewPager2 and BottomNavigationView, and set up their interactions:

In Kotlin:

class MainActivity : AppCompatActivity() {

private lateinit var viewPager: ViewPager2
private lateinit var bottomNavigationView: BottomNavigationView

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

viewPager = findViewById(R.id.viewPager)
bottomNavigationView = findViewById(R.id.bottom_navigation)

val adapter = ViewPagerAdapter(this)
viewPager.adapter = adapter

// Handle swipe between pages
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
bottomNavigationView.menu.getItem(position).isChecked = true
}
})

// Handle click on BottomNavigationView items
bottomNavigationView.setOnItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home -> viewPager.currentItem = 0
R.id.navigation_dashboard -> viewPager.currentItem = 1
R.id.navigation_notifications -> viewPager.currentItem = 2
}
true
}
}
}

In Java:

public class MainActivity extends AppCompatActivity {

private ViewPager2 viewPager;
private BottomNavigationView bottomNavigationView;

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

viewPager = findViewById(R.id.viewPager);
bottomNavigationView = findViewById(R.id.bottom_navigation);

ViewPagerAdapter adapter = new ViewPagerAdapter(this);
viewPager.setAdapter(adapter);

// Handle swipe between pages
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
bottomNavigationView.getMenu().getItem(position).setChecked(true);
}
});

// Handle click on BottomNavigationView items
bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
switch (item.getItemId()) {
case R.id.navigation_home:
viewPager.setCurrentItem(0);
break;
case R.id.navigation_dashboard:
viewPager.setCurrentItem(1);
break;
case R.id.navigation_notifications:
viewPager.setCurrentItem(2);
break;
}
return true;
});
}
}

Here’s the result

--

--