A must-read for newbies: Android studio sidebar implementation, with source code

Article directory

  • Preface
  • renderings
  • text
    • toolbar is used to define the navigation bar of the application
    • app_bar
    • drawer_layout is used to create sidebar navigation
      • nav_header_draw
    • app:menu=”@menu/activity_main_drawer”
      • activity

Foreword

The content of this article is mainly some summary after I implemented the sidebar. Some of the theories come from the network and AI assistant. If there are any mistakes, please give me some advice.

Renderings



Text

I didn’t find an example that was suitable for novices at first, so I tried the layout of the sidebar that comes with Android studio.

But after using it, I found that there were some things I didn’t want, so I deleted the things I didn’t want and kept what I wanted. My sidebar is a global sidebar, so I made a sidebar. activity to reuse, multiple fragments reuse one sidebar activity. At present, I see more implementation of global sidebar in this form. If you are like me at the beginning, you have no foundation for sidebar. You can try my method next or read my blog. This blog will explain the implementation method of the global sidebar that I know.

I used NavigationView to implement it. When I used NavigationView to implement the sidebar, I found that it mainly contains the content of these parts. Next, we will talk about each part.

toolbar is used to define the navigation bar of the application

The main function of this xml is to define a sidebar layout, which contains a Toolbar as the main title bar of the application, and an AppBarLayout that provides the background and behavior for this bar.
AppBarLayout is used to group one or more application bars and can provide backgrounds and behaviors for these bars
Toolbar can serve as the main title bar of your application and contain a set of menu items and custom actions

<?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:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context=".DrawerActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.MyMall.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@ + id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/Theme.MyMall.PopupOverlay" />

    </com.google.android.material.appbar.AppBarLayout>
</LinearLayout>

xml effect

app_bar

This code defines a layout with a sidebar that contains a toolbar, and the content area is a scrollable frame layout
is a layout in Android that can coordinate the behavior of various other layouts and views within it, such as AppBarLayout and Scrolling UI components
tool_bar.xm is introduced in this xml
There is also a element in , whose scrolling behavior is set to @string/appbar_scrolling_view_behavior. This scrolling behavior causes that when this view (FrameLayout) scrolls, AppBarLayout will scroll with it.

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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=".DrawerActivity">

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

        <include
            layout="@layout/tool_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <FrameLayout
            android:id="@ + id/flContent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

xml effect

drawer_layout is used to create sidebar navigation

This xml is connected to the activity, using the layout, which is used to create sidebar navigation
android:fitsSystemWindows="true": This attribute indicates that the layout will fill the system window and is typically used to create a full-screen experience.
tools:openDrawer="start": This is the instruction to open the sidebar in the toolbar.

There is NavigationView and an include in xml

  • NavigationView is used to create a navigation view for the sidebar, which contains:
    app:headerLayout="@layout/nav_header_draw"Specifies the header layout of the navigation view
    app:menu="@menu/activity_main_drawer" Specifies the menu resource of the navigation view
    android:layout_gravity="start": Attribute specifies that the navigation view should start from the left.
  • app_bar_draw is referenced in include
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        android:id="@ + id/app_bar_draw"
        layout="@layout/app_bar_draw"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <com.google.android.material.navigation.NavigationView
        android:id="@ + id/nav_view"
        android:layout_width="200dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_draw"
        app:menu="@menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>

xml effect

nav_header_draw

This xml is the location of the sidebar

It depends on whether you need it. The default xml file I use can be adjusted according to your needs.

<?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"
    android:layout_width="match_parent"
    android:layout_height="@dimen/nav_header_height"
    android:background="@drawable/side_nav_bar"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@ + id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/nav_header_desc"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        app:srcCompat="@mipmap/ic_launcher_round" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="@string/nav_header_title"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

    <TextView
        android:id="@ + id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/nav_header_subtitle" />
</LinearLayout>

app:menu=”@menu/activity_main_drawer”

Regarding the menu resource of drawer_layout, I wrote an item that can fold and expand the secondary menu.

<menu
    xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@ + id/FirstAge"
            android:title="Home"
            android:visible="true"
            android:icon="@drawable/baseline_arrow_drop_down_24" />

        <item
            android:id="@ + id/Dashboard"
            android:checked="false"
            android:title="Dashboard"
            android:visible="false"
            />
        <item
            android:id="@ + id/StudyTutorial"
            android:checked="false"
            android:title="Learning Tutorial"
            android:visible="false" />
        <item
            android:id="@ + id/VideoTutorials"
            android:checked="false"
            android:title="Video Tutorial"
            android:visible="false" />
    </group>

    <group android:checkableBehavior="single">
        <item
            android:id="@ + id/Commodity"
            android:title="Product"
            android:visible="true"
            android:icon="@drawable/baseline_arrow_drop_down_24"/>
        <item
            android:id="@ + id/ProductList"
            android:checked="false"
            android:title="Product List"
            android:visible="false"/>
        <item
            android:id="@ + id/AddProduct"
            android:checked="false"
            android:title="Add product"
            android:visible="false"/>
        <item
            android:id="@ + id/Category"
            android:checked="false"
            android:title="Product Classification"
            android:visible="false"/>
        <item
            android:id="@ + id/ProductType"
            android:checked="false"
            android:title="Product Type"
            android:visible="false"/>
        <item
            android:id="@ + id/Branding"
            android:checked="false"
            android:title="Brand Management"
            android:visible="false"/>
    </group>

    <group android:checkableBehavior="single">
        <item
            android:id="@ + id/OrderForGoods"
            android:title="Order"
            android:visible="true"
            android:icon="@drawable/baseline_arrow_drop_down_24"/>
        <item
            android:id="@ + id/Orderlist"
            android:checked="false"
            android:title="Order List"
            android:visible="false"/>
        <item
            android:id="@ + id/OrderSettings"
            android:checked="false"
            android:title="Order Settings"
            android:visible="false"/>
        <item
            android:id="@ + id/ReturnApplicationProcessing"
            android:checked="false"
            android:title="Return application processing"
            android:visible="false"/>
        <item
            android:id="@ + id/ReturnReasonSettings"
            android:checked="false"
            android:title="Return Reason Settings"
            android:visible="false"/>
    </group>
    <group android:checkableBehavior="single">
        <item
            android:id="@ + id/Marketing"
            android:title="Marketing"
            android:visible="true"
            android:icon="@drawable/baseline_arrow_drop_down_24"/>
        <item
            android:id="@ + id/ListOfFlashKillingActivities"
            android:checked="false"
            android:title="Flash sale activity list"
            android:visible="false"/>
        <item
            android:id="@ + id/CouponList"
            android:checked="false"
            android:title="Coupon List"
            android:visible="false"/>
        <item
            android:id="@ + id/BrandRecommendation"
            android:checked="false"
            android:title="Brand Recommendation"
            android:visible="false"/>
        <item
            android:id="@ + id/NewProductRecommendation"
            android:checked="false"
            android:title="New product recommendations"
            android:visible="false"/>
        <item
            android:id="@ + id/PopularRecommendation"
            android:checked="false"
            android:title="Popular recommendation"
            android:visible="false"/>
        <item
            android:id="@ + id/SpecialRecommendation"
            android:checked="false"
            android:title="Special Recommendations"
            android:visible="false"/>
        <item
            android:id="@ + id/AdvertisingList"
            android:checked="false"
            android:title="Advertising List"
            android:visible="false"/>
    </group>
    <group android:checkableBehavior="single">
        <item
            android:id="@ + id/LimitsOfAuthority"
            android:title="Permissions"
            android:visible="true"
            android:icon="@drawable/baseline_arrow_drop_down_24"/>
        <item
            android:id="@ + id/UserList"
            android:checked="false"
            android:title="User List"
            android:visible="false"/>
        <item
            android:id="@ + id/RoleList"
            android:checked="false"
            android:title="Character List"
            android:visible="false"/>
        <item
            android:id="@ + id/MenuList"
            android:checked="false"
            android:title="menu list"
            android:visible="false"/>
        <item
            android:id="@ + id/ResourceList"
            android:checked="false"
            android:title="Resource List"
            android:visible="false"/>
    </group>
</menu>

activity

My sidebar menu can be clicked to collapse/expand the secondary menu. I pasted the source code of the sidebar activity for reference.

import android.app.Dialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import com.google.android.material.navigation.NavigationView;
import com.google.gson.Gson;

public class DrawerActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {<!-- -->
    private static final String TAG = "DrawerActivity";

    //Define an id enumeration
    //When a variable has several fixed possible values, it can be defined as an enumeration type, such as seasonal gender
    public enum manualNavID {<!-- -->
        DASHBOARD_ID,
        ACCOUNTS_ID
    }

    //Interface control class member variables
    // TODO:DrawerLayout Baidu looks at its usage. This library is a bit outdated. It is best to understand the usage of this class under the Androidx library. It should be the same.
    private DrawerLayout drawerLayout;
    // TODO:NavigationView Baidu looks at its use. This library is a bit outdated. It is best to understand the usage of this class under the Androidx library. It should be the same.
    private NavigationView navigationView;

    private Toolbar toolbar;
    // TODO:ActionBarDrawerToggle Baidu has a look at its usage. This library is a bit outdated. It is best to understand the usage of this class under the Androidx library. It should be the same.
    private ActionBarDrawerToggle toggle;

    // TODO: In the new version, SharedPreferences is gradually deprecated. I will write an example later to implement these functions without using SharedPreferences.
    private SharedPreferences userPreferences;

    //TODO:Gson - Java's JSON class library
    private Gson gson;
    private String json;

    private ContactsContract.Profile userProfile;

    //TODO: Pop-up windows are rarely used and can be ignored.
    privateDialog depositDialog;
    //TODO:Spinner Baidu to see how he is used
    private Spinner spnAccounts;
    //TODO:ArrayAdapter Baidu to see its use
    // TODO: ArrayAdapter is a specific implementation of BaseAdapter. It can be constructed directly using generics and can directly add and delete Adapter like List.
    // TODO: Think about whether List<Account> can be used here
    private ArrayAdapter<User> accountAdapter;
    private EditText edtDepositAmount;
    private Button btnCancel;
    private Button btnDeposit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {<!-- -->
        super.onCreate(savedInstanceState);
        setContentView(R.layout.drawer_layout);

        drawerLayout = findViewById(R.id.drawer_layout);

        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //TODO:
        //Action bar drawer switching, see the blog for this class ActionBarDrawerToggle
        toggle = new ActionBarDrawerToggle(
                this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        //Using ActionBarDrawerToggle is used by DrawerLayout to control the display of ToolBar.
        drawerLayout.addDrawerListener(toggle);
        //Synchronization status
        toggle.syncState();

        // NavigationView
        navigationView = findViewById(R.id.nav_view);
        //Used to set the listener for the bottom navigation bar option to be selected. When the user clicks an option on the bottom navigation bar, this method will be called to perform the corresponding operation.
        navigationView.setNavigationItemSelectedListener(this);
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {<!-- -->
        Class fragmentClass = null;
        FragmentManager fragmentManager = getSupportFragmentManager();

        if (menuItem.getItemId() == R.id.FirstAge) {<!-- -->
            FirstAge();
            // Handle the click event of first-level menu 1
        } else if (menuItem.getItemId() == R.id.Dashboard) {<!-- -->
            //Click the secondary menu bar, close the sidebar, and jump to the corresponding function page
            drawerLayout.closeDrawers();

        } else if (menuItem.getItemId() == R.id.StudyTutorial) {<!-- -->

        } else if (menuItem.getItemId() == R.id.VideoTutorials) {<!-- -->

        }
        //Product menu
        else if (menuItem.getItemId() == R.id.Commodity) {<!-- -->
            Commodity();
        } else if (menuItem.getItemId() == R.id.ProductList) {<!-- -->

        } else if (menuItem.getItemId() == R.id.AddProduct) {<!-- -->

        } else if (menuItem.getItemId() == R.id.Category) {<!-- -->

        } else if (menuItem.getItemId() == R.id.ProductType) {<!-- -->

        } else if (menuItem.getItemId() == R.id.Branding) {<!-- -->

        }
        //Order menu
        else if (menuItem.getItemId() == R.id.OrderForGoods) {<!-- -->
            OrderForGoods();
        } else if (menuItem.getItemId() == R.id.Orderlist) {<!-- -->

        } else if (menuItem.getItemId() == R.id.OrderSettings) {<!-- -->

        } else if (menuItem.getItemId() == R.id.ReturnApplicationProcessing) {<!-- -->

        } else if (menuItem.getItemId() == R.id.ReturnReasonSettings) {<!-- -->

            //Marketing menu
        } else if (menuItem.getItemId() == R.id.Marketing) {<!-- -->
            Marketing();
        } else if (menuItem.getItemId() == R.id.ListOfFlashKillingActivities) {<!-- -->

        } else if (menuItem.getItemId() == R.id.CouponList) {<!-- -->

        } else if (menuItem.getItemId() == R.id.BrandRecommendation) {<!-- -->

        } else if (menuItem.getItemId() == R.id.NewProductRecommendation) {<!-- -->

        } else if (menuItem.getItemId() == R.id.PopularRecommendation) {<!-- -->

        } else if (menuItem.getItemId() == R.id.SpecialRecommendation) {<!-- -->

        } else if (menuItem.getItemId() == R.id.AdvertisingList) {<!-- -->

        }
        //Permissions menu
        else if (menuItem.getItemId() == R.id.LimitsOfAuthority) {<!-- -->
            LimitsOfAuthority();
        } else if (menuItem.getItemId() == R.id.UserList) {<!-- -->
            fragmentClass = UserListFragment.class;
        } else if (menuItem.getItemId() == R.id.RoleList) {<!-- -->
            fragmentClass = RoleListFragment.class;
        } else if (menuItem.getItemId() == R.id.MenuList) {<!-- -->

        } else if (menuItem.getItemId() == R.id.ResourceList) {<!-- -->

        }

        try {<!-- -->
            //newInstance() is a method in Java that is used to dynamically create new instances of classes
            Fragment fragment = (Fragment) fragmentClass.newInstance();
            //beginTransaction method is the method used to start a transaction in SQLite database
            fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();
            //setChecked() is used in APP applications to set the checked state of the checkbox multi-select box or radioButton radio button with the specified id.
            menuItem.setChecked(true);
            //setTitle(title);
            //Log.e(TAG, title);
            drawerLayout.closeDrawers();

        } catch (Exception e) {<!-- -->
            e.printStackTrace();
            //Used to print out the current call stack information during program execution, including detailed information such as the class, method name, and line number of each method call.
        }
        //fragmentClass = DashboardFragment.class;//Welcome page
        return true;
    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {<!-- -->
        super.onPointerCaptureChanged(hasCapture);
    }


    //Use method to switch the visibility of the secondary menu. When the first-level menu item is clicked for the first time, the second-level menu will be expanded; when the first-level menu item is clicked again, the second-level menu will be collapsed.
    private void LimitsOfAuthority() {<!-- -->
        Menu menu = navigationView.getMenu();
        MenuItem subMenu1 = menu.findItem(R.id.UserList);
        MenuItem subMenu2 = menu.findItem(R.id.RoleList);
        MenuItem subMenu3 = menu.findItem(R.id.MenuList);
        MenuItem subMenu4 = menu.findItem(R.id.ResourceList);

        if (subMenu1.isVisible()) {<!-- -->
            subMenu1.setVisible(false);
            subMenu2.setVisible(false);
            subMenu3.setVisible(false);
            subMenu4.setVisible(false);
        } else {<!-- -->
            subMenu1.setVisible(true);
            subMenu2.setVisible(true);
            subMenu3.setVisible(true);
            subMenu4.setVisible(true);
        }
    }

    private void Marketing() {<!-- -->
        Menu menu = navigationView.getMenu();
        MenuItem subMenu1 = menu.findItem(R.id.ListOfFlashKillingActivities);
        MenuItem subMenu2 = menu.findItem(R.id.CouponList);
        MenuItem subMenu3 = menu.findItem(R.id.BrandRecommendation);
        MenuItem subMenu4 = menu.findItem(R.id.NewProductRecommendation);
        MenuItem subMenu5 = menu.findItem(R.id.PopularRecommendation);
        MenuItem subMenu6 = menu.findItem(R.id.SpecialRecommendation);
        MenuItem subMenu7 = menu.findItem(R.id.AdvertisingList);

        if (subMenu1.isVisible()) {<!-- -->
            subMenu1.setVisible(false);
            subMenu2.setVisible(false);
            subMenu3.setVisible(false);
            subMenu4.setVisible(false);
            subMenu5.setVisible(false);
            subMenu6.setVisible(false);
            subMenu7.setVisible(false);
        } else {<!-- -->
            subMenu1.setVisible(true);
            subMenu2.setVisible(true);
            subMenu3.setVisible(true);
            subMenu4.setVisible(true);
            subMenu5.setVisible(true);
            subMenu6.setVisible(true);
            subMenu7.setVisible(true);
        }
    }

    private void OrderForGoods() {<!-- -->
        Menu menu = navigationView.getMenu();
        MenuItem subMenu1 = menu.findItem(R.id.Orderlist);
        MenuItem subMenu2 = menu.findItem(R.id.OrderSettings);
        MenuItem subMenu3 = menu.findItem(R.id.ReturnApplicationProcessing);
        MenuItem subMenu4 = menu.findItem(R.id.ReturnReasonSettings);

        if (subMenu1.isVisible()) {<!-- -->
            subMenu1.setVisible(false);
            subMenu2.setVisible(false);
            subMenu3.setVisible(false);
            subMenu4.setVisible(false);
        } else {<!-- -->
            subMenu1.setVisible(true);
            subMenu2.setVisible(true);
            subMenu3.setVisible(true);
            subMenu4.setVisible(true);
        }
    }

    private void Commodity() {<!-- -->
        Menu menu = navigationView.getMenu();
        MenuItem subMenu1 = menu.findItem(R.id.ProductList);
        MenuItem subMenu2 = menu.findItem(R.id.AddProduct);
        MenuItem subMenu3 = menu.findItem(R.id.Category);
        MenuItem subMenu4 = menu.findItem(R.id.ProductType);
        MenuItem subMenu5 = menu.findItem(R.id.Branding);

        if (subMenu1.isVisible()) {<!-- -->
            subMenu1.setVisible(false);
            subMenu2.setVisible(false);
            subMenu3.setVisible(false);
            subMenu4.setVisible(false);
            subMenu5.setVisible(false);
        } else {<!-- -->
            subMenu1.setVisible(true);
            subMenu2.setVisible(true);
            subMenu3.setVisible(true);
            subMenu4.setVisible(true);
            subMenu5.setVisible(true);
        }
    }

    private void FirstAge() {<!-- -->
        Menu menu = navigationView.getMenu();
        MenuItem subMenu1 = menu.findItem(R.id.Dashboard);
        MenuItem subMenu2 = menu.findItem(R.id.StudyTutorial);
        MenuItem subMenu3 = menu.findItem(R.id.VideoTutorials);

        if (subMenu1.isVisible()) {<!-- -->
            subMenu1.setVisible(false);
            subMenu2.setVisible(false);
            subMenu3.setVisible(false);
        } else {<!-- -->
            subMenu1.setVisible(true);
            subMenu2.setVisible(true);
            subMenu3.setVisible(true);
        }
    }
}