I'm following this color scheme of Navigation View.
I created 3 selectors, for background, text and icon.
When I set the selectors, my navigation view looked like this:
The problem is that no item is shown selected and if I press one item, all items' background color changes to gray. Icon never gets the primary color.
Here is are the XMLs:
<android.support.design.widget.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/white"
app:itemTextColor="#drawable/nav_item_text"
app:itemIconTint="#drawable/nav_item_icon_tint"
app:itemBackground="#drawable/nav_item_background"
app:headerLayout="#layout/drawer_student_data_header"
app:menu="#menu/drawer"
android:id="#+id/navigationView"/>
nav_item_icon_tint.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#color/gray_600"/>
<item android:state_selected="true" android:color="#color/primary" />
<item android:color="#color/gray_600" />
</selector>
nav_item_text.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#color/black_87_percent"/>
<item android:state_selected="true" android:color="#color/primary" />
<item android:color="#color/black_87_percent" />
</selector>
nav_item_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#color/gray_400"/>
<item android:state_selected="true" android:drawable="#color/gray_200" />
<item android:drawable="#android:color/white" />
</selector>
I've had a similar problem and looks like the way to solve it is to use android:state_checked instead of the android:state_selected in all three selectors (at least that solved it for me).
You can use setItemTextColor and setItemIconTintList for set text color tint and icon color tint to item of NavigationDrawer,
To use this methods add this code to end of onCreateView:
int[][] states = new int[][]{
new int[]{-android.R.attr.state_checked},// unchecked state
new int[]{android.R.attr.state_checked}, // checked state
};
int[] colors = new int[]{
ContextCompat.getColor(this, R.color.colorPrimary),
ContextCompat.getColor(this, R.color.colorPrimaryDark)
};
ColorStateList colorStateList = new ColorStateList(states, colors);
navigationView.setItemTextColor(colorStateList);
navigationView.setItemIconTintList(colorStateList);
This code set color to unchecked state and checked state. You can set color to other states.
Color array and state array should be have equals member count. You can select color whatever you want.
You can use Color class or like the sample use resource. In this link you can find list of available states developer.android.
Make sure you are not accessing the menu item from bottom navigation and setting its state to 'checked' twice. To avoid that, use:
mBottomNavigationView.selectedItemId(R.id.your_menu_item_id);
instead of
mBottomNavigationView.menu.getItem(position).setChecked(true);
Related
I want to change to icons of the bottom navigation view as we switch items.
I have light blue icons and dark blue icons for selected items.
I am using selector drawable for each navigation item but I see the images like below in grey as inactive and blue as active
Here is my code
bottom_nav_menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_home"
android:icon="#drawable/home_icon_selector"
android:title="#string/title_home" />
<item
android:id="#+id/navigation_scheduler"
android:icon="#drawable/schelduler_icon_selector"
android:title="#string/title_scheduler" />
<item
android:id="#+id/navigation_favourites"
android:icon="#drawable/favourites_icon_selector"
android:title="#string/title_favourites" />
<item
android:id="#+id/navigation_settings"
android:icon="#drawable/settings_icon_selector"
android:title="#string/title_settings" />
</menu>
home
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/margin_20"
android:layout_marginLeft="#dimen/margin_20"
android:layout_marginRight="#dimen/margin_20"
android:layout_marginEnd="#dimen/margin_20"
android:layout_marginBottom="#dimen/margin_8"
android:background="#drawable/bottom_navigation_background"
android:elevation="8dp"
app:itemIconTint="#drawable/bottom_navigation_color_selector"
app:labelVisibilityMode="unlabeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_nav_menu" />
And selectors
scheduler selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/qa_scheduler_inactive" android:state_checked="false"/>
<item android:drawable="#drawable/ic_scheduler_blue" android:state_checked="true"/>
</selector>
Settings selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/qa_settings_inactive" android:state_checked="false"/>
<item android:drawable="#drawable/ic_settings_blue" android:state_checked="true"/>
</selector>
Favorites selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/qa_favorites_inactive" android:state_checked="false"/>
<item android:drawable="#drawable/ic_favourites_blue" android:state_checked="true"/>
</selector>
Home Selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/qa_home_inactive" android:state_checked="false"/>
<item android:drawable="#drawable/ic_home" android:state_checked="true"/>
</selector>
Activity code
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(setOf(
R.id.navigation_home, R.id.navigation_scheduler, R.id.navigation_favourites, R.id.navigation_settings))
// setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
What am I doing wrong here? Please help...
Edit :
I am using following drawables
enter link description here
enter link description here
The reason of this issue is that there is always a value for app:itemIconTint, even if it is not used, it takes the default values of the primary/accent colors.
So to solve your problem you need to explicitly disable this with:
val btmNav = findViewById<BottomNavigationView>(R.id.nav_view)
navView.itemIconTintList = null
Although I do recommend another thing:
The icons are already the same icons in checked/unchecked states, but with different tint colors. If these icons are vectors, then you can just tint colors using a selector in app:itemIconTint, and use a single version of the icon without needing to duplicate the resources:
icon_color_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#2596CD" android:state_checked="true" />
<item android:color="#84D0F4" android:state_checked="false" />
</selector>
And apply that:
<com.google.android.material.bottomnavigation.BottomNavigationView
...
app:itemIconTint="#drawable/icon_color_selector"
And keep the menu items only with icons not the selectors, for instance:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_home"
android:icon="#drawable/home_icon" //<<<<< icon not selector
android:title="#string/title_home" />
....
</menu>
UPDATE:
As you are using navigation architecture components, make sure to have the same ids in the bottomNavView menu that matches the corresponding ones in the navGraph of the bottomNavView fragments.
In case you don't use a navGraph for the bottomNavView fragments, then you can't use navView.setupWithNavController(navController)
Here is with your drawable icon
This is just a wild guess, but maybe this line here:
app:itemIconTint="#drawable/bottom_navigation_color_selector"
is interfering with the colors of your drawables? If your drawables have the right colors (light blue/dark blue) they should work with your current selectors.
Alternatively, check that you don't set app:itemIconTint for the bottom-nav some other way, eg through a theme or programmatically!
You can achieve this using using selector like #Chris said or you can do it dynamically by using setOnNavigationItemSelectedListener{}
update - For changing icons , you can just brute force by changing the current item.icon to filled and others to unfilled icon , see here to get a gist of it (don't copy its for tabLayout).
navView.setOnNavigationItemSelectedListener { item ->
// change the icon to filled icon
true
}
It seems so that listner is depreciated so refer this
I'm adding a BottomNavigationView to a project, and I would like to have a different text (and icon tint) color for the selected tab (to achieve greying out non-selected tabs effect). Using a different color with android:state_selected="true" in a color selector resource file doesn't seem to work. I also tried having additional item entries with android:state_focused="true" or android:state_enabled="true", no effect unfortunately. Also tried setting the state_selected attribute to false (explicitly) for the default (non-selected) color, with no luck.
Here is how I add the view to my layout:
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:itemBackground="#color/silver"
app:itemIconTint="#color/bnv_tab_item_foreground"
app:itemTextColor="#color/bnv_tab_item_foreground"
app:menu="#menu/bottom_nav_bar_menu" />
Here is my color selector (bnv_tab_item_foreground.xml):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#android:color/darker_gray" />
<item android:state_selected="true" android:color="#android:color/holo_blue_dark" />
</selector>
And my menu resource (bottom_nav_bar_menu.xml):
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/action_home"
android:icon="#drawable/ic_local_taxi_black_24dp"
android:title="#string/home" />
<item
android:id="#+id/action_rides"
android:icon="#drawable/ic_local_airport_black_24dp"
android:title="#string/rides"/>
<item
android:id="#+id/action_cafes"
android:icon="#drawable/ic_local_cafe_black_24dp"
android:title="#string/cafes"/>
<item
android:id="#+id/action_hotels"
android:icon="#drawable/ic_local_hotel_black_24dp"
android:title="#string/hotels"/>
</menu>
I would appreciate any help.
While making a selector, always keep the default state at the end, otherwise only default state would be used. You need to reorder the items in your selector as:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="#android:color/holo_blue_dark" />
<item android:color="#android:color/darker_gray" />
</selector>
And the state to be used with BottomNavigationBar is state_checked not state_selected.
1. Inside res create folder with name color (like drawable)
2. Right click on color folder. Select
new-> color resource file-> create color.xml file (bnv_tab_item_foreground)
(Figure 1: File Structure)
3. Copy and paste bnv_tab_item_foreground
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
app:itemBackground="#color/appcolor"//diffrent color
app:itemIconTint="#color/bnv_tab_item_foreground" //inside folder 2 diff colors
app:itemTextColor="#color/bnv_tab_item_foreground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/navigation" />
bnv_tab_item_foreground:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="#color/white" />
<item android:color="#android:color/darker_gray" />
</selector>
Figure 1: File Structure:
BottomNavigationView uses colorPrimary from the theme applied for the selected tab and it uses android:textColorSecondary for the inactive tab icon tint.
So you can create a style with the prefered primary color and set it as a theme to your BottomNavigationView in an xml layout file.
styles.xml:
<style name="BottomNavigationTheme" parent="Theme.AppCompat.Light">
<item name="colorPrimary">#color/active_tab_color</item>
<item name="android:textColorSecondary">#color/inactive_tab_color</item>
</style>
your_layout.xml:
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
android:theme="#style/BottomNavigationTheme"
app:menu="#menu/navigation" />
If you want to change icon and text colors programmatically:
ColorStateList iconColorStates = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_checked},
new int[]{android.R.attr.state_checked}
},
new int[]{
Color.parseColor("#123456"),
Color.parseColor("#654321")
});
navigation.setItemIconTintList(iconColorStates);
navigation.setItemTextColor(iconColorStates);
I am using a com.google.android.material.bottomnavigation.BottomNavigationView (not the same as OP's) and I tried a variety of the suggested solutions above, but the only thing that worked was setting app:itemBackground and app:itemIconTint to my selector color worked for me.
<com.google.android.material.bottomnavigation.BottomNavigationView
style="#style/BottomNavigationView"
android:foreground="?attr/selectableItemBackground"
android:theme="#style/BottomNavigationView"
app:itemBackground="#color/tab_color"
app:itemIconTint="#color/tab_color"
app:itemTextColor="#color/bottom_navigation_text_color"
app:labelVisibilityMode="labeled"
app:menu="#menu/bottom_navigation" />
My color/tab_color.xml uses android:state_checked
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/grassSelected" android:state_checked="true" />
<item android:color="#color/grassBackground" />
</selector>
and I am also using a selected state color for color/bottom_navigation_text_color.xml
Not totally relevant here but for full transparency, my BottomNavigationView style is as follows:
<style name="BottomNavigationView" parent="Widget.Design.BottomNavigationView">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">#dimen/bottom_navigation_height</item>
<item name="android:layout_gravity">bottom</item>
<item name="android:textSize">#dimen/bottom_navigation_text_size</item>
</style>
It's too late to answer but might be helpful for someone.
I was doing a very silly mistake, I was using a selector file named as bottom_color_nav.xml for Select and unselect color change but still it was not reflecting any color change in BottomNavigationView.
Then I realize, I was returning false in onNavigationItemSelected method. It will work fine if you'll return true in this method.
In order to set textColor, BottomNavigationView has two style properties you can set directly from the xml:
itemTextAppearanceActive
itemTextAppearanceInactive
In your layout.xml file:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bnvMainNavigation"
style="#style/NavigationView"/>
In your styles.xml file:
<style name="NavigationView" parent="Widget.MaterialComponents.BottomNavigationView">
<item name="itemTextAppearanceActive">#style/ActiveText</item>
<item name="itemTextAppearanceInactive">#style/InactiveText</item>
</style>
<style name="ActiveText">
<item name="android:textColor">#color/colorPrimary</item>
</style>
<style name="InactiveText">
<item name="android:textColor">#color/colorBaseBlack</item>
</style>
Try using android:state_enabled rather than android:state_selected for the selector item attributes.
This will work:
setItemBackgroundResource(android.R.color.holo_red_light)
Instead of creating selector,
Best way to create a style.
<style name="AppTheme.BottomBar">
<item name="colorPrimary">#color/colorAccent</item>
</style>
and to change the text size, selected or non selected.
<dimen name="design_bottom_navigation_text_size" tools:override="true">11sp</dimen>
<dimen name="design_bottom_navigation_active_text_size" tools:override="true">12sp</dimen>
Enjoy Android!
As the folder structure has changed, the tab_color.xml belongs to res > drawable now which can handle selectors. From there on the accepted solution works.
I use a spinner to display a dropdown list.
I want to have the items in the list to have rounded corners.
So I use 9-patch containing an image with rounded corners (transparent on the outside of the corners) for the views items background and a selector to display a different color 9-patch when pressed.
Problem: When I press the items in the spinner's list, I can see a blue background in the corners, where the 9-patch is transparent.
I can't seem to get rid of this blue background that appears when the items are pressed. If I remove the 9-patches and any setting in the spinner, I can see that the items views in the list are by default grey, and blue when pressed.
I tried also to not use 9 patches as the background but just a color selector, and set the pressed color in the selector to be transparent. Then when I press the item, it's not transparent, but blueish. I think the view in the list is really transparent, but there is still the blue color in the background when pressed...
I use a custom SpinnerAdapter to create the items view.
Here is the simplified code:
private class MySpinnerAdapter implements SpinnerAdapter {
#Override
public View getDropDownView(int i, View recycledView, ViewGroup viewGroup) {
View view = new View(context);
view.setBackground(context.getResources().getDrawable(R.drawable.testspinner));
view.setMinimumHeight(100);
return (View) view;
}
}
The selector used for the background. Here with just a color, and no 9-patch. The pressed color should be transparent:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#android:color/transparent" />
<item
android:drawable="#android:color/holo_purple" />
</selector>
I set the custom adapter on the spinner:
spinner.setAdapter(new MySpinnerAdapter());
And the spinner is fetched from XML layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent" android:layout_height="wrap_content">
<Spinner
android:id="#+id/myDropDown"
android:spinnerMode="dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dropDownWidth="match_parent"/>
</LinearLayout>
I have tried setting many different attributes on the Spinner, and tried some styling attributes, but I could not get rid of this blue background...
Thank you #Vikram for pointing out the use of styles.
However, after investigations it turns out that the background of the pressed item in the Spinner doesn't come from the attribute you suggested, but from android:listSelector. So I could fix the problem like this:
Define a new style in styles.xml:
<style name="MyListView">
<item name="android:listSelector">#android:color/transparent</item>
</style>
Define a new theme in themes.xml:
<style name="MyTheme" parent="#android:style/Theme.NoTitleBar.Fullscreen">
<item name="android:dropDownListViewStyle">#style/MyListView</item>
</style>
Apply the theme to my activity in AndroidManifest.xml:
<activity android:name=".MyActivity"
...
android:theme="#style/MyTheme">
Problem: When I press the items in the spinner's list, I can see a
blue background in the corners, where the 9-patch is transparent.
I think the blue background comes from android:selectableItemBackground attribute. To change this attribute, add the following to your application's theme in styles.xml:
<item name="android:selectableItemBackground">#drawable/whicheverDrawable</item>
For reference: By default, selectableItemBackground points to the following drawable in API 19 (for Theme.Holo). You should define whicheverDrawable in a similar way:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
<item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="#drawable/list_selector_disabled_holo_dark" />
<item android:state_focused="true" android:state_enabled="false" android:drawable="#drawable/list_selector_disabled_holo_dark" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="#drawable/list_selector_background_transition_holo_dark" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="#drawable/list_selector_background_transition_holo_dark" />
<item android:state_focused="true" android:drawable="#drawable/list_focused_holo" />
<item android:drawable="#color/transparent" />
</selector>
In your case, you can define rounded corners for another drawable, which is used for statePressed in whicheverDrawable.
I am struggling with this which apparently is a very simple effect but incredibly haven't found any intutitive way for doing it in Android.
I have a ListView and I managed to customize the background images so the selected item gets highlighted by getting a new background drawable. This I do creating a new style where I set the android:listSelector attribute to point a StateListDrawable where I have specified which drawables to use for every state.
However each ListView item is a LinearLayout where i have two TextViews. My goal is to be able to change the text color of these child views whenever the parent is selected or pressed, at the same time as the background drawable does. I know there is a ColorStateList but haven't been succesful setting that up.
Has anybody succeed getting something like this to work?
Thanks.
Neither of these are possible answers when your ListView is compromised of a layout that has multiple views. You need to set your child views to:
android:duplicateParentState="true"
Now you can use the methods others have described above to declare your TextViews' colors using a selector such as:
android:textColor="#drawable/my_row_selector"
and I'm sure you're aware, but the selector can be as simple as:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#color/white" />
<item android:color="#color/black" />
</selector>
As you can see, #color values are allowed. Hope this helps.
Also - android:state_pressed is used in conjunction with the AdapterView.OnItemClickListener.
in your textview propeties
android:textColor="#color/text_selector"
in res/color
text_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="YOUR_CUSTOM_COLOR" />
<item android:state_selected="true" android:color="YOUR_CUSTOM_COLOR" />
<item android:color="YOUR_CUSTOM_COLOR" />
</selector>
In order to make it work on selection use the following code:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#fff"/>
<item android:state_activated="true" android:color="#fff"/>
<item android:color="#000" />
</selector>
Apparently the key is state_activated="true" state.
When you are deploying the app for Android 11+ (HoneyComb+), you should use
android:state_activated="true"
for selected list state.
For the earlier versions use the combination of:
android:state_checked="true"
android:state_activated="true"
Of course don't forget to include the
android:duplicateParentState="true"
so the view can get the activated/checked state from a parent list view item
Also you may create a res/color folder and add a file "text_selector.xml" with the following lines:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:color="#f0f"/>
<item android:state_pressed="true" android:color="#f0f"/>
<item android:color="#000"/>
</selector>
After that assign in TextView:
android:textColor="#color/text_selector"
Is it possible to change the text color of a textview if the textview is pressed?
I want to achieve a flashing effect with the color change only lasting as long as the button is pressed.
I know how to change the background of the textview with a selector list and the correct state but how can I change the color of text if the user pushes a button or a simple textview?
You can define a selector for colors as well. A short example that only distinguishes between pressed and all other states is:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:color="#FFFFFF" />
<item
android:color="#4C566C" />
</selector>
For a full documentation on the selector see this unofficial documentation.
Put every color selector in a single file and put this files in a directory called color in the resources folder of your project.
Taken from official documentation:
XML file saved at res/color/button_text.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:color="#ffff0000"/> <!-- pressed -->
<item android:state_focused="true"
android:color="#ff0000ff"/> <!-- focused -->
<item android:color="#ff000000"/> <!-- default -->
</selector>
This layout XML will apply the color list to a View:
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/button_text"
android:textColor="#color/button_text" />
search for color selector to use in the
android:setTexColor
attr
you can change it using the setTextColor(ColorStateList) method
myTextView.setTextColor(myColorStates);
myTextView.setTextColor( 0xFFFF0000 )