I have an activity in which I have added a Navigation Drawer with a custom Toolbar. This my activity layout:
<androidx.drawerlayout.widget.DrawerLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="#+id/toolbar" />
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph" />
</LinearLayout>
//NavigationView
</androidx.drawerlayout.widget.DrawerLayout>
In the activity I have also added a custom menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/sign_out"
android:title="Sign-out"
android:orderInCategory="100"
app:showAsAction="never"/>
</menu>
In this moment I have the burger icon and the three dots, which is what I want.
The problem arrives I try to add a search functionality in the fragment. This is how my fragment layout file looks like:
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.SearchView
android:id="#+id/search_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:iconifiedByDefault="false"
android:layout_centerHorizontal="true" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Instead of adding the SearchView to the actual Toolbar it creates another one. So I get two Toolbars. The problem is that I don't want to inflate the SerachView via a menu file in the fragment, I need to have it my layout file. How to have a single ToolBar that contains all three views (burger icon, the three dots and SearchView)?
This is what I have:
And this is what I want to achieve:
SOLVED:
I solved this by removing the Toolbar from the activity and set separate toolbar in each fragment.
You can have the below approach to achieve it:
Keep the Search item as always hidden in menu.xml
(In your activity)
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.<your menu name>, menu)
menu?.findItem(R.id.<search item id>)?.isVisible = false
val visibleFragment = supportFragmentManager.getCurrentNavigationFragment() //This is an extension function, which will return the current visible fragment
visibleFragment?.let {
if (it is SearchFragment) {
menu?.findItem((R.id.search))?.isVisible = true
}
}
return super.onCreateOptionsMenu(menu)
}
Refer menu.xml for full code
Change the visibility of the "search item" when your "SearchFragment" is visible. This can be achieved by using the listener approach. When the SearchFragment is visible send a callback to activity and call "invalidateOptionsMenu()"
To get the current visible fragment in Navigation graph, you can create an extension function as below:
fun FragmentManager.getCurrentNavigationFragment(): Fragment? =
primaryNavigationFragment?.childFragmentManager?.fragments?.first()
In your SearchFragment, initialize the listener in onAttach method.
Send action to MainActivity by using listener fron onViewCreated.
I have pushed the full code on Github for your reference.
https://github.com/parmeshtoyou/StackOverFlowActionBar
Updated action bar in Search Fragment
In your menu add the search item as follows:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/sign_out"
android:title="Sign-out"
android:orderInCategory="100"
app:showAsAction="never"/>
<item
android:id="#+id/action_search"
android:icon="#drawable/ic_search"
android:title="#string/search_label"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="always|collapseActionView" />
</menu>
Then edit your onCreateOptionsMenu as follows to add the search item (kotlin code):
val menuInflater = menuInflater
menuInflater.inflate(R.menu.<your_toolbar_menu_name>, menu)
val searchItem = menu.findItem(R.id.action_search)
val searchManager =
this#YourActivityName.getSystemService(Context.SEARCH_SERVICE) as SearchManager
var searchView: SearchView? = null
if (searchItem != null) {
searchView = searchItem.actionView as SearchView
}
searchView?.setSearchableInfo(searchManager.getSearchableInfo(this#YourActivityName.componentName))
return super.onCreateOptionsMenu(menu)
I guess that you want this search to only appear when your Fragment is visible. To do that you should check if the fragment is visible or only run above code when the fragment transaction is done. Do ask if anything is not particularly clear.
Related
The question is clear! I need to add another menu beside of the main menu in toolbar. I have created the status.xml menu file like this:
<?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/online"
android:orderInCategory="10"
android:title="#string/action_settings"
app:showAsAction="never" />
<item
android:id="#+id/busy"
android:orderInCategory="20"
android:title="#string/action_settings"
app:showAsAction="never" />
<item
android:id="#+id/invisible"
android:orderInCategory="30"
android:title="#string/action_settings"
app:showAsAction="never" />
</menu>
and added a clickable TextView to toolbar like this:
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
... />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.Toolbar>
Now I need to add it separately to the toolbar, but in code below:
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)
menuInflater.inflate(R.menu.status, menu)
return true
}
It add all of items to main menu. Any help will be appreciated.
If this menus have to be separate that appear depending on some kind of condition you can use onPrepareOptionsMenu.
Check this question and developer guide on menus
Android: Multiple Option Menus in one Activity
https://developer.android.com/guide/topics/ui/menus
How do I set up navigation component with navigation drawer?
How do I use it in my app?
Can everything be done with one Activity?
How do I handle toolbar visibility with just one Activity and fragments which have a dynamic toolbar visibility. Also, there are fragments which I need to close the drawer and make it inaccessible.
This question is a self answered question and works more as a tutorial than a real-life QA.
How do I set up navigation component with navigation drawer?
How do I use it in my app?
The navigation drawer set up differs a little when it comes to Navigation component.
Note, if you create a new app with drawer navigation, the current tutorial is not needed. However I'm going to explain some things that might look strange around here and if you decide to add a drawer at a later stage of the app
First, you need to set up your activity_main.xml and MainActivity to be ready for the Navigation Architecture:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.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" />
<com.google.android.material.navigation.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" />
</androidx.drawerlayout.widget.DrawerLayout>
where app_bar_main is just:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And the content_main is where your fragments are going to be held:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main">
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
Things you should know: The activity mustn't have a AppBar set on AndroidManifest.xml:
android:theme="#style/AppTheme.NoActionBar"
If you notice app:menu="#menu/activity_main_drawer" in the NavigationView tag, the fragment names should be the same that they are inside the mobile_navigation.xml:
<group android:checkableBehavior="single">
<item
android:id="#+id/homeFragment"
android:icon="#drawable/ic_menu_camera"
android:title="#string/menu_home" />
<item
android:id="#+id/galleryFragment"
android:icon="#drawable/ic_menu_gallery"
android:title="#string/menu_gallery" />
<item
android:id="#+id/slideshowFragment"
android:icon="#drawable/ic_menu_slideshow"
android:title="#string/menu_slideshow" />
<item
android:id="#+id/toolsFragment"
android:icon="#drawable/ic_menu_manage"
android:title="#string/menu_tools" />
</group>
<item android:title="Communicate">
<menu>
<item
android:id="#+id/shareFragment"
android:icon="#drawable/ic_menu_share"
android:title="#string/menu_share" />
<item
android:id="#+id/sendFragment"
android:icon="#drawable/ic_menu_send"
android:title="#string/menu_send" />
</menu>
</item>
</menu>
This way, with what is going to be explained below there will be no need to call for onCreateOptionsMenu to detect the clicks. Android team has already solved that for us. Follow below.
Until now, this doesn't differ too much from the usual drawer set up we actually do. But, there are some configurations we would need to do in the logic part of the app. So let's open MainActivity.kt. First you will need these:
private var appBarConfiguration: AppBarConfiguration? = null
private var drawerLayout: DrawerLayout? = null
private var toolbar: Toolbar? = null
private var navController: NavController? = null
After that in your onCreate method:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar) //set the toolbar
drawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
navController = findNavController(R.id.nav_host_fragment)
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.homeFragment,
R.id.galleryFragment,
R.id.slideShowFragment,
R.id.toolsFragment,
R.id.shareFragment,
R.id.sendFragment,
R.id.loginFragment,
R.id.phoneConfirmationFragment
), drawerLayout
)
setupActionBarWithNavController(navController!!, appBarConfiguration!!) //the most important part
navView.setupWithNavController(navController!!) //the second most important part
//other things unrelated
}
Let's see what's going on here:
First you would need a reference to the navController. The AppBarConfiguration is just a class which holds the fragments that are going to be opened as top level destinations. Which means that the fragment which is going to be opened after them would release the current one from the fragment back stack. It's important to tell to the AppBarConfiguration that we have a drawer also (passed as a parameter in the constructor).
Down below you would have a method called onSupportNavigateUp():
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration!!) || super.onSupportNavigateUp()
}
This method has to do with the up back button. But you won't need it too much if you have drawer navigation. This really comes in handy when you have a lot of fragments added on the backstack (or at least two).
Can everything be done with one Activity?
Yes, definitely! but still it requires a little bit more work when it comes to conditional navigation. Like when you want to show fragments which are not part of your drawer app. But still Google has done a huge progress with it. You can refer to conditional navigation here.
How do I handle toolbar visibility with just one Activity and
fragments which have a dynamic toolbar visibility. Also, there are
fragments which I need to close the drawer and make it inaccessible.
You can use addOnDestinationChangedListener from the navController:
navController.addOnDestinationChangedListener { _, destination, _ ->
when (destination.id) {
R.id.loginFragment, R.id.registerFragment, R.id.phoneConfirmationFragment -> {
toolbar?.visibility = View.GONE
drawerLayout?.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
}
else -> {
toolbar?.visibility = View.VISIBLE
drawerLayout?.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
}
}
}
Now you have a drawer and navigation component on your app.
I am trying to understand how to implement a SearchView in Android in my toolbar. The problem is that depending on the configurations I choose I get different interface results.
This is the layout of my Activity:
<RelativeLayout 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="fill_parent"
tools:context="com.construct.v2.activities.teams.ActivityTeams"
android:background="#ffffff"
android:id="#+id/relativeLayout">
<include android:id="#+id/toolbar" layout="#layout/toolbar_shadow"/>
<ListView
android:id="#+id/listview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/toolbar" />
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabIndicatorColor="#125688"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</RelativeLayout>
This is my toolbar_shadow layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/PopupMenuStyle"
android:id="#+id/my_awesome_toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
app:titleTextColor="#android:color/black"
android:layout_alignParentTop="true"
android:gravity="right"
android:elevation="5dp">
<TextView
android:id="#+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/s_text_size"
android:padding="#dimen/small_margin"
android:layout_gravity="right|end"
android:layout_marginEnd="#dimen/s_margin"
android:textColor="#000000"
android:text="#string/edit"/>
</android.support.v7.widget.Toolbar>
And this is the layout file for my search item:
<?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/search"
android:title="#string/search"
app:icon="#drawable/ic_search_black_24dp"
android:icon="#drawable/ic_search_black_24dp"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
With this configuration I get this output:
But if I click on the magnifying glass I get this:
If I start typing I get this:
So I thought that it was because I have this configuration app:showAsAction="collapseActionView|ifRoom" but I tried to change to always but i got this output:
The magnifying glass disappears. But if I click on the place where it is supposed to be I get this output:
Which is the correct output I am looking for, but I don't know why the magnifying glass is not showing.
This is the part in my activity where I initialize the searchview:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_search_team, menu);
SearchManager searchManager = (SearchManager)
getSystemService(Context.SEARCH_SERVICE);
searchMenuItem = menu.findItem(R.id.search);
searchView = (SearchView) searchMenuItem.getActionView();
ImageView searchClose = (ImageView) searchView.findViewById(android.support.v7.appcompat.R.id.search_close_btn);
searchClose.setImageResource(R.drawable.ic_action_cancel_black);
for (TextView textView : findChildrenByClass(searchView, TextView.class)) {
textView.setTextColor(Color.BLACK);
textView.setHintTextColor(Color.BLACK);
}
searchView.setSearchableInfo(searchManager.
getSearchableInfo(getComponentName()));
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextListener(this);
return true;
}
And this is how I initialize my toolbar:
#Override
protected void initToolbar() {
toolbar = (Toolbar) findViewById(R.id.toolbar);
if(toolbar!=null) {
if (user_type == 1) {
toolbar.setTitle(R.string.collaborators_title);
} else if (user_type == 2) {
toolbar.setTitle(R.string.admin_title);
}
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationIcon(R.drawable.ic_action_back_black);
//getSupportActionBar().setDisplayHomeAsUpEnabled(true);
//toolbar.setTitle("Teste");
//toolbar.setTitleTextColor(Color.parseColor("#000000"));
//final TextView edit = (TextView) findViewById(R.id.delete);
//edit.setText(" ");
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
}
}
Since I can't see the rest of the code where you implement the functionality for the x button, I'm just gonna take a stab at it. Add a listener for when the user leaves the search view to go back to the view with the magnifying glass. In that listener add this line:
<Your activity>.findViewById(R.id.search).setVisibility(View.VISIBLE);
It could be possible that the searchview automatically set the view to invisible, but you never reset the visibility for the user.
Edit:
app:icon="#drawable/ic_search_black_24dp"
android:icon="#drawable/ic_search_black_24dp"
there is difference between app: prefix and android: prefix. With appcompat-v7 library you can use android: prefix and remove app:icon line .
app:showAsAction="collapseActionView|ifRoom"
Change this line to
app:showAsAction="always|collapseActionView"
In searchview if we select only always as showasAction then back arrow is not visible.
Check the theme and styles of your app because a I had had the same problem that you and it made me crazy.
I found the solution changing the theme and styles.
If you are using Toolbar I assume that your main theme is
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
For the AppBarLayout use this
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark" />
For the Toolbar use this
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
Note that one is Dark and the other is Light. You can exchange both if it adjust better to your main theme
Use the suggest from Zohra Khan
Change this line to
app:showAsAction="always|collapseActionView" In searchview if we select only always as showasAction then back arrow is not visible.
If it's not clear, take a look to this example from where I took this ideas
Hope this helps you
I have actually a problem with my Searchview on the Support AppCompat v7 lib 24.0.0.
The SearchView is not shown up no text and input text (look screenshot)
The searchquery work perfect.
Thats my menu
<menu 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"
tools:context=".MainActivity">
<item
android:title="#string/search"
android:id="#+id/action_search"
android:icon="#drawable/ic_search_24dp"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>
And here my onCreateOptionsMenu;
menu.clear();
inflater.inflate(R.menu.menu_search, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
//Perform the final search
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
//Text has changed, apply filtering?
return false;
}
});
I hope someone can help me. :)
Sebastian
i have this problem too, i've changed Toolbar height to absolute value instead of wrap_content and problem solved. i don't know why but i think this issue is related to CoordinatorLayout and height of toolbar, something breaks the SearchView height. if i use LinearLayout instead of CoordinatorLayout and AppBarLayout it works.
menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_search"
android:icon="#drawable/ic_search_white_24dp"
android:orderInCategory="100"
android:title="#string/action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always|collapseActionView" />
</menu>
layout.xml
<android.support.design.widget.CoordinatorLayout 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="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="#dimen/toolbar_height"
android:paddingTop="#dimen/toolbar_top_padding"
android:background="?attr/colorPrimary"
app:title="#string/drawer_item_publisher_customization"
app:layout_scrollFlags="scroll|enterAlways|snap"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
app:tabGravity="fill"
style="#style/DefaultTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
toolbar_height value:
<dimen name="toolbar_height">75dp</dimen>
Before absolute height value (layout_height:"wrap_content"):
After absolute height value (layout_height:"75dp"):
if you are using theme: .NoActionBar
set this in your onCreate()
setSupportActionBar(toolbar);
This is very odd. I'm using build tools 25.0.1 and support lib 25.1.0. For me the accepted answer was not necessary, but the way the menu item was defined needs a small change. I need it like so:
<menu 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">
<item
android:id="#+id/search"
android:title="#string/search_title"
android:icon="#drawable/ic_search_24dp"
app:showAsAction="always|collapseActionView"
app:actionViewClass="android.widget.SearchView"/>
Where app:showAsAction is the key. Lint underlines this as red and tells me:
Should use android:showAsAction when using the appcompat library.
However if I have it set to android:showAsAction then the search view simply does not appear. Go figure.
Make sure you have add AppCompat library to your project. Is your activity was extended "AppCompatActivity"?
And also showAsAction shoud be: showAsAction="always|collapseActionView"
Hope this help!
None of the answers worked for me. I realized my case was a bit different. I omitted this line inside the fragment's onViewCreated()
setHasOptionsMenu(true)
Worked for me
I have this Layout:
<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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- The ActionBar -->
<include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- The main content view -->
<FrameLayout
android:id="#+id/flContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- The navigation drawer -->
<android.support.design.widget.NavigationView
android:id="#+id/nvView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/white"
app:menu="#menu/drawer_menu"
app:headerLayout="#layout/nav_header"/>
So, looking that in NavigationView we have the attribute:
app:menu="#menu/drawer_menu"
And I have this XML id menu folder.
I wanna make dynamic menus, ie, in code I should mount the 'MenuItem' objects and set into NavigationView.
Is this correct?
Is this best pratice?
Is this possible?
Note: My code is working with 'static drawer_menu', I want to improve it.
I'm waiting.
[EDIT]
I make it:
Menu menu = nvDrawer.getMenu();
for (KSMenuItem kmi : menus.values()) {
if (menu.size() == 0) {
menu.add(kmi.getId());
}
if (menu.getItem(kmi.getId()) == null) {
menu.add(kmi.getId());
}
MenuItem mi = menu.getItem(kmi.getId());
mi.setIcon(kmi.getIcon());
mi.setTitle(kmi.getTittle());
}
But this error happened:
06-27 15:26:15.538 15335-15335/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.sticdev30.newdrawer, PID: 15335
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sticdev30.newdrawer/com.example.sticdev30.newdrawer.MainActivity}: android.content.res.Resources$NotFoundException: String resource ID #0x1
KSMenuItem is a POJO with my menu data. In kmi.id I informed incremental integers...
I'm waitning
You can re-inflate NavigationViewat runtime with 2 lines of code using public method inflateMenu. In this example i re-inflate with new_navigation_drawer_items.xml
navigationView.getMenu().clear(); //clear old inflated items.
navigationView.inflateMenu(R.menu.new_navigation_drawer_items); //inflate new items.
You can add menus dynamically by following steps :
Step1. Obtain menu object from Navigation View NavigationView.getMenu()
Step2. Add any item to the menu using Menu.add()
We can dynamically add/remove menu items.
Suppose we have this menu items `
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#mipmap/home_icon_x48"
android:title="Home" />
<item
android:id="#+id/nav_part_catalouge"
android:icon="#mipmap/catalogue_icon_x48"
android:title="Parts Catalogue" />
<item
android:id="#+id/nav_favourite"
android:icon="#mipmap/my_favourate_x48"
android:title="My-Favourite" />\
<item
android:id="#+id/nav_opencarrequest"
android:icon="#mipmap/cart_request"
android:title="Cart-Request" />
<item
android:id="#+id/nav_setting"
android:icon="#mipmap/settings_x48"
android:title="Settings" />
</group>
<item android:title="">
<menu>
<item
android:id="#+id/nav_logout"
android:icon="#mipmap/logout_icon_x48"
android:title="Logout" />
</menu>
</item>
`
In Activity we can add or remove menuitems based on our condition
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);// your activity layout here
NavigationView navigationView= (NavigationView) findViewById(R.id.nav_view); // navigation view which holds menu items
navigationView.setNavigationItemSelectedListener(this);
if(yourCondition){
navigationView.getMenu().getItem(0).setVisible(false); //if you want to hide first item
navigationView.getMenu().getItem(1).setVisible(true); // if you want to show second menu item should be visible
}
}
Hope it will help.
Seems like kmi.getId() returns int(or long).
But Menu.add(int) adds menu with title from the given string resources, which is usually represented as R.string.something, and not for usual integer values.
Menu.add(CharSequence) does add menu with title of CharSequence, so you need to do some int-to-string conversion like menu.add(kmi.getId() + "");