When I have an app with multiple activities and like to have an options-menu all-over: Do I have to override the onCreateOptionsMenu-method in each activity?
Or can that become centralized?
You can prevent that boilerplate code creating a common Activity which all of your Activities inherit.
abstract class CommonSaveActivity : Activity() {
#CallSuper
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.common_save_action_menu, menu)
return true
}
#CallSuper
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.saveAction -> {
// TODO: handle common save action
true
}
else -> super.onOptionsItemSelected(item)
}
}
}
class ActivityA : CommonSaveActivity()
class ActivityB : CommonSaveActivity()
class ActivityC : CommonSaveActivity() {
// You can have the common save menu AND your
// activity specific menu at the same time in UI.
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// NOTE: if you call super.onCreateOptionsMenu(menu) AFTER
// menuInflater.infalte(..) line, then the order of menu
// items will be different.
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.activity_c_menu, menu)
return true
}
Related
I inflate my SearchView into my AppBarLayout and MaterialToolbar in MainActivity. When I search items in ListFragment and open DetailFragment for an item then get back my AppBarLayout inflates again and I see my list is cleared. I want it to save query and show my previous state.
In ListFragment I do:
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.menu_main, menu)
}
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
setupSearchView(menu)
}
private fun setupSearchView(menu: Menu) {
userSearchView = menu.findItem(R.id.search).actionView as SearchView
userSearchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
query?.let(viewModel::trySearching)
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
newText?.let(viewModel::trySearching)
return true
}
})
}
In DetailFragment I do:
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
menu.clear()
}
For navigation I use AAC nav component
I hope you are well.
My question is why this callback class has two of the same functions?
the only difference that I see is that some functions deal with nullable and the others don't, but in the end, we can achieve what want with both ways (with nullable or without nullable)
if anyone has a good explanation for this and thanks in advance
private val actionModeCallback = object : Callback, android.view.ActionMode.Callback {
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
return false
}
// Called each time the action mode is shown. Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
return false // Return false if nothing is done
}
// Called when the user selects a contextual menu item
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
return false
}
// Called when the user exits the action mode
override fun onDestroyActionMode(mode: ActionMode) {
actionMode = null
}
override fun onCreateActionMode(p0: android.view.ActionMode?, p1: Menu?): Boolean {
// Called when the action mode is created; startActionMode() was called
// Inflate a menu resource providing context menu items
val inflater: MenuInflater = p0!!.menuInflater
inflater.inflate(R.menu.memory_fragment_context_menu, p1)
return true
}
override fun onPrepareActionMode(p0: android.view.ActionMode?, p1: Menu?): Boolean {
return false
}
override fun onActionItemClicked(p0: android.view.ActionMode?, p1: MenuItem?): Boolean {
return when (p1?.itemId) {
R.id.someId -> {
Toast.makeText(context,"go to hell", Toast.LENGTH_LONG).show()
selectionTracker?.clearSelection()
p0?.finish() // Action picked, so close the CAB
true
}
else -> false
}
}
override fun onDestroyActionMode(p0: android.view.ActionMode?) {
}
}
here is my code
fun initActionBar() {
setSupportActionBar(toolbar_main)
actionBar?.setDisplayHomeAsUpEnabled(true)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
MenuInflater(this).inflate(R.menu.toolbar_menu, menu)
return true
}
and here I serve you my menu and screenshot
Remove the '?' after actionBar. Looks like this now:
fun initActionBar() {
setSupportActionBar(toolbar_main)
actionBar.setDisplayHomeAsUpEnabled(true)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
MenuInflater(this).inflate(R.menu.toolbar_menu, menu)
return true
}
I have two fragments and a toolbar with a menu. I want to be able to switch fragments when a menu item is selected by calling the method in the fragment that does this. Problem is, I get this error when I try running the app with the code below. java.lang.IllegalStateException: Fragment FirstFragment{5ce330b (f5c2d362-d3fb-4346-9971-dd7be653e609)} not associated with a fragment manager.
MainActivity.kt
class MainActivity : AppCompatActivity() {
lateinit var adapter: Adapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar))
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
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.
return when (item.itemId) {
R.id.action_settings -> {
FirstFragment().settings()
true
}
else -> super.onOptionsItemSelected(item)
}
}
}
FirstFragment.kt
fun settings() {
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
}
How can I implement a fragment manager so I can call this method via MenuItem and not get an exception? Thanks in advance!
Thanks for the help! I solved the issue by creating the MenuItem in my first fragment like so:
lateinit var second: MenuItem
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
second = menu.add("second fragment")
second.setOnMenuItemClickListener() {
settings()
true
}
}
fun settings() {
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
}
I have a Fragment:
class HomeFragment : Fragment() { ... }
Now I'm trying to add an Actionbar to it, but this doesn't work:
setSupportActionBar(findViewById(R.id.toolbar_main))
How can I set the Support and then add Items to the ActionBar?
This is how it works in an AppCompatActivity:
// This adds items to the ActionBar
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_toolbar_main, menu)
return true
}
// This is the OnClickListener for the Buttons in the ActionBar
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.toolbar_edit -> {
true
}
R.id.toolbar_search -> {
true
}
else -> {
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
super.onOptionsItemSelected(item)
}
}
Big thanks in advance!
Override onCreateOptionsMenu in your Fragment and inflate your menu inside. Than in onCreate method of Fragment set setHasOptionsMenu() to true. To inflate different menus depending on Fragment creation clear the menu first.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
super.onCreateOptionsMenu(menu, inflater)
inflater?.inflate(Your menu here, menu)
}