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