Home | History | Annotate | Download | only in navigationdrawer
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.navigationdrawer
     18 
     19 import android.annotation.SuppressLint
     20 import android.app.Activity
     21 import android.app.SearchManager
     22 import android.content.Intent
     23 import android.content.res.Configuration
     24 import android.os.Bundle
     25 import android.support.v4.view.GravityCompat
     26 import android.support.v4.widget.DrawerLayout
     27 import android.support.v7.app.ActionBarDrawerToggle
     28 import android.support.v7.widget.RecyclerView
     29 import android.view.Menu
     30 import android.view.MenuItem
     31 import android.view.View
     32 import android.widget.Toast
     33 
     34 /**
     35  * This example illustrates a common usage of [DrawerLayout] in the Android support library.
     36  *
     37  * When a navigation (left) drawer is present, the host activity should detect presses of
     38  * the action bar's Up affordance as a signal to open and close the navigation drawer. The
     39  * ActionBarDrawerToggle facilitates this behavior.
     40  * Items within the drawer should fall into one of two categories:
     41  *
     42  *  * **View switches**. A view switch follows the same basic policies as
     43  * list or tab navigation in that a view switch does not create navigation history.
     44  * This pattern should only be used at the root activity of a task, leaving some form
     45  * of Up navigation active for activities further down the navigation hierarchy.
     46  *
     47  *  * **Selective Up**. The drawer allows the user to choose an alternate
     48  * parent for Up navigation. This allows a user to jump across an app's navigation
     49  * hierarchy at will. The application should treat this as it treats Up navigation from
     50  * a different task, replacing the current task stack using TaskStackBuilder or similar.
     51  * This is the only form of navigation drawer that should be used outside of the root
     52  * activity of a task.
     53  *
     54  * Right side drawers should be used for actions, not navigation. This follows the pattern
     55  * established by the Action Bar that navigation should be to the left and actions to the right.
     56  * An action should be an operation performed on the current contents of the window,
     57  * for example enabling or disabling a data overlay on top of the current content.
     58  */
     59 class NavigationDrawerActivity : Activity(), PlanetAdapter.OnItemClickListener {
     60 
     61     private lateinit var drawerLayout: DrawerLayout
     62     private lateinit var drawerList: RecyclerView
     63     private lateinit var drawerToggle: ActionBarDrawerToggle
     64     private lateinit var newTitle: CharSequence
     65     private lateinit var planetTitles: Array<String>
     66 
     67     override fun onCreate(savedInstanceState: Bundle?) {
     68         super.onCreate(savedInstanceState)
     69         setContentView(R.layout.activity_navigation_drawer)
     70 
     71         val drawerTitle = title
     72         newTitle = title
     73         planetTitles = resources.getStringArray(R.array.planets_array)
     74         drawerLayout = findViewById<DrawerLayout>(R.id.drawer_layout).apply {
     75             setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START)
     76         }
     77 
     78         drawerList = findViewById<RecyclerView>(R.id.left_drawer).apply {
     79             // Improve performance by indicating the list if fixed size.
     80             setHasFixedSize(true)
     81             // Set up the drawer's list view with items and click listener.
     82             adapter = PlanetAdapter(planetTitles, this@NavigationDrawerActivity)
     83         }
     84 
     85         // Enable ActionBar app icon to behave as action to toggle nav drawer.
     86         actionBar.run {
     87             setDisplayHomeAsUpEnabled(true)
     88             setHomeButtonEnabled(true)
     89         }
     90 
     91         // ActionBarDrawerToggle ties together the the proper interactions
     92         // between the sliding drawer and the action bar app icon.
     93         drawerToggle = object : ActionBarDrawerToggle(
     94                 this, /* Host Activity */
     95                 drawerLayout, /* DrawerLayout object */
     96                 R.string.drawer_open, /* "Open drawer" description for accessibility */
     97                 R.string.drawer_close  /* "Close drawer" description for accessibility */
     98         ) {
     99 
    100             override fun onDrawerClosed(drawerView: View) {
    101                 actionBar.title = newTitle
    102                 invalidateOptionsMenu() // Creates call to onPrepareOptionsMenu().
    103             }
    104 
    105             override fun onDrawerOpened(drawerView: View) {
    106                 actionBar.title = drawerTitle
    107                 invalidateOptionsMenu() // Creates call to onPrepareOptionsMenu().
    108             }
    109         }
    110 
    111         // Set a custom shadow that overlays the main content when the drawer opens.
    112         drawerLayout.addDrawerListener(drawerToggle)
    113 
    114         if (savedInstanceState == null) selectItem(0)
    115     }
    116 
    117 
    118     override fun onCreateOptionsMenu(menu: Menu): Boolean {
    119         menuInflater.inflate(R.menu.navigation_drawer, menu)
    120         return true
    121     }
    122 
    123     /**
    124      * Called whenever we call [invalidateOptionsMenu].
    125      * If the nav drawer is open, hide action items related to the content view.
    126      */
    127     override fun onPrepareOptionsMenu(menu: Menu) =
    128             super.onPrepareOptionsMenu(menu.apply {
    129                 findItem(R.id.action_websearch).isVisible = !drawerLayout.isDrawerOpen(drawerList)
    130             })
    131 
    132     override fun onOptionsItemSelected(item: MenuItem): Boolean {
    133         // The action bar home/up action should open or close the drawer.
    134         // ActionBarDrawerToggle will take care of this.
    135         if (drawerToggle.onOptionsItemSelected(item)) {
    136             return true
    137         }
    138 
    139         // Handle action buttons
    140         return when (item.itemId) {
    141             R.id.action_websearch -> {
    142                 // Create intent to perform web search for this planet.
    143                 val intent = Intent(Intent.ACTION_WEB_SEARCH).apply {
    144                     putExtra(SearchManager.QUERY, actionBar.title)
    145                 }
    146                 // Catch event that there's no activity to handle intent.
    147                 if (intent.resolveActivity(packageManager) != null) {
    148                     startActivity(intent)
    149                 } else {
    150                     Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show()
    151                 }
    152                 true
    153             }
    154             else -> super.onOptionsItemSelected(item)
    155         }
    156     }
    157 
    158     /* The click listener for RecyclerView in the navigation drawer. */
    159     override fun onClick(view: View, position: Int) {
    160         selectItem(position)
    161     }
    162 
    163     override fun setTitle(title: CharSequence) {
    164         newTitle = title
    165         actionBar.title = title
    166     }
    167 
    168     /**
    169      * If [ActionBarDrawerToggle] is used, it must be called in [onPostCreate] and
    170      * [onConfigurationChanged].
    171      */
    172     override fun onPostCreate(savedInstanceState: Bundle?) {
    173         super.onPostCreate(savedInstanceState)
    174         // Sync the toggle state after has occurred.
    175         drawerToggle.syncState()
    176     }
    177 
    178     override fun onConfigurationChanged(newConfig: Configuration) {
    179         super.onConfigurationChanged(newConfig)
    180         // Pass any configuration change to the drawer toggle.
    181         drawerToggle.onConfigurationChanged(newConfig)
    182     }
    183 
    184     @SuppressLint("CommitTransaction") // commit() is called
    185     private fun selectItem(position: Int) {
    186         fragmentManager.beginTransaction().run {
    187             replace(R.id.content_frame, PlanetFragment.newInstance(position))
    188             commit()
    189         }
    190         title = planetTitles[position]
    191         drawerLayout.closeDrawer(drawerList)
    192     }
    193 
    194 }
    195