Le Navigation Drawer en kotlin

Bonjour à tous ! Le nouvel article de la semaine.  Aujourd’hui j’ai décidé de vous proposer un concept simple le Navigation Drawer en kotlin avec sa navigation view. Il va vous permettre d’afficher différentes vues et de se déplacer à l’intérieur de vos applications.

Vous pouvez également regarder la vidéo, elle résume ce que je dis dans cet article. Je m’essaye  au format vidéo, pour acquérir de nouvelles compétences  et de vous proposer le sujet sous un format différent.

Dans cet article,  je vais vous présenter la définition d’un Navigation Drawer. Vous allez pouvoir voir comment le créer et l’implémenter. Pour finir et pour aller plus loin, je vous montrerai comment vous allez pouvoir l’additionner  à des fragments.  Si la notion de fragments ne vous évoque rien,  je vous invite à aller lire mes deux précédents articles “Introduction au fragment sur kotlin” et “Fragment statique et dynamique en kotlin”.

Qu’est-ce qu’un Navigation Drawer ?

Navigation Drawer Activity

  • C’est un menu de navigation sur une activité principale.
  • Le menu est caché et s’ouvre comme un tiroir à partir d’un bouton (burger) sur une barre d’outil ou de façon tactile de l’utilisateur de la gauche vers le centre.
  • Le menu permet à l’utilisateur de naviguer à travers les différents onglets.
  • Les fragments sont souvent utilisés avec le Navigation Drawer.

La création d’un Navigation Drawer

fenêtre choix optionSur Android studio lors de la création de notre projet, il faut sélectionner l’activité qui s’intitule “Bottom Navigation Activity” puis cliquer sur “Next”.

Configure your projet

Il faut ensuite nommez votre projet (le nom de votre application par exemple). Choisir le langage de programmation Kotlin et pour finir choisir la version de l’API. Pour finir appuyer sur “Finish”.

Votre application est prête à être lancer, Android Studio va vous générer tout seul le fichier de code de votre activité et quatre fichiers layout qui permettront de configurer la navigation view. Appuyer sur l’icône bouton play  et sélectionner votre émulateur pour lancer votre application et voir son rendu.

Le visuel de l’activité principale

appercut navigation drawer

Le layout de l’activity_main va venir recueillir et constituer l’ensemble de la navigationView . Il regroupe également les 3 autres layout à savoir le layout pour le contenu de l’activité, le layout pour la barre d’outil et le layout pour l’entête du menu de navigation.

code
<?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"
        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
            layout="@layout/app_bar_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    <android.support.design.widget.NavigationView
            android:id="@+id/nav_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/nav_header_main"
            app:menu="@menu/activity_main_drawer"/>

</android.support.v4.widget.DrawerLayout>

La balise “fitsSystemWindows” est un attribut du type Boolean qui permet d’afficher ou non la barre des tâches d’information du téléphone (batterie, notification, ect…).

La balise “openDrawer” indique au menu de navigation qu’il doit s’ouvrir selon comment on le configure par la gauche ou par la droite.

La balise “headerLayout” va permettre à l’activité de venir charger le fichier layout correspondant à l’entête de menu de navigation.

La balise “menu” va permettre à l’activité de venir charger le fichier menu correspondant au menu de navigation de l’activité.

La balise “id” est toujours intéressente pour venir interagir avec notre composant dans le code de notre application.

La barre d’outil du Navigation Drawer

Le deuxième fichier layout qu’ Android Studio génère est le fichier correspondant à la barre d’outil et le bouton flottant. C’est sur cette barre d’outil que l’on retrouve notre bouton (burger) pour accéder au menu de navigation et notre bouton de droite pour ouvrir le menu setting.

imagebouton flottant

code
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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=".MainActivity">

    <android.support.design.widget.AppBarLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/AppTheme.AppBarOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main"/>

    <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            app:srcCompat="@android:drawable/ic_dialog_email"/>

</android.support.design.widget.CoordinatorLayout>

L’apparence du contenu de l’activité

appli_navigation_drawer

Le troisième fichier layout qu’ Android Studio génère est le fichier content_main, il va permettre d’afficher le contenu des vues de notre activité. C’est dans ce layout qu’on va afficher le contenu de nos onglets du menu de navigation.

code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:id="@+id/content_main"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:showIn="@layout/app_bar_main"
        tools:context=".MainActivity">



</LinearLayout>

Les deux balises “layout_behavior” et “shohIn” sont importantes ici car elles permettent d’afficher la barre d’outil où se trouvent notamment nos boutons utiles pour la navigation.

L’entête du Navigation Drawer

imageimage

Le dernier fichier layout qu’ Android Studio génère est le fichier d’entête du menu de navigation. Si vous ne voulez pas d’entête, vous pouvez tout à fait la retirer mais je vous recommande de le laisser car elle donne un aspect sympathique au menu de navigation. Dans ce fichier layout, pour aller pouvoir vous occuper de l’aspect visuelle de votre entête. Soyez créatif !

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

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

    <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:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/nav_header_subtitle"
            android:id="@+id/textView"/>

</LinearLayout>

Les menu

image

Le menu du Navigation Drawer

image

C’est un fichier XML qui est généré également par android studio mais contrairement à un fichier layout il ne possède que deux type de structure/balise à savoir : groupe  et Item

code
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      tools:showIn="navigation_view">

    <group android:checkableBehavior="single">
        <item
                android:id="@+id/nav_camera"
                android:icon="@drawable/ic_menu_camera"
                android:title="Import"/>
        <item
                android:id="@+id/nav_gallery"
                android:icon="@drawable/ic_menu_gallery"
                android:title="Gallery"/>
        <item
                android:id="@+id/nav_slideshow"
                android:icon="@drawable/ic_menu_slideshow"
                android:title="Slideshow"/>
        <item
                android:id="@+id/nav_manage"
                android:icon="@drawable/ic_menu_manage"
                android:title="Tools"/>
    </group>

    <item android:title="Communicate">
        <menu>
            <item
                    android:id="@+id/nav_share"
                    android:icon="@drawable/ic_menu_share"
                    android:title="Share"/>
            <item
                    android:id="@+id/nav_send"
                    android:icon="@drawable/ic_menu_send"
                    android:title="Send"/>
        </menu>
    </item>

</menu>

La structure Item : correspond à un onglet de notre menu dans lequel on peut configurer son icône (balise “icon”), son identifiant (balise “id”) et son titre (balise “title”).

La structure Groupe : permet de grouper un ensemble d’item pour leur appliquer des paramètres par exemple avec la balise “checkableBehavior”  et sa valeur “single” qui indique que sur l’ensemble des items il n’y a qu’un seul qui peut être sélectionné à la fois.

Le menu de la barre des tâches

image

Le fichier menu “main” correspond au menu setting déroulant de la barre des tâches.

code
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/action_settings"
          android:title="@string/action_settings"
          android:orderInCategory="100"
          app:showAsAction="never"/>
</menu>

Le code de l’activité

La méthode “onCreate” permet d’initialiser les différents composants et d’ajouter les évènements lors du click sur les boutons.

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

    fab.setOnClickListener { view ->
        Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
            .setAction("Action", null).show()
    }

    val toggle = ActionBarDrawerToggle(
        this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close
    )
    drawer_layout.addDrawerListener(toggle)
    toggle.syncState()

    nav_view.setNavigationItemSelectedListener(this)
}

La méthode “onBackPressed” permet d’associer le bouton back du téléphone à un événement de l’application. Lorsque le menu de navigation est ouvert le bouton “back” permet de fermer le menu. Lorsque le menu est fermé le bouton back récupère son rôle par défaut, c’est-à-dire revenir en arrière.

back bottom phone

code
override fun onBackPressed() {
    if (drawer_layout.isDrawerOpen(GravityCompat.START)) {
        drawer_layout.closeDrawer(GravityCompat.START)
    } else {
        super.onBackPressed()
    }
}

La méthode “onCreateOptionsMenu” : cette méthode permet d’afficher les boutons sur la barre d’actions de l’application.

code
override fun onCreateOptionsMenu(menu: Menu): Boolean {
    // Inflate the menu; this adds items to the action bar if it is present.
    menuInflater.inflate(R.menu.main, menu)
    return true
}

La méthode “onOptionItemSelected” permet d’initialiser le menu setting de la barre des tâches de l’application.

code
override fun onOptionsItemSelected(item: MenuItem): Boolean {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    when (item.itemId) {
        R.id.action_settings -> return true
        else -> return super.onOptionsItemSelected(item)
    }
}

La méthode “onNavigationItemSelected” : cette méthode permet d’associer un événement lorsque l’utilisateur sélectionne un item dans le menu de navigation.

code
override fun onNavigationItemSelected(item: MenuItem): Boolean {
    // Handle navigation view item clicks here.
    var fragment:Fragment = ImportFragment.newInstance()

    when (item.itemId) {
        R.id.nav_camera -> {
        }
        R.id.nav_gallery -> {
        }
        R.id.nav_slideshow -> {
        }
        R.id.nav_manage -> {
        }
        R.id.nav_share -> {
        }
        R.id.nav_send -> {
        }
    }
    drawer_layout.closeDrawer(GravityCompat.START)
    return true
}

Pour aller plus loin

Le navigationView est souvent utilisé avec les fragments car elle permet une meilleure fluidité et adaptabilité due au faite d’avoir qu’une seule activité et des fragments qui s’adaptent aux dimensions de l’écran .

Dans l’exemple qui va suivre j’ai réalisé 6 fragments plus ou moins similaires pour correspondre à chaque item du menu de navigation.

galleryimportmanage

slideshowsharesend

Le code ci-dessous représente le code d’un des fragments, les autres fragments sont similaires.

code
class ImportFragment : Fragment() {

    companion object {
        fun newInstance() : ImportFragment
        {
            return ImportFragment()
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_import, container, false)
    }


}

L’implémentation des fragments reste simple je viens dans la méthode “onNavigationItemSelected” initialiser un fragment différent selon l’item qui est sélectionné. Puis je viens l’afficher ou le remplacer avec l’objet supportFragmentManager et sa méthode beginTransaction() et sa méthode replace() puis valider la transaction avec la méthode commit().

code
override fun onNavigationItemSelected(item: MenuItem): Boolean {
    // Handle navigation view item clicks here.
    var fragment:Fragment = ImportFragment.newInstance()

    when (item.itemId) {
        R.id.nav_camera -> {
            fragment = ImportFragment.newInstance()
        }
        R.id.nav_gallery -> {
            fragment = GalleryFragment.newInstance()
        }
        R.id.nav_slideshow -> {
            fragment = SlideshowFragment.newInstance()
        }
        R.id.nav_manage -> {
            fragment = ManageFragment.newInstance()
        }
        R.id.nav_share -> {
            fragment = ShareFragment.newInstance()
        }
        R.id.nav_send -> {
            fragment = SendFragment.newInstance()
        }
    }
    supportFragmentManager.beginTransaction()
        .replace(R.id.content_main, fragment, "").commit()
    drawer_layout.closeDrawer(GravityCompat.START)
    return true
}

Merci d’avoir lu ! Maintenant, si vous avez aimé le contenu de l’article, si  vous connaissez une personne à qui cet article peut intéresser, n’hésitez pas à le liker et à le partager sur les réseaux sociaux. Si  vous souhaitez me faire part de vos remarques, de vos problèmes, de vos suggestions de prochain article ou tout simplement de votre soutien n’hésitez pas à m’en faire part dans les commentaires, je vous en remercie.

crédit photo : Blickpixel

Partager l'article :
  •  
  •  
  •  
  •  
  • 10
    Partages

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *