How to customize individual tabs? (changing background color, indicator color and text color)

android, android-actionbar-compat, android-tabs, android-viewpager

Solution

Just set your custom view at the tab creation time, something like:

final Tab firstTab = actionBar.newTab()
                              .setText(mAppSectionsPagerAdapter.getPageTitle(0))
                              .setCustomView(R.id.custom_tab_view_red);
final Tab secondTab = actionBar.newTab()
                               .setText(mAppSectionsPagerAdapter.getPageTitle(1))
                               .setCustomView(R.id.custom_tab_view_blue);
// etc

actionBar.addTab(firstTab);
actionBar.addTab(secondTab);
// etc

in `inCreate()`.

You'll also have to define `View`s corresponding to the above `id`s in your xml layout file (and not `style`s).

Or, if you want to create the view directly:

final View firstCustomView = new CustomView(this);
firstCustomView.setBackgroundColor(Color.BLUE);  // or with drawable or resource
final Tab firstTab = actionBar.newTab()
                              .setText(mAppSectionsPagerAdapter.getPageTitle(0))
                              .setCustomView(firstCustomView);
actionBar.addTab(firstTab);
// then same for other tabs, just with another color

Leaving the below information for reference:

To define one such view, you need to specify it an Android `Context`. This is usually the `Activity` where the tabs will be displayed. Supposing that you initialize your tabs in an `Activity`, simply pass the `Activity` instance as a `Context`:

ctv = new CustomView(this, R.attr.tabStyleAttr);

if from inside the `Activity`, or for example:

ctv = new CustomView(getActivity(), R.attr.tabStyleAttr);

if from inside a `Fragment`, etc.

As for setting a specific style for action bar tabs, no need to go create a custom view programmatically as you're trying to. Read up a little about the action bar first, then check the example they provide. As you can see, you'll be able to specify the tab style in xml:

In your manifest file, you can apply the theme to your entire app:

<application android:theme="@style/CustomActionBarTheme" ... />

Or to individual activities:

<activity android:theme="@style/CustomActionBarTheme" ... />

for example.

For a complete example matching perfectly your use case, see this Android doc article: https://developer.android.com/training/basics/actionbar/styling.html#CustomTabs . Notice the usage of state-lists to achieve the "when selected style".

Problem

In this link : How do I apply a style programmatically? Kevin Grant gave a explaination to this question my problem with his code is the context part. To be precise : ``` ctv = new CustomView(context, R.attr.tabStyleAttr); ``` In this code it says : context cannot be resolved to a variable I want to apply specific style to tabs and that's why setting theme doesn't work for me. Any alternative to my problem is welcome too of course. I try to change the background color, indicator color and text color of actionbar tabs. ``` @Override public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { CustomView ctv; ctv = new CustomView(this, R.attr.tabStyleAttr); tab.setCustomView(ctv); mViewPager.setCurrentItem(tab.getPosition()); } ``` styles.xml ``` <?xml version="1.0" encoding="utf-8"?> <resources> <style name="Theme.Ab" parent="@android:style/Theme.Holo.Light"> <item name="android:actionBarStyle">@style/abStyle</item> <item name="@attr/actionBarTabStyle">@style/tabStyle</item> <item name="android:actionBarTabTextStyle">@style/tabTextColor</item> </style> <style name="abStyle" parent="@android:style/Widget.Holo.Light.ActionBar.Solid"> <item name="android:background">@drawable/ab_solid_style</item> <item name="android:backgroundStacked">@drawable/ab_stacked_solid_style</item> <item name="android:backgroundSplit">@drawable/ab_bottom_solid_style</item> <item name="android:height">100dp</item> </style> <style name="tabStyle" parent="@android:style/Widget.Holo.Light.ActionBar.TabView"> <item name="android:background">@drawable/tab_indicator_ab_style</item> </style> <style name="tabTextColor" parent="@android:style/Widget.Holo.Light.ActionBar.TabText"> <item name="android:textColor">@android:color/white</item> </style> </resources> ``` MainActivity.java (onCreate) ``` public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Create the adapter that will return a fragment for each of the three primary sections // of the app. mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager()); // Set up the action bar. final ActionBar actionBar = getActionBar(); //set custom actionbar actionBar.setCustomView(R.layout.titlebar); //Displays the custom design in the actionbar actionBar.setDisplayShowCustomEnabled(true); //Turns the homeIcon a View View homeIcon = findViewById(android.R.id.home); //Hides the View (and so the icon) ((View)homeIcon.getParent()).setVisibility(View.GONE); // Specify that we will be displaying tabs in the action bar. actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // Set up the ViewPager, attaching the adapter and setting up a listener for when the // user swipes between sections. mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mAppSectionsPagerAdapter); mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { // When swiping between different app sections, select the corresponding tab. // We can also use ActionBar.Tab#select() to do this if we have a reference to the Tab. actionBar.setSelectedNavigationItem(position); } }); // For each of the sections in the app, add a tab to the action bar. for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) { // Create a tab with text corresponding to the page title defined by the adapter. // Also specify this Activity object, which implements the TabListener interface, as the // listener for when this tab is selected. Tab tab = actionBar.newTab().setText(mAppSectionsPagerAdapter.getPageTitle(i)).setTabListener(this); actionBar.addTab(tab); } } ``` This is what I want to make: As for the new result using Views this happened MainActivity.java ``` package com.example.android.effectivenavigation; import android.app.ActionBar; import android.app.ActionBar.Tab; import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; public class MainActivity extends FragmentActivity implements ActionBar.TabListener { AppSectionsPagerAdapter mAppSectionsPagerAdapter; //The viewpager displays on of the section at a time ViewPager mViewPager; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Create the adapter that will return a fragment for each of the three primary sections // of the app. mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager()); // Set up the action bar. final ActionBar actionBar = getActionBar(); //set custom actionbar actionBar.setCustomView(R.layout.titlebar); //Displays the custom design in the actionbar actionBar.setDisplayShowCustomEnabled(true); //Turns the homeIcon a View View homeIcon = findViewById(android.R.id.home); //Hides the View (and so the icon) ((View)homeIcon.getParent()).setVisibility(View.GONE); // Specify that we will be displaying tabs in the action bar. actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // Set up the ViewPager, attaching the adapter and setting up a listener for when the // user swipes between sections. mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mAppSectionsPagerAdapter); mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { // When swiping between different app sections, select the corresponding tab. // We can also use ActionBar.Tab#select() to do this if we have a reference to the Tab. actionBar.setSelectedNavigationItem(position); } }); /*final Tab firstTab = actionBar.newTab() .setText(mAppSectionsPagerAdapter.getPageTitle(0)) .setTabListener(this) .setCustomView(R.id.nieuws_tab_layout); /*final Tab secondTab = actionBar.newTab() .setText(mAppSectionsPagerAdapter.getPageTitle(1)) .setCustomView(R.id.nieuws_tab_layout); final Tab thirdTab = actionBar.newTab() .setText(mAppSectionsPagerAdapter.getPageTitle(2)) .setCustomView(R.id.nieuws_tab_layout); actionBar.addTab(firstTab); actionBar.addTab(secondTab); actionBar.addTab(thirdTab);*/ // For each of the sections in the app, add a tab to the action bar. for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) { if(i == 0) { final View firstCustomView = new CustomView(this); //firstCustomView.setBackgroundColor(Color.BLUE); Tab tab = actionBar.newTab().setText(mAppSectionsPagerAdapter.getPageTitle(i)).setTabListener(this).setCustomView(R.layout.nieuws_tab_layout); actionBar.addTab(tab); } else { // Create a tab with text corresponding to the page title defined by the adapter. // Also specify this Activity object, which implements the TabListener interface, as the // listener for when this tab is selected. Tab tab = actionBar.newTab().setText(mAppSectionsPagerAdapter.getPageTitle(i)).setTabListener(this); actionBar.addTab(tab); } } } @Override public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { } @Override public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { //CustomView ctv; //ctv = new CustomView(context, R.attr.tabStyleAttr); // When the given tab is selected, switch to the corresponding page in the ViewPager. //LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); //View tabView = inflater.inflate(R.layout.nieuws_tab_layout, null); //tabView.setBackgroundColor(0xFF00FF00); //tab.setCustomView(tabView); mViewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { } public static class AppSectionsPagerAdapter extends FragmentPagerAdapter { public AppSectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { switch (i) { case 0: // The first section of the app is the most interesting -- it offers // a launchpad into the other demonstrations in this example application. return new LaunchpadSectionFragment(); default: // The other sections of the app are dummy placeholders. Fragment fragment = new DummySectionFragment(); Bundle args = new Bundle(); args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, i + 1); fragment.setArguments(args); return fragment; } } @Override public int getCount() { return 3; } @Override public CharSequence getPageTitle(int position) { switch(position) { case 0: { return "Tab1"; } case 1: { return "Tab2"; } case 2: { return "Tab3"; } default: { return "Section " + (position + 1); } } } } public static class LaunchpadSectionFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_section_launchpad, container, false); // Demonstration of a collection-browsing activity. rootView.findViewById(R.id.demo_collection_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(getActivity(), CollectionDemoActivity.class); startActivity(intent); } }); // Demonstration of navigating to external activities. rootView.findViewById(R.id.demo_external_activity).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Create an intent that asks the user to pick a photo, but using // FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, ensures that relaunching // the application from the device home screen does not return // to the external activity. Intent externalActivityIntent = new Intent(Intent.ACTION_PICK); externalActivityIntent.setType("image/*"); externalActivityIntent.addFlags( Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); startActivity(externalActivityIntent); } }); return rootView; } } /** * A dummy fragment representing a section of the app, but that simply displays dummy text. */ public static class DummySectionFragment extends Fragment { public static final String ARG_SECTION_NUMBER = "section_number"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_section_dummy, container, false); Bundle args = getArguments(); ((TextView) rootView.findViewById(android.R.id.text1)).setText(getString(R.string.dummy_section_text, args.getInt(ARG_SECTION_NUMBER))); return rootView; } } public class CustomView extends View { public CustomView(Context context) { super(context, null); } } } ``` tab_layout.xml ``` <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/nieuws_tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/nieuws" android:gravity="center_vertical" android:layout_marginTop="15dp" android:textColor="@android:color/white" android:textStyle="bold" android:background="@android:color/black" /> </LinearLayout> ```

Original source

Related problems