Implementing DrawerLayout for Tablet and BottomNavigationView for Mobile Screens in Android


1. Introduction

In Android development, it's essential to design user interfaces that adapt to various screen sizes, including mobile phones and tablets. A common design pattern involves using a BottomNavigationView for mobile screens and a DrawerLayout for tablets. This approach ensures optimal navigation experiences tailored to the device's screen size.

This document outlines the implementation of a DrawerLayout for tablet screens and a BottomNavigationView for mobile screens in an Android application, along with best practices and code examples.

2. Understanding DrawerLayout and BottomNavigationView

2.1 DrawerLayout

DrawerLayout is a layout that allows developers to implement a sliding drawer that can contain navigation items. It is typically used in tablet designs to utilize the larger screen space effectively.

2.2 BottomNavigationView

BottomNavigationView is a bar at the bottom of the screen that provides easy access to primary navigation destinations. It is ideal for mobile devices where space is limited.

3. Adaptive UI Design

3.1 Screen Size Configuration

To differentiate between mobile and tablet devices, Android developers use configuration qualifiers such as sw600dp (smallest width of 600dp) for tablets. This allows the app to load different layouts depending on the screen size.

3.2 XML Layout Files

  1. Mobile Layout (default):

    • Use a BottomNavigationView at the bottom of the screen.
  2. Tablet Layout (res/layout-sw600dp):

    • Use a DrawerLayout with a navigation drawer.

3.3 Example Layout Files

Main Layout (Mobile) - res/layout/activity_main.xml

<androidx.drawerlayout.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Main Content -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- Bottom Navigation View -->
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:menu="@menu/bottom_nav_menu" />

</androidx.drawerlayout.widget.DrawerLayout>

Main Layout (Tablet) - res/layout-sw600dp/activity_main.xml

<androidx.drawerlayout.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Toolbar for Tablet -->
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary" />

    <!-- Main Content -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- Navigation Drawer -->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/drawer_menu" />

</androidx.drawerlayout.widget.DrawerLayout>

4. Java Implementation

4.1 MainActivity.java

This is the main activity where the DrawerLayout and BottomNavigationView are managed. The code below demonstrates how to handle both navigation patterns based on the device type.

import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationView;

public class MainActivity extends AppCompatActivity {

    private DrawerLayout drawerLayout;
    private NavigationView navigationView;
    private BottomNavigationView bottomNavigationView;
    private ActionBarDrawerToggle toggle;

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

        // Toolbar setup for Drawer
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        drawerLayout = findViewById(R.id.drawer_layout);
        navigationView = findViewById(R.id.nav_view);
        bottomNavigationView = findViewById(R.id.bottom_navigation);

        // Setup Drawer Toggle
        toggle = new ActionBarDrawerToggle(
                this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawerLayout.addDrawerListener(toggle);
        toggle.syncState();

        // Drawer Menu Item Selection Handling
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                int id = item.getItemId();

                if (id == R.id.nav_home) {
                    // Handle Home navigation
                } else if (id == R.id.nav_profile) {
                    startActivity(new Intent(getApplicationContext(), ProfileActivity.class));
                } else if (id == R.id.nav_settings) {
                    startActivity(new Intent(getApplicationContext(), SettingsActivity.class));
                } else if (id == R.id.nav_help) {
                    startActivity(new Intent(getApplicationContext(), HelpActivity.class));
                }

                drawerLayout.closeDrawer(GravityCompat.START);
                return true;
            }
        });

        // Bottom Navigation Setup
        bottomNavigationView.setSelectedItemId(R.id.nav_home); // Home page selected by default
        bottomNavigationView.setOnItemSelectedListener(menuItem -> {
            int id = menuItem.getItemId();
            if (id == R.id.nav_home) {
                // Empty when currently selected.
                return true;
            } else if (id == R.id.nav_news) {
                startActivity(new Intent(getApplicationContext(), NewsActivity.class)); // Starts the News activity
                overridePendingTransition(0, 0); // Removes the sliding animation
                finish();
                return true;
            } else if (id == R.id.nav_settings) {
                startActivity(new Intent(getApplicationContext(), SettingsActivity.class));
                overridePendingTransition(0, 0);
                finish();
                return true;
            }
            return false;
        });

        // Determine if running on a tablet
        boolean isTablet = getResources().getBoolean(R.bool.isTablet);
        if (isTablet) {
            bottomNavigationView.setVisibility(View.GONE); // Hide BottomNavigationView on tablets
        } else {
            drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); // Lock the Drawer closed on phones
        }
    }

    @Override
    public void onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (toggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

4.2 Explanation

  • Drawer Toggle: The ActionBarDrawerToggle is used to open and close the navigation drawer with the hamburger icon.

  • Responsive Design: The application checks if it's running on a tablet or mobile. On tablets, the BottomNavigationView is hidden, and the drawer is unlocked. On mobile, the drawer is locked, and the BottomNavigationView is visible.

  • Navigation Handling: Both the drawer and bottom navigation handle user navigation seamlessly.

5. Testing and Validation

5.1 Testing on Multiple Devices

Testing should be conducted on both tablet and mobile devices to ensure the layouts adapt correctly to different screen sizes. This includes checking:

  • Drawer behavior on tablets.

  • Bottom navigation visibility on mobile devices.

  • Correct handling of back navigation.

5.2 Unit Testing and UI Testing

Unit tests should be written to ensure navigation actions are handled as expected. UI testing using Espresso can validate the visibility and interactions of UI elements like the drawer and bottom navigation.

6. Conclusion

Implementing a DrawerLayout for tablets and BottomNavigationView for mobile screens allows Android applications to provide a user-friendly and device-specific navigation experience. By leveraging configuration qualifiers and adaptive layouts, developers can create applications that look and function well on both large and small screens.

7. References


This research document should give you a comprehensive understanding of how to implement adaptive navigation patterns in an Android application, catering to both mobile and tablet