Changing ActionBar tabs underline color programmatically - android

I have created the action bar by
ActionBar actionbar = getActionBar()
The background of the action bar is changed by
actionbar.setBackgroundDrawable(actionBarBackgroundImage);
Now I need to change the action bar tabs underline color programmatically. Is there any method to change the action bar tabs underline color?

Alternatively you could use Android Action Bar Style Generator to easily theme your action bar and tabs.

Here is a much easier way. I know you were looking for a programmatic change, but this one is REALLY easy.
I've been struggling with this for days, but finally found the solution. I'm using AppCompat. You can set colorAccent in your theme and that will change the highlight color on your ActionBar. Like so:
<item name="colorAccent">#color/highlightcolor</item>
Here it is in context:
<style name="LightTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/darkgrey</item>
<item name="colorPrimaryDark">#color/black</item>
<item name="colorAccent">#color/highlightcolor</item>
</style>
Where I originally posted this answer: Android Tab underline color not changing

I'll suggest you use ActionBarSherlock. There is one sample available in the library named "Style ActionBar". (this is only way you can change ActionBar tabs underline color)
if you have customized ActionBar then You have to add this style in ActionBar Style
or here is way how to Do this
create style like below (here i have used ActionBarShareLock if you don't want to use then use android-support-v4.jar for support all Android OS Version)
<style name="Theme.AndroidDevelopers" parent="Theme.Sherlock.Light">
<item name="android:actionBarTabStyle">#style/MyActionBarTabStyle</item>
<item name="actionBarTabStyle">#style/MyActionBarTabStyle</item>
</style>
<!-- style for the tabs -->
<style name="MyActionBarTabStyle" parent="Widget.Sherlock.Light.ActionBar.TabBar">
<item name="android:background">#drawable/actionbar_tab_bg</item>
<item name="android:paddingLeft">32dp</item>
<item name="android:paddingRight">32dp</item>
actionbar_tab_bg.xml
<item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="#drawable/ad_tab_unselected_holo" />
<item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="#drawable/ad_tab_selected_holo" />
<item android:state_selected="false" android:state_pressed="true" android:drawable="#drawable/ad_tab_selected_pressed_holo" />
<item android:state_selected="true" android:state_pressed="true" android:drawable="#drawable/ad_tab_selected_pressed_holo" />
applay this style in your activity in android manifest file
<activity
android:name="com.example.tabstyle.MainActivity"
android:label="#string/app_name"
android:theme="#style/Theme.AndroidDevelopers" >
for more detail check this answer and this article.
EDITED : 29-09-2015
ActionBarSherlock is deprecated so alternatively you can use android design support library and android app appcompat library for TOOLBAR(Action-Bar is deprecated so..) and TABS.
use TabLayout like below
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="center"
app:tabMode="scrollable"
app:tabSelectedTextColor="#color/white"
app:tabIndicatorColor="#color/colorPrimary"
app:tabIndicatorHeight="2dip"
app:tabTextAppearance="?android:attr/textAppearanceMedium"
app:tabTextColor="#color/colorAccent" />
here is sample of android design support library with tab

Refer this, for customize action bar,
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- the theme applied to the application or activity -->
<style name="CustomActivityTheme" parent="#android:style/Theme.Holo">
<item name="android:actionBarStyle">#style/MyActionBar</item>
<!-- other activity and action bar styles here -->
</style>
<!-- style for the action bar backgrounds -->
<style name="MyActionBar" parent="#android:style/Widget.Holo.ActionBar">
<item name="android:background">#drawable/ab_background</item>
<item name="android:backgroundStacked">#drawable/ab_background</item>
<item name="android:backgroundSplit">#drawable/ab_split_background</item>
</style>
</resources>

I tried many of the suggestions posted here and other places with no luck. But I think I managed to piece together a (albeit not perfect) solution.
The TabWidget is using a selector. Essentially it is showing a different 9 patch image depending on the state of the tab (selected, pressed, etc.). I finally figured out that you could generate a selector programmatically. I started with generated 9 patches from http://android-holo-colors.com/ (color: #727272, TabWidget: Yes).
The biggest issue was setting the color. Setting the color filter did nothing. So, I ended up changing the colors of each of the pixels of the 9 patch image inside a loop.
...
/**
* <code>NinePatchDrawableUtility</code> utility class for manipulating nine patch resources.
*
* #author amossman
*
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class NinePatchDrawableUtility {
// Matches the colors in the supported drawables
private static final int TAB_UNDERLINE_HIGHLIGHT_COLOR = 1417247097;
private static final int TAB_UNDERLINE_COLOR = -8882056;
private static final int TAB_PRESSED_COLOR = -2122745479;
private Resources resources;
public NinePatchDrawableUtility(Resources resources) {
this.resources = resources;
}
/**
* Create a <code>StateListDrawable</code> that can be used as a background for the {#link android.widget.TabWidget}</br></br>
*
* <code>
* FragmentTabHost tabHost = ...</br>
* NinePatchUtility ninePatchUtility = new NinePatchUtility(getResources());</br>
* TabWidget tabWidget = tabHost.getTabWidget();</br>
* for (int i = 0; i < tabWidget.getChildCount(); i++) {</br>
* tabWidget.getChildAt(i).setBackground(ninePatchUtility.getTabStateListDrawable(titleColor));</br>
* }
* </code>
*
* #param tintColor The color to tint the <code>StateListDrawable</code>
* #return A new <code>StateListDrawable</code> that has been tinted to the given color
*/
public StateListDrawable getTabStateListDrawable(int tintColor) {
StateListDrawable states = new StateListDrawable();
states.addState(new int[] {android.R.attr.state_pressed},
changeTabNinePatchColor(resources, R.drawable.cc_tab_selected_pressed_holo, tintColor));
states.addState(new int[] {android.R.attr.state_focused},
changeTabNinePatchColor(resources, R.drawable.cc_tab_selected_focused_holo, tintColor));
states.addState(new int[] {android.R.attr.state_selected},
changeTabNinePatchColor(resources, R.drawable.cc_tab_selected_holo, tintColor));
states.addState(new int[] { },
changeTabNinePatchColor(resources, R.drawable.cc_tab_unselected_holo, tintColor));
return states;
}
/**
* Change the color of the tab indicator.</br></br>
*
* Supports only the following drawables:</br></br>
*
* R.drawable.cc_tab_selected_pressed_holo</br>
* R.drawable.cc_tab_selected_focused_holo</br>
* R.drawable.cc_tab_selected_holo</br>
* R.drawable.cc_tab_unselected_holo</br></br>
*
* Note: This method is not efficient for large <code>Drawable</code> sizes.
*
* #param resources Contains display metrics and image data
* #param drawable The nine patch <code>Drawable</code> for the tab
* #param tintColor The color to tint the <code>Drawable</code>
* #return A new <code>NinePatchDrawable</code> tinted to the given color
*/
public NinePatchDrawable changeTabNinePatchColor(Resources resources, int drawable, int tintColor) {
int a = Color.alpha(tintColor);
int r = Color.red(tintColor);
int g = Color.green(tintColor);
int b = Color.blue(tintColor);
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inMutable = true;
Bitmap bitmap = BitmapFactory.decodeResource(resources, drawable, opt);
for (int x = 0; x < bitmap.getWidth(); x++) {
for (int y = 0; y < bitmap.getHeight(); y++) {
int color = bitmap.getPixel(x, y);
if (color == TAB_PRESSED_COLOR) {
bitmap.setPixel(x, y, Color.argb((int)(a * 0.5), r, g, b));
} else if (color == TAB_UNDERLINE_HIGHLIGHT_COLOR) {
bitmap.setPixel(x, y, Color.argb((int)(a * 0.9), r, g, b));
} else if (color == TAB_UNDERLINE_COLOR) {
bitmap.setPixel(x, y, tintColor);
}
}
}
return new NinePatchDrawable(resources, bitmap, bitmap.getNinePatchChunk(), new Rect(), null);
}
}
Example of usage:
/**
* Theme the tab widget with the defined background color and title color set
* in the TabManager
* #param tabWidget
*/
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
public void theme(TabWidget tabWidget) {
ColorDrawable backgroundDrawable = new ColorDrawable(backgroundColor);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
tabWidget.setBackground(backgroundDrawable);
tabWidget.setAlpha(0.95f);
} else {
backgroundDrawable.setAlpha(242);
tabWidget.setBackgroundDrawable(backgroundDrawable);
}
NinePatchDrawableUtility ninePatchUtility = new NinePatchDrawableUtility(resources);
for (int i = 0; i < tabWidget.getChildCount(); i++) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
tabWidget.getChildAt(i).setBackground(ninePatchUtility.getTabStateListDrawable(titleColor));
} else {
tabWidget.getChildAt(i).setBackgroundDrawable(ninePatchUtility.getTabStateListDrawable(titleColor));
}
View tabView = tabWidget.getChildTabViewAt(i);
tabView.setPadding(0, 0, 0, 0);
TextView tv = (TextView) tabView.findViewById(android.R.id.title);
tv.setSingleLine(); // set the texts on the tabs to be single line
tv.setTextColor(titleColor);
}
}

Got the solution for changing the Tab Highlighter Color after 1 long day of search.Just 2 lines of code makes this work perfect!
Go to values/styles.xml and add the code below in ActionBar Theme
<item name="colorAccent">#color/Tab_Highlighter</item>
Now give the color for Tab_Highlighter in colors.xml
<color name="Tab_Highlighter">#ffffff</color>

you can use this code:
actionBar.setStackedBackgroundDrawable(new ColorDrawable(yourColor));

Related

Status bar overlay image shifted down in android nought

I am trying to add an image to the status bar in xamarin forms android..
But the image is completely shifted down and coming under the normal status bar color i set in android nougat.
This happened when i updated the xamarin forms version to 2.4.0.74863
in 2.3.4.270 its working fine. Is this the xamrin forms issue or my code issue.
The code i used to draw overlay on status bar is
activity.Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
activity.Window.ClearFlags(WindowManagerFlags.TranslucentStatus);
activity.Window.SetStatusBarColor(Android.Graphics.Color.Transparent);
ViewGroup contentView = (ViewGroup)activity.FindViewById(Android.Resource.Id.Content);
//if (contentView.ChildCount > 1)
//{
// contentView.RemoveViewAt(1);
//}
// get status bar height
int res = activity.Resources.GetIdentifier("status_bar_height", "dimen", "android");
int height = 0;
if (res != 0)
height = activity.Resources.GetDimensionPixelSize(res);
// create new imageview and set resource id
ImageView image = new ImageView(activity);
LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, height);
params1.Width = LinearLayout.LayoutParams.MatchParent;
image.LayoutParameters = params1;
image.SetImageResource(imageRes);
image.SetScaleType(ImageView.ScaleType.FitXy);
// add image view to content view
contentView.AddView(image);
contentView.SetFitsSystemWindows(true);
I call this as a dependedncy from the xaml page.
EDIT
After i added the flags that #york mentioned the bottom navigation bar has become translucent and the app view went down.
Just need add the following code in your Activity style :
<style name="MyTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
...
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">#android:color/transparent</item>
</style>
Effect :

How to control NavigationView margin between menu items

I have a navigation drawer with many items so the user needs to scroll up and down in order to see all the items.
I would like to reduce the margins between individual menu items, so that all items fit within a standard screen with no need to scroll.
Is there a way to control the margins in between the menu items?
Answer here helped me to reduce space at least between groups. I used the following dimen
<dimen tools:override="true" name="design_navigation_separator_vertical_padding">1dp</dimen>
We can create a drawable and set it as the NavigationView's itemBackground attribute. I will explain below:
If we walk through the NavigationMenuAdapter, we will see there are four types of items:
private static final int VIEW_TYPE_NORMAL = 0;
private static final int VIEW_TYPE_SUBHEADER = 1;
private static final int VIEW_TYPE_SEPARATOR = 2;
private static final int VIEW_TYPE_HEADER = 3;
What we want to work with is VIEW_TYPE_NORMAL. The attributes exposed to developers can be found in the below code:
case VIEW_TYPE_NORMAL:
{
NavigationMenuItemView itemView = (NavigationMenuItemView) holder.itemView;
itemView.setIconTintList(iconTintList);
if (textAppearanceSet) {
itemView.setTextAppearance(textAppearance);
}
if (textColor != null) {
itemView.setTextColor(textColor);
}
ViewCompat.setBackground(
itemView,
itemBackground != null ? itemBackground.getConstantState().newDrawable() : null);
NavigationMenuTextItem item = (NavigationMenuTextItem) items.get(position);
itemView.setNeedsEmptyIcon(item.needsEmptyIcon);
itemView.setHorizontalPadding(itemHorizontalPadding);
itemView.setIconPadding(itemIconPadding);
if (hasCustomItemIconSize) {
itemView.setIconSize(itemIconSize);
}
itemView.setMaxLines(itemMaxLines);
itemView.initialize(item.getMenuItem(), 0);
break;
}
Unfortunately,there is no interface for us to add margins between the NavigationMenuItemView. However, it allows us to set a background. So we can set a customer drawable to the NavigationView with a specific height. We only set a height in that drawable, like:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle">
<size android:height="60dp"/>
</shape>
Then apply this drawable to the NavigationView in the layout.xml, like:
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:itemBackground="#drawable/bk_menu_item"/>
I understand it is not a perfect solution, but it seems the only solution working in my case.
Paste this in styles.xml
<style name="NavigationTheme" parent="AppTheme">
<item name="android:textSize">16sp</item>
<item name="android:layout_marginBottom">02dp</item>
</style>
In navigation drawer put this in each item:
android:theme="#style/NavigationTheme"
add below code in dimens.xml
<dimen tools:override="true" name="design_navigation_icon_padding">16dp</dimen>

Changing ActionBar background affects Navigation drawer

I'm changing the ActionBar background in a fragment with a ScrollView. I have a ScrollView listener which changes the alpha of the items in the layered-list based on the scroll distance. The action bar actually works great. However, the Navigation Drawer background gets affected by this alpha change and I have no idea why; the nav drawer background becomes invisible. I can reproduce this easily on a Nexus 7 running Android L but it doesn't always happen for some 4.4 devices.
The main part is:
ActionBar actionBar = activity.getSupportActionBar();
LayerDrawable mActionBarBg = (LayerDrawable) getResources().getDrawable(R.drawable.background_actionbar);
if (mActionBarBg != null) {
setActionBarBgAlpha(0);
actionBar.setBackgroundDrawable(mActionBarBg);
}
Alpha calculator is this:
scrollView.setOnScrollChangedLitstener(new OnScrollChangedListener() {
#Override
public void onScrollChanged(int l, int t, int oldl, int oldt) {
t = Math.max(t, 0);
endpointHeader.setTranslationY(endpointHeader.getTop() + (t * 0.25f));
mScrollAlpha = (int) Math.min(alphaToHeightRatio * t, 255);
updateActionBarElemsAlpha(mScrollAlpha);
}
});
Couple of other methods:
private void updateActionBarElemsAlpha(int updatedAlpha){
if(mActionBarTitleColor != null){
mActionBarTitleColor.setAlpha(updatedAlpha);
mActionBarTitleView.setTextColor(mActionBarTitleColor.getColor());
}
setActionBarBgAlpha(updatedAlpha);
}
private void setActionBarBgAlpha(int alpha){
if(mActionBarBg != null){
mActionBarBg.getDrawable(1).setAlpha(alpha);
mActionBarBg.getDrawable(2).setAlpha(alpha);
}
}
background_actionbar.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/gradient" />
<item android:drawable="#color/grey_divider"/>
<item android:bottom="2dp"
android:drawable="#color/White"/>
</layer-list>
You should always mutate drawables before changing any attributes, otherwise you'll end up modifying the cached state which is by default shared across all instances.
if (mActionBarBg != null) {
mActionBarBg.mutate();
mActionBarBg.getDrawable(1).setAlpha(alpha);
mActionBarBg.getDrawable(2).setAlpha(alpha);
}

Get the current ActionBar size

I tried several things before and searched the web, but no answer.
How do I get the current ActionBar size?
I styled my ActionBar like this:
<style name="MusicSlide.Theme.ActionBar" parent="android:Widget.Holo.ActionBar">
<item name="android:height">60dp</item>
<item name="android:actionBarSize">60dp</item>
<item name="android:homeAsUpIndicator">#drawable/ic_drawer</item>
<item name="android:background">#color/complete_transparent</item>
<item name="android:titleTextStyle">#style/MusicSlide.Theme.ActionBar.TitleText</item>
<item name="android:subtitleTextStyle">#style/MusicSlide.Theme.ActionBar.TitleText</item>
</style>
It is transparent.
In my app I implemented a DrawerLayout. I don't want the DrawerLayout to be underneath the ActionBar , so I set the margin of the DrawerLayout:
final TypedArray styledAttributes = mContext.getTheme().obtainStyledAttributes(
new int[] { android.R.attr.actionBarSize });
int actionheight = (int) styledAttributes.getDimension(0, 0);
styledAttributes.recycle();
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) mDrawerListRight
.getLayoutParams();
mlp.setMargins(0,(actionheight + statbarheight),0,0);
The problem is that android.R.attr.actionBarSize returns the original height of the ActionBar.
How do I get the 60dp I set in my style?
android:actionBarSize isn't an attribute of Widget.ActionBar, this is why you aren't returning the correct value. Add that line to your app's theme, wherever you define android:actionBarStyle.

Android - Get highlight color of listview programatically (backward compatibly)

When the user presses a listview item it gets highlighted, and returns back to its original color when they let go.
I would like to programmatically query what colors these are.
On an Api version later than 14 it seems I can use
(i) Theme.resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) or
(ii) Theme.obtainStyledAttributes(int[] attrs)
//-- (i) ---------------------------------------------
int getAttrVal(int attr)
{
TypedValue Val = new TypedValue();
getContext().getTheme().resolveAttribute(attr, Val, true);
return Val.data;
}
int colBgd = getAttrVal(android.R.attr.colorBackground);
int colAh = getAttrVal(android.R.attr.colorActivatedHighlight);
int colPh = getAttrVal(android.R.attr.colorPressedHighlight); // not sure if this or prev is what im looking for!?
// (ii) ---------------------------------------------
TypedArray Arr = getContext().getTheme().obtainStyledAttributes(
new int[] {android.R.attr.colorPressedHighlight});
int colPh2 = arrTst.getColor(0, 0xFF00FF);
//--------------------------------------------------
On older Api versions this wont work since
android.R.attr.colorActivatedHighlight/colorPressedHighlight
were not available yet.
(1) Is there a to programmatically get these colours on api 8?
(2) I'm a bit confused as to some of the other functions in Theme
eg (iii) Theme.obtainStyledAttributes(int resid, int[] attrs)
// ---------------------------------------------
TypedArray Arr2 = getContext().getTheme().obtainStyledAttributes(
android.R.attr.colorBackground, new int[] {android.R.attr.colorPressedHighlight});
int colTst2 = arrTst.getColor(0, 0xFF00FF);
Here it seems not to matter what value I use for resid. What's the point of this parameter?
(3) What's the difference between R.attr and R.styleable?
Is R.attr supposed to be a replacement for R.styleable (and basically have corresponding entries), or do their purposes only partly overlap.
You should have a selector declared with the items bellow:
<item android:drawable="#color/selected" android:state_focused="true" android:state_pressed="true"/>
<item android:drawable="#color/selected" android:state_focused="false" android:state_pressed="true"/>
<item android:drawable="#color/selected" android:state_focused="true"/>
<item android:drawable="#color/normal" android:state_focused="false" android:state_pressed="false"/>
and set it as background for listRow

Categories

Resources