Android SharedPreferences Tutorial and Example

Create an Android navigation drawer with fragments

A navigation drawer gives an Android app a compact way to expose several destinations without crowding the main screen. When the user taps the menu icon, a panel slides in from the left, displaying items such as Home, Favourites, Settings, and Help. Each selection can replace the current content with a Fragment while the activity keeps control of the drawer itself.

This pattern suits many practical apps, including a local events guide for Sydney, a public transport companion for Melbourne, or a café finder for Brisbane. In this tutorial, you will build the drawer with AndroidX, Material components, Kotlin, and XML layouts, then connect each menu item to a separate fragment.

Set up the Android project

Create an Android Studio project using a standard Views-based activity. Make sure the app uses AndroidX and add the Material Components dependency to the module-level build.gradle file:

dependencies {
    implementation("androidx.core:core-ktx:1.13.1")
    implementation("androidx.appcompat:appcompat:1.7.0")
    implementation("androidx.fragment:fragment-ktx:1.8.2")
    implementation("com.google.android.material:material:1.12.0")
}

Use a theme derived from a Material theme, such as Theme.Material3.DayNight.NoActionBar, so the toolbar and drawer have consistent colours and typography. A NoActionBar theme is useful because the activity will provide its own MaterialToolbar, which becomes the visible control for opening and closing the drawer.

Create three Kotlin fragments named HomeFragment, FavouritesFragment, and SettingsFragment. Each can initially contain a simple TextView. Later, these screens could display train alerts for Perth, saved weekend markets in Adelaide, or settings for an app used by customers across Australia.

Design the drawer layout

Replace the activity layout with a DrawerLayout. Its first child is the main content area, containing the toolbar and a FragmentContainerView. Its second child is a NavigationView, which slides over the content when the drawer opens.

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.google.android.material.appbar.MaterialToolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:title="Home" />

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/fragmentContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navigationView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>

The layout_gravity value of start allows the drawer to respect left-to-right and right-to-left layouts. Keep the drawer width at wrap_content, or apply a suitable maximum width in a custom dimension resource so it does not dominate large tablet screens.

Create res/layout/nav_header.xml for a compact header. It might show the application name, a user avatar, and a short account label. For a local discovery app, a header such as “Explore Australia” can establish the app’s purpose without taking too much vertical space.

Add menu items and fragments

Create res/menu/drawer_menu.xml and define the destinations. Use stable IDs because the Kotlin code will use them to decide which Fragment to display.

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:icon="@drawable/ic_home"
            android:title="Home" />

        <item
            android:id="@+id/nav_favourites"
            android:icon="@drawable/ic_favourite"
            android:title="Favourites" />

        <item
            android:id="@+id/nav_settings"
            android:icon="@drawable/ic_settings"
            android:title="Settings" />
    </group>
</menu>

The single checkable behaviour highlights the active destination and helps users understand where they are. Keep labels short and familiar. Australian users may access the app outdoors, on a tram in Melbourne, or while walking through a busy Sydney station, so the menu should be easy to scan quickly.

A simple fragment layout can contain a message while the navigation structure is being tested:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/screenTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textSize="22sp" />
</FrameLayout>

In a real project, each Fragment can use its own layout. HomeFragment might load current events, FavouritesFragment might read saved records from SQLite, and SettingsFragment might expose notification preferences stored with SharedPreferences.

Connect selections in the activity

In MainActivity.kt, obtain references to the drawer, toolbar, and NavigationView. An ActionBarDrawerToggle supplies the hamburger icon and synchronises its animation with the drawer.

class MainActivity : AppCompatActivity() {

    private lateinit var drawerLayout: DrawerLayout
    private lateinit var navigationView: NavigationView
    private lateinit var toolbar: MaterialToolbar

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

        drawerLayout = findViewById(R.id.drawerLayout)
        navigationView = findViewById(R.id.navigationView)
        toolbar = findViewById(R.id.toolbar)

        setSupportActionBar(toolbar)

        val toggle = ActionBarDrawerToggle(
            this,
            drawerLayout,
            toolbar,
            R.string.open_drawer,
            R.string.close_drawer
        )

        drawerLayout.addDrawerListener(toggle)
        toggle.syncState()

        navigationView.setNavigationItemSelectedListener { item ->
            when (item.itemId) {
                R.id.nav_home -> {
                    showFragment(HomeFragment(), "Home")
                    true
                }
                R.id.nav_favourites -> {
                    showFragment(FavouritesFragment(), "Favourites")
                    true
                }
                R.id.nav_settings -> {
                    showFragment(SettingsFragment(), "Settings")
                    true
                }
                else -> false
            }
        }

        if (savedInstanceState == null) {
            navigationView.setCheckedItem(R.id.nav_home)
            showFragment(HomeFragment(), "Home")
        }
    }

Add a helper method to replace the current screen and close the drawer:

    private fun showFragment(fragment: Fragment, title: String) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.fragmentContainer, fragment)
            .commit()

        toolbar.title = title
        drawerLayout.closeDrawer(GravityCompat.START)
    }
}

Calling showFragment after a menu selection ensures that the toolbar title changes with the content. The savedInstanceState check prevents the initial Home Fragment from being inserted again after a configuration change, such as rotating the device.

Improve state, accessibility, and testing

A basic replacement transaction does not add screens to the back stack. That is often correct for a primary navigation drawer: selecting Home, Favourites, and Settings changes the main destination rather than creating a long history. If a destination has deeper detail pages, those pages can use separate navigation or explicitly call addToBackStack.

Add the required strings to res/values/strings.xml:

<string name="open_drawer">Open navigation drawer</string>
<string name="close_drawer">Close navigation drawer</string>

Use meaningful content descriptions for custom icons, maintain sufficient colour contrast, and check that the drawer can be operated with TalkBack. Clear labels matter for users with different accessibility needs, including people using Android devices while navigating unfamiliar places or public services. Avoid putting essential actions exclusively inside the drawer if they need to remain visible during frequent use.

Run the app on an emulator and a physical device. Check opening and closing with the toolbar icon, selecting every menu item, rotating between portrait and landscape, and pressing the system Back button. Test different screen sizes and Android versions, including a device configured for Australian English. If the app displays local prices or venue details, verify Australian dollar formatting, suburb names, and time zones such as Australia/Sydney rather than relying on a fixed UTC offset.

The finished structure separates responsibilities cleanly: DrawerLayout manages the sliding panel, NavigationView presents destinations, the activity coordinates selection, and Fragments own individual screens. That arrangement remains easy to extend when the application grows from a small tutorial project into a production app for users in Sydney, Melbourne, Brisbane, or elsewhere in the Australian market.