Some Kotlin Problem with solutions Every developer need to know

How to add Dynamic Navigation Drawer Items

In the last few posts, we have executed material navigation drawer with or without using the design support library where items of the navigation drawer were static, that is, they were predefined.
In any case, there are times when you need things to change as indicated by certain client activities or prefrences. In this post, we will progressively add things to a navigation drawer from a database with design support library, MySQLi and PHP scripts.

1)Creating some database tables:

This should always be the very first step whenever there’s a database involved. Here, we create a demo database hosted locally via Apache Web Server using XAMPP to serve the purpose of this post. For XAMPP – https://www.apachefriends.org/index.html.
Below is the screenshot of a demo table  – ‘test‘ – just holding some string values in column ‘Items‘.


2)PHP Script:

Here, We return a JSON response containing names of all the great houses from ASOIAF as declared in the above table.

getItems.php

$db_name = 'test';
$host_name = 'localhost';
$username = 'root';
$password = '';
$table_name = 'test_table';
 
 
$db = new mysqli($host_name,$username,$password,$db_name);
 
if($db->connect_errno>0){
 
    die('Unable to connect -> '.$db->error);
}
 
$queryString="Select * from $table_name";
 
if(!$result = $db->query($queryString)){
 
    die('error'. $db->error);
 
}
 
$temp=0;
$itemArray = array();
 
while ($row = $result->fetch_assoc()) {
    $itemArray[$temp] = $row['Items']; 
    $temp++;
}
 
echo json_encode($itemArray);
 
$result->free();

The response from the above script:

[“House Lannister”,”House Stark”,”House Targaryen”,”House Martell”,”House Tyrell”,”House Tully”]

3)Include Desing Support Library Dependency:

Now, fire up the Android Studio, select an ‘EMPTY‘ activity and include the design support library in your Gradle. Open Module(App) Gradle file and add the below dependencies. (If prompted update your android SDK).
//Code : compile ‘com.android.support:design:23.1.1’

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
   }

4)Creating a Blank Menu Resource:


  1. Create a new Android Resouce Directory of resource type ‘menu‘ in res and name it ‘menu‘.
  2. Create a new menu resource file – ‘drawer_menu.xml‘ in the menu directory.

This blank menu is attached with navigationalView to inflate menu items. We will programmatically add items to this menu later in this post.

5)Modifying Styles:

Open your style.xml file from the values directory and change the parent theme to ‘Theme.AppCompat.NoActionBar’ since we will be implementing a toolbar.

styles.xml

<resources>
 
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
 
</resources>

6)Adding the internet permission:

Open up your AndroidManifest.xml file and add
<uses-permission android:name=”android.permission.INTERNET”/>
above the application declaration.

7)Designing the Navigation Drawer:

Navigation View inflates navigation items from a menu resource. The hierarchy of elements is shown below:

Basically, a DrawerLayout holds two items – one is the NavigationView and the other Container view.
Container view includes a frameLayout to inflate fragment view and a toolbar. The app: menu attribute of navigation view refers to the blank menu resource created above.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.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:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
 
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            />
 
        <FrameLayout
            android:id="@+id/containerView"
            android:background="#FFF"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
 
 
 
    </LinearLayout>
 
    <android.support.design.widget.NavigationView
        android:id="@+id/navigationView"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_gravity="left"
        app:headerLayout="@drawable/header"/>
 
</android.support.v4.widget.DrawerLayout>

6)Retrieving required data from the database.

Now the thing is: To dynamically add navigation items, we first get all the elements to be inflated from the database and then add those to the menu by passing our menu as a parameter to an async task.
Here, JsonReader is used to parse the response from the PHP script.

MainActivity.java

package com.blogspot.geekonjava.navdrawer;
 
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.util.JsonReader;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
 
public class MainActivity extends AppCompatActivity {
 
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        /**
         * Setting up the DrawerLayout,NavigationView and Toolbar.
         */
 
 
        final DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
        NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
 
        /**
         * Accessing the NavigationView menu.
         * The getMenu method returns menu resource used by navigationView.
         * Later,we will add items to this menu.
         */
 
        Menu drawerMenu = navigationView.getMenu();
 
        /**
         * Creating an ArrayList to hold items for the above Menu.
         */
        ArrayList items = new ArrayList();
 
        /**
         * Creating object of NavMenuClass defined later.
         * We pass our drawerMenu and ArrayList items to NavMenuClass.
         * And later , use this object to access both arrayList holding the items and the drawer menu.
         */
         
        NavMenuClass navMenuObject = new NavMenuClass(drawerMenu,items);
 
        /**
         * Creating object of AsyncClass - 'PopulateMenuItems' defined later to get items from the database.
         * Here,we pass the above navMenuObject as parameter to async class.
         */
 
        PopulateMenuItems populateMenuItems = new PopulateMenuItems();
        populateMenuItems.execute(navMenuObject);
 
        /**
         * This is required to handle the onItemClick on Navigation Drawer Items.
         */
 
        NavigationView.OnNavigationItemSelectedListener item_click_listener = new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem item) {
 
                /** This a sample code to change fragments depending on the menu item.
                 *
                 *  if(item.toString="someConditionalText")
                 *  {
                 *       FragmentManager mFragmentManager;
                 *       FragmentTransaction mFragmentTransaction;
                 *
                 *       mFragmentManager = getSupportFragmentManager();
                 *       mFragmentTransaction = mFragmentManager.beginTransaction();
                 *
                 *       mFragmentTransaction.replace(R.id.containerView,new TabFragment()).commit();
                 *  }
                 */
                drawerLayout.closeDrawers();
                return true;
            }
        };
 
        /**
         * Attaching the above listener to NavigationView
         */
 
        navigationView.setNavigationItemSelectedListener(item_click_listener);
 
        /**
         * Setting up Drawer Toggle for Toolbar.
         */
 
 
        ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout, toolbar,R.string.app_name,
                R.string.app_name);
 
        drawerLayout.setDrawerListener(mDrawerToggle);
 
        mDrawerToggle.syncState();
 
 
 
 
    }
 
    /**
     * NavMenuClass holds the NavigationView menu and an ArrayList which holds items to be populated in menu.
     */
 
    class NavMenuClass{
        Menu menu;
        ArrayList items;
         
        public NavMenuClass(Menu menu,ArrayList items){
 
            this.items = items;
            this.menu = menu;
 
        }
         
        public Menu getMenu(){
            return menu;
        }
         
        public ArrayList getItems(){
            return items;
        }
           
    }
 
    /**
     * An async task accepts 3 parameters:
     * Params -> the type of the parameters sent to the task upon execution.
     * Progress -> the type of the progress units published during the background computation.
     * Result -> the type of the result of the background computation.
     *
     * For more on asyncTack checkout this answer from stackOverflow :
     * http://stackoverflow.com/a/6053673/5087027
     *
     **/
 
 
    public class PopulateMenuItems extends android.os.AsyncTask<navmenuclass,void,navmenuclass>{
 
        @Override
        protected NavMenuClass doInBackground(final NavMenuClass... params) {
 
            /**
             * Accessing the navMenuObject passed to this class.
             */
            NavMenuClass navMenuObject = params[0];
 
            /**
             * Accessing arrayList passed with this object to add items.
             */
 
            ArrayList items = navMenuObject.getItems();
 
            try {
 
                /**
                 * Here, declare the URL. If on localhost, just write the localhost ip and add the path.
                 * The url object parses the urlString and throws 'MalformedURLException' if  URL could not be parsed.
                 * OpenConnection returns a connection referred by URL.
                 */
 
                String urlString = "http://192.168.0.100/getItems.php";
                URL url = new URL(urlString);
                URLConnection urlConnection = url.openConnection();
 
                /**
                 * InputStream reads the response in bytes and by InputStreamReader it is converted into characters.
                 */
 
                InputStream inputStream = urlConnection.getInputStream();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"UTF-8");
 
                /**
                 * JsonReader is used to parse the below output.
                 * ["House Lannister","House Stark","House Targaryen","House Martell","House Tyrell","House Tully"]
                 * In JSON , array stats with '['(Square Bracket) and object with '{'(Curly Bracket)).
                 * More on JsonReader : http://developer.android.com/reference/android/util/JsonReader.html.
                 */
 
                JsonReader jsonReader = new JsonReader(inputStreamReader);
 
                jsonReader.beginArray();
                while (jsonReader.hasNext()){
                    /**
                     * Get the nextString of the JSON array and add it to the arrayList - 'items'.
                     */
                    String name = jsonReader.nextString();
                    items.add(name);
                }
                jsonReader.endArray();
 
                return params[0];
            }
 
            catch (Exception e){
                Log.e("Exception", e.toString());
            }
 
            return null;
        }
 
        /**
         * @param NavMenuClass accepted by onPostExecute is returned by the above doInBackground method.
         * Here, we add ArrayList items added in doInBackground to Menu.
         */
 
        @Override
        protected void onPostExecute(NavMenuClass NavMenuObject) {
            /**
             *  Accessing menu of NavMenuObject.
             */
             
                Menu menu = NavMenuObject.getMenu();
             
            /**
             *  Accessing items of ArrayList from NavMenuObject.
             */
                 
                ArrayList arrayList = NavMenuObject.getItems();
 
            /**
             *  Adding items to menu by iterating the ArrayList.
             */
 
                for(int temp=0;temp<=arrayList.size()-1;temp++){
                    menu.add(arrayList.get(temp).toString());
                }
 
        }
    }
}
 
//Ignore
 
</navmenuclass,void,navmenuclass>

Hope you enjoy this tutorial and if it useful for you and want some more interesting article then subscribe us.

Comments