Highlight the background of the navigation menu item currently selected - android

this is a snip/screenshot of my app design in Adobe Illustrator: https://imgur.com/a/7tXii
Depending on the menu you are currently in, the respective section shall be highlighted as shown below (light blue in this case).
I know that you can change the ITEM/ICON color via a custom ThemeOverlay that you create under /styles.xml and by adding app:theme="#style/afore_mentioned_theme_overlay" like this:
<style name="ThemeOverlay.AppCompat.navTheme">
<!-- Color of text and icon when SELECTED -->
<item name="colorPrimary">#color/color_of_your_choice</item>
<!-- Background color when SELECTED -->
<item name="colorControlHighlight">#color/color_of_your_choice</item>
</style>
However, all this does is change the icon color upon selection, instead of highlighting the section below the icon.
The main problem is, probably, that the navigation background is a horizontal bar along the entire screen, but I just want to change the color of 33% of it, depending on the selected item. This will probably require a dirty workaround (?).

Not that much of a dirty workaround required. Just add this after you initialized your BottomNavigationView instance:
navigation.setItemBackgroundResource(R.drawable.menubackground);
and put this inside /drawable/menubackground.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/colorAccent" android:state_pressed="true" />
<item android:drawable="#color/colorAccent" android:state_checked="true" />
<item android:drawable="#color/colorPrimary" />
</selector>
Looks like this:

Related

Customize BottomNavigationView to show text for the selected item, and icon for non-selected items

I'm trying to make this NavigationBottomView:
All I want is to make selected item text instead of icon.
I googled it and tried to make custom navigationBottomView item, but I found nothing like what I want.
is it possible to be a text ? or even can i hide the icon and display item title only ?
Yes it's.
To control toggling BottomNavigationView item text, use app:itemTextColor with a custom selector
In your case you need to show up the text when an item is checked, and hide it otherwise.
To control toggling the item icon, use app:itemIconTint with a custom selector
In your case you need to show up the icon when an item is unchecked, and hide it otherwise.
For both text/icon cases you can use a transparent color as a hack for the hidden state.
Example:
<com.google.android.material.bottomnavigation.BottomNavigationView
...
app:itemTextColor="#drawable/text_selector"
app:itemIconTint="#drawable/icon_selector"
text_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#FFEB3B" android:state_checked="true" />
<item android:color="#android:color/transparent" android:state_checked="false" />
</selector>
icon_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#FFEB3B" android:state_checked="false" />
<item android:color="#android:color/transparent" android:state_checked="true" />
</selector>
UPDATE
i tried it before but all i got icon get hidden and text still at the
bottom not shifted to the center like gif u sent
You can have the same behavior by changing the BottomNavView text size:
Create the following style to increase the item text:
<style name="BottomNavigationViewActiveItemText" parent="#style/TextAppearance.AppCompat.Caption">
<item name="android:textSize">20sp</item>
</style>
Apply it to the BottomNavigationView with app:itemTextAppearanceActive="#style/BottomNavigationViewActiveItemText"
If your item text can be in two lines, use also:
<style name="BottomNavigationStyle">
<item name="android:gravity">center</item>
<item name="android:lines">2</item>
</style>
And apply it with android:theme="#style/BottomNavigationStyle"

Setting text color in custom sliding tab view on first display

I'm trying so set the text color on sliding tabs within a custom view according to the tab state. It's working but not on initial display.
The textcolor in the custom view should be white when the tab is selected and darker grey otherwise. I got it partly working already: When I select a tab manually the text color changes correctly.
My problem is that on first display the text of the first tab, whose content is displayed initially and before any user interaction with the tabs, is not colored in the active state color (white). Its grey, like the inactive tabs. If I start interacting with the tabs, everything works, but the initial tab color of the first displayed tab is wrong.
[FIRST TAB | SECOND TAB]
^
Grey (inactive color) on first load
EDIT:
The cause seems to be in the styles.xml: If I declare a custom style that inherits from Widget.Design.TabLayout the initial coloring does not work anymore. If I do not declare custom styles for the tablayout, everything works fine!
EDIT2:
No, it doesn't work. It works without setting the custom view but it still does not do the initial coloring correctly when first loading the tabs with setting the custom view.
Here is my code:
tab_gallerylayout.xml (custom tab view)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.mbprojects.retro.view.RetroTextView
android:id="#+id/tab_title"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textColor="#drawable/gallerytab_title_color"
app:font="#string/font_name_syncopate"
/>
</LinearLayout>
gallerytab_title_color.xml (selector)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#android:color/white" />
<item android:state_selected="false" android:color="#android:color/darker_gray" />
<item android:state_focused="true" android:color="#android:color/white" />
<item android:state_pressed="true" android:color="#android:color/white" />
<item android:color="#android:color/darker_grey" />
</selector>
styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="#style/Theme.AppCompat.NoActionBar">
</style>
<style name="AppTheme.Base.Widget.Design.TabLayout" parent="Widget.Design.TabLayout">
<item name="tabMaxWidth">#dimen/tab_max_width</item>
<item name="tabIndicatorColor">#android:color/white</item>
<item name="tabIndicatorHeight">0dp</item>
<item name="tabPaddingStart">12dp</item>
<item name="tabPaddingEnd">12dp</item>
<item name="tabBackground">#android:color/black</item>
<item name="tabTextAppearance">#style/TextAppearance.Design.Tab</item>
</style>
Any suggestions?
The reason for this unusual behaviour is that your viewPager sets first item as current internally in viewPager.setAdapter(). This in turn makes tabLayout to select first tab in tabLayout.setupWithViewPager().
After this when you set custom tabs, state of custom view is not changed to "selected" (because select initial tab code already completed before this).
So, you need to explicilty change the state of custom view of selected tab.
Add below line after you set custom tabs and you're good to go.
mTabLayout.getTabAt(mInitialTab).getCustomView().setSelected(true);
You should use android:selector in your xml instead of the android:textColor. The former is for dynamically changing an attribute while the latter is assigning one value and keeping it

Changing default text colour and still showing disabled menu items in different colour

With Theme.Holo.Light as the base theme, a designer noticed that the default text colour is not black, but a dark grey (#505050). We'd like to change it to black.
Looking for a simple way to change the default to black everywhere in the app, I found that this works:
<resources>
<style name="MyAppTheme" parent="android:Theme.Holo.Light">
<item name="android:textColor">#android:color/black</item>
</style>
</resources>
Now, problem is, that also changes the colour of disabled items in Action Bar's overflow menu. How to override default text colour while still having disabled menu items look "disabled"?
The menu should look something like below, but using android:textColor as above, it changes all the items to black.
I was experimenting with textColorPrimaryInverse, textColorPrimaryDisableOnly, textColorPrimaryInverseDisableOnly and disabledAlpha but those didn't seem to affect the overflow menu.
You can use a drawable as the text colour, and in drawable you can use selector to select the colour according to enabled status. Using following drawable definition as colour will make your disabled menu items grey and the rest black.
In e.g. res/drawable/default_text_colour.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="#android:color/darker_gray"/>
<item android:color="#android:color/black"/>
</selector>
Then, using the drawable:
<item name="android:textColor">#drawable/default_text_colour</item>

Is it possible to grey out (not just disable) a MenuItem in Android?

There's a question for the same functionality on Blackberry, and a few different threads referred to this bug (which has since been closed without resolution as far as I can tell), but I haven't found one specifically for Android.
I'm calling setEnabled(false) on certain MenuItems based on some state, but they visually look the same. I'd like them to be offset in some way, so that the user knows that the option currently isn't available -- is there any way to do that?
On all android versions, easiest way to use this to SHOW a menu action icon as disabled AND make it FUNCTION as disabled as well:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.menu_my_item);
if (myItemShouldBeEnabled) {
item.setEnabled(true);
item.getIcon().setAlpha(255);
} else {
// disabled
item.setEnabled(false);
item.getIcon().setAlpha(130);
}
}
I had the same issue. There are two ways of getting this to work:
Put your icons in a StateList so that a different icon will be used on disable
What I use now. Change the icon yourself with something like this in onPrepareOptionsMenu():
public boolean onPrepareOptionsMenu(Menu menu) {
boolean menusEnabled = reachedEndOfSlidehow(); // enable or disable?
MenuItem item = menu.findItem(R.id.menu_next_slide);
Drawable resIcon = getResources().getDrawable(R.drawable.ic_next_slide);
if (!menusEnabled)
resIcon.mutate().setColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN);
item.setEnabled(menusEnabled); // any text will be automatically disabled
item.setIcon(resIcon);
}
You can call invalidateOptionsMenu() (or from ABS, supportInvalidateOptionsMenu()) to rebuild the menu.
EDIT: Updated solution 2
Source: https://groups.google.com/forum/?fromgroups#!topic/actionbarsherlock/Z8Ic8djq-3o
I found a new way to solve this issue using a drawable selector xml file. You just create a selector with the icon you want to use in your menu item, then you can either change the tint, alpha or both of the bitmap:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<bitmap android:src="#drawable/ic_menu_item"
android:tint="#color/enabled_color"
android:alpha="#integer/enabled_alpha"/>
</item>
<item android:state_enabled="false">
<bitmap android:src="#drawable/ic_menu_item"
android:tint="#color/disabled_color"
android:alpha="#integer/disabled_alpha"/>
</item>
</selector>
As a side note; I like to set the tint to "?android:attr/textColorPrimary" for enabled state and "?android:attr/textColorHint" for disabled state. This way it will adjust depending on the theme used.
Then you can just set the icon in your menu xml file to the selector resource:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/menu_action"
android:orderInCategory="0"
android:title="#string/title_menu_action"
android:icon="#drawable/ic_menu_item_selector"
app:showAsAction="ifRoom"/>
</menu>
Then when you call item.setEnabled(enabled) the color and/or alpha of the icon will change along with the state!
The way I did it is by using "itemIconTint" in NavigationView, you can also grey out the text by using "itemTextColor"
This is Navigationview:
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:itemBackground="#color/white"
android:background="#color/white"
app:itemTextColor="#color/menu_text_color"
app:itemIconTint="#color/menu_text_color"
app:menu="#menu/main_drawer" />
and the "#color/menu_text_color" is a selector:
<?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/primaryColor" />
<item android:state_enabled="false" android:color="#color/disabled_text_color" />
<item android:color="#color/primaryText" />
</selector>
Finally, if you want to disable a menuitem,
MenuItem item = mNavigationView.getMenu().findItem(R.id.your_menu_item);
item.setEnabled(isEnable);
Done!
I was having difficulty with this on modern android with MaterialComponents theme. My problem was I had set <item name="actionMenuTextColor">#color/blue</item> in styles.xml and this overrides the text color whether the item is enabled or disabled. The solution is to set a Color state list and not a color directly.
My styles attribute now looks like:
<item name="actionMenuTextColor">#color/menu_color_selector</item>
I had an issue where neither my the text nor the icon was visibly changing. The other answers either didn't work for me or weren't very elegant. Here's an answer that works for the latest Material recommendations.
You should be able to simply call menu.findItem(R.id.menu_my_item).isEnabled = false in onPrepareOptionsMenu(menu: Menu).
(If you need onPrepareOptionsMenu to run again, you can simply call invalidateOptionsMenu() or activity?.invalidateOptionsMenu() (from a fragment) and the application will queue up the menu to be recreated. Alternatively you can store off the menu item in a member variable to modify it later, but be careful to destroy your reference to it within onDestroyOptionsMenu to avoid a memory leak.)
The fact that the menu item is disabled should be enough to grey out the text or the icon automatically. The difficulty is in setting up your styles to make this work.
Short Answer
First create a color state list my_color_state_list.xml that you want your icons and text to use (e.g. black when enabled, grey when disabled). (See the full answer for an example.)
If you're using com.google.android.material.appbar.MaterialToolbar, you can tell it to use this selector for icons and text by providing a custom theme overlay. In your activity's XML, give the toolbar the attribute android:theme="#style/Foo" and define that style somewhere as:
<style name="Foo">
<item name="colorControlNormal">#color/my_color_state_list</item>
<item name="actionMenuTextColor">#color/my_color_state_list</item>
</style>
Now when the menu item is enabled or disabled via menu.findItem(R.id.menu_my_item).isEnabled = false the text will automatically change color, and any icons which use the color ?attr/colorControlNormal will also automatically change color.
Full answer
My starting place
My menu items are part of a Material toolbar. This answer may help for other kinds of toolbar/app bar, but your mileage may vary. In my activity I have something like this:
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.MaterialComponents.Toolbar.Surface"/>
and the theme I'm using looks something like this:
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="colorPrimary">#color/blue</item>
<item name="colorSecondary">#color/green</item>
<item name="colorSurface">#color/lightGrey</item>
<item name="colorOnSurface">#color/black</item>
[...]
<item name="windowActionModeOverlay">true</item>
</style>
It is also convention that the icon you use in buttons and menu items (and everywhere really) should have their default color be ?attr/colorControlNormal. So for example I might have a vector image which looks like:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal"
android:tintMode="src_atop">
<path android:pathData="..." android:fillColor="#android:color/white"/>
</vector>
If you download an icon from Material Icons you will see they all use colorControlNormal.
What I needed to do
If you look back at the definition of my toolbar, you will see it uses a ThemeOverlay ThemeOverlay.MaterialComponents.Toolbar.Surface which is defined as:
<style name="ThemeOverlay.MaterialComponents.Toolbar.Surface" parent="">
<item name="colorControlNormal">#color/material_on_surface_emphasis_medium</item>
<item name="actionMenuTextColor">#color/material_on_surface_emphasis_medium</item>
</style>
This sets the menu item text color and icon color to #color/material_on_surface_emphasis_medium which does not respond to being enabled or not. #color/material_on_surface_emphasis_medium looks like:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="#dimen/material_emphasis_medium" android:color="?attr/colorOnSurface"/>
</selector>
(You may be using ThemeOverlay.MaterialComponents.Toolbar.Primary instead, which has a similar issue - it simply uses colorOnPrimary.)
We need to replace this with our own color state list which responds to enabled state. So, make a new file res/color/menu_item_selector.xml that looks something like this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:alpha="#dimen/material_emphasis_medium" android:color="?attr/colorOnSurface"/>
<item android:alpha="#dimen/material_emphasis_disabled" android:color="?attr/colorOnSurface"/>
</selector>
You see I've used the same conventions that the material library does by using their constants to define the alpha values, and I used colorOnSurface as my color. If you were using ThemeOverlay.MaterialComponents.Toolbar.Primary you would want colorOnPrimary instead. Of course you can use any color or alpha here, it's up to you.
And now make a new ThemeOverlay in res/values/styles.xml to point to this selector, inheriting from whatever ThemeOverlay you were using:
<!-- Toolbar - overrides the menu text color to use a selector that responds to whether it's enabled or not -->
<style name="ThemeOverlay.MyTheme.Toolbar" parent="ThemeOverlay.MaterialComponents.Toolbar.Surface">
<!-- Color used in the icons of menu actions (i.e. non-overflow menu items). This is just convention, this will affect anything that uses ?attr/colorControlNormal) -->
<item name="colorControlNormal">#color/menu_item_color_selector</item>
<!-- Color used in the text of menu actions (i.e. non-overflow menu items) -->
<item name="actionMenuTextColor">#color/menu_item_color_selector</item>
</style>
And now finally we can apply this ThemeOverlay to the toolbar:
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.MyTheme.Toolbar"/>
setEnabled(false) works fine on API Level < 14 but on 14 the item still clickable.
Have a look at this link
setEnabled can also be used for MenuItems.
Here's a simple way to do it (using Kotlin):
fun changeMenuItemColour(enabled: Boolean) {
var menuItem = SpannableString(mCustomToolbar?.menu?.findItem(R.id.some_menu_item)?.title)
var style = activity?.resources?.getColor(R.color.darkGraphite)!!
if (enabled) style = activity?.resources?.getColor(R.color.black)!!
menuItem.setSpan(ForegroundColorSpan(style), 0, menuItem.length, 0)
}

How can I give a series of buttons with background colors a focus?

I made a layout that is just simply a textview that says "What do you want?", followed by a series of buttons underneath it.
All of the buttons can be clicked/touched, but when I scroll with the trackball, none of them become highlighted. I noticed, however, then when I disable the background colors on the buttons, I can see the orange box that shows that button's focus.
Is there any way I can visibly see the focus while still being able to have a background color on the buttons?
EDIT: Found the solution! This helped A LOT. Standard Android Button with a different color
Create a "selector" resource in your res/drawable. It can look something like this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="false"
android:state_pressed="false"
android:drawable="#color/white" />
<item
android:state_pressed="true"
android:drawable="#color/orange" />
<item
android:state_selected="true"
android:state_pressed="false"
android:drawable="#color/blue" />
</selector>
Then set the background of your button to be:
android:background="#drawable/your_selector"
Rather than applying a simple background color to buttons, try applying a ColorStateList instead.
To do so, define a new XML file at
/res/color/buttonstate.xml
and use code such as the following:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="# FOCUSED COLOR HERE"
android:state_focused="true" />
<item android:drawable="# DEFAULT COLOR HERE" />
</selector>
Notes:
You can definitely add more colors for more states, such as pressed, enabled, and certain other factors.
In the layout or code just reference R.color.buttonstate or #color/buttonstate (the XML's filename).
Make sure the default color is last. This is because it goes down the list and finds the first item that has all of the states the same as it. If you don't provide android:state_focused="false" for the default item and put it first, it will always display.
You can do a similar thing with drawables and
nine-patch drawables to make your own custom button styles.
Rather than just change the background color, consider using a 9-patch style. This is more work to begin, but you'll have much more control over your app's appearance.
Modify your Button layout to look something like this (the style line is the kicker):
<Button
style="#style/PushButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Your styles.xml resource file then should contain a style similar to this:
<style name="PushButton">
<item name="android:background">#drawable/btn</item>
</style>
Then the btn.xml (put in in res/drawable) contents should look something like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/btn_pressed"
android:state_pressed="true" />
<item android:drawable="#drawable/btn_focused"
android:state_pressed="false"
android:state_focused="true" />
<item android:drawable="#drawable/btn_default"
android:state_focused="false"
android:state_pressed="false" />
You would then use some image editor to create files named btn_pressed.9.png, btn_focused.9.png, and btn_default.9.png. Drop these files in your res/drawable.
A good starting point is the Google IO app (I lifted the code examples from it). Just grab the png files and modify them to match your desired style.
Keep in mind you can put all sorts of stuff in the style now, like text size, height and width.

Categories

Resources