Android change tab icon when selected tutorial with example is tonight’s hot topic.
In this tutorial, you will learn how to change tab icon, tab text, tab icon color, tab text color, tab background color, indicator color programmatically when user selects the tab.
Developers use these features to indicate the current working tab to the user.
Output
What will be the final output at the end of this example?
Check it out in the below video.
Step 1. Update colors.xml file
Add some necessary colors in the colors.xml file which is located at the values->colors.xml path.
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#525e5e</color> <color name="colorPrimaryDark">#41f8f8</color> <color name="colorAccent">#525e5e</color> <color name="greyback">#1e2926</color> <color name="black">#000000</color> <color name="view">#5e6664</color> <color name="tranparent">#00ffffff</color> <color name="white">#FFFFFF</color> </resources>
Step 2. Necessary strings
A file which is available at values->strings.xml needed to be replaced with following source code
<resources> <string name="app_name">ChangeTabIcon</string> <string name="login">Login</string> <string name="intro">Introduction</string> <string name="Product">Product</string> <string name="Location">Location</string> <!-- TODO: Remove or change this placeholder text --> <string name="hello_blank_fragment">Hello blank fragment</string> </resources>
Step 3. Various Icons
As we want to change the color or may be the whole icon when the user clicks on the tab, we need to add different icons for every situation.
There should be different icons for both events, when the tab is selected and when it is deselected.
Click on below link to download necessary icons for this practical example tutorial.
[sociallocker]Download All the Icons[/sociallocker]
Now copy all these icons in the mipmap folder.
Step 4. Making Drawable resource files
In the drawable folder, make one new resource file and name it like roundback.xml
Copy the following code in it
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <!-- <stroke android:width="1dp" android:color="@color/common_border_color" />--> <!-- <solid android:color="#ffffff" />--> <gradient android:startColor="#525e5e" android:endColor="#525e5e" android:angle="270" /> <corners android:bottomRightRadius="2.3dp" android:bottomLeftRadius="0dp" android:topLeftRadius="0dp" android:topRightRadius="2.3dp" /> </shape>
Create another resource file named roundleft.xml and add the below code
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <!-- <stroke android:width="1dp" android:color="@color/common_border_color" />--> <!-- <solid android:color="#ffffff" />--> <gradient android:startColor="#525e5e" android:endColor="#525e5e" android:angle="270" /> <corners android:bottomRightRadius="0dp" android:bottomLeftRadius="2.3dp" android:topLeftRadius="2.3dp" android:topRightRadius="0dp" /> </shape>
Step 5. Four Fragments for Four Tabs
There are four tabs in this android studio example so we have to create separate fragments for each tab.
Make first fragment with name IntroFragment.
Add below code in IntroFragment.java file
import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class IntroFragment extends Fragment { public IntroFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_intro, container, false); } }
Code for fragment_intro.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".IntroFragment"> <!-- TODO: Update blank fragment layout --> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textSize="50sp" android:text="@string/intro" /> </FrameLayout>
Now second fragment’s name is Location.
LocationFragment.java
import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class LocationFragment extends Fragment { public LocationFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_location, container, false); } }
fragment_location.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".LocationFragment"> <!-- TODO: Update blank fragment layout --> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textSize="50sp" android:text="Location" /> </FrameLayout>
Third fragment is Login Fragment
LoginFragment.java
import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class LoginFragment extends Fragment { public LoginFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_login, container, false); } }
fragment_login.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".LoginFragment"> <!-- TODO: Update blank fragment layout --> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textSize="50sp" android:text="@string/login" /> </FrameLayout>
Product Fragment is the last one.
ProductFragment.java
import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class ProductFragment extends Fragment { public ProductFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_product, container, false); } }
fragment_product.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ProductFragment"> <!-- TODO: Update blank fragment layout --> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textSize="50sp" android:text="@string/Product" /> </FrameLayout>
Step 6. Main Activity
In the last step, you need to add required code in Main Activity’s both files.
In the activity_main.xml, add following code
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal" android:background="@mipmap/tab_bar_bg" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:layout_marginRight="5dp" android:layout_marginLeft="5dp"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:id="@+id/llIntro" > <ImageView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_marginTop="5dp" android:paddingTop="5dp" android:id="@+id/ivIntro" android:src="@mipmap/icon_intro_normal" android:foregroundGravity="center" /> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:text="@string/intro" android:id="@+id/tvIntro" android:layout_weight="1" android:textSize="12sp" android:gravity="center" /> </LinearLayout> <View android:layout_width="0.5dp" android:layout_height="match_parent" android:background="@color/view" /> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:id="@+id/llProduct" > <ImageView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_marginTop="5dp" android:paddingTop="5dp" android:foregroundGravity="center" android:id="@+id/ivProduct" android:src="@mipmap/icon_product" /> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:text="@string/Product" android:id="@+id/tvProduct" android:layout_weight="1" android:gravity="center" android:textSize="12sp" /> </LinearLayout> <View android:layout_width="0.5dp" android:layout_height="match_parent" android:background="@color/view" /> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:id="@+id/llLocation" > <ImageView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_marginTop="5dp" android:paddingTop="5dp" android:id="@+id/ivLocation" android:src="@mipmap/icon_location" /> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:text="@string/Location" android:id="@+id/tvLocation" android:layout_weight="1" android:gravity="center" android:textSize="12sp" /> </LinearLayout> <View android:layout_width="0.5dp" android:layout_height="match_parent" android:background="@color/view" /> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:id="@+id/llLogin" > <ImageView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_marginTop="5dp" android:paddingTop="5dp" android:id="@+id/ivLogin" android:src="@mipmap/icon_login2" /> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:text="@string/login" android:id="@+id/tvLogin" android:layout_weight="1" android:gravity="center" android:textSize="12sp" /> </LinearLayout> </LinearLayout> <FrameLayout android:id="@+id/container_body" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout> </LinearLayout>
I have designed four Linear Layouts, which represents the four tabs.
Each Linear layout includes one imageview and one textview.
ImageView represnts the tab icon and Textview represents the tab text.
You can add other UI elements as per your requirement.
After four linear layouts, there is a frame layout in which fragment for each tab will be loaded.
Update Main Activity java file
Finally, time to update MainActivity.java file
import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private int currentSelected = 0; private String intro="intro", product = "product", location = "location", login = "login"; private ImageView ivIntro, ivProduct, ivLocation, ivLogin; private TextView tvIntro, tvProduct, tvLocation, tvLogin; private LinearLayout llIntro, llProduct, llLocation, llLogin; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); llIntro = (LinearLayout) findViewById(R.id.llIntro); llProduct = (LinearLayout) findViewById(R.id.llProduct); llLocation = (LinearLayout) findViewById(R.id.llLocation); llLogin = (LinearLayout) findViewById(R.id.llLogin); ivIntro = (ImageView) findViewById(R.id.ivIntro); ivProduct = (ImageView) findViewById(R.id.ivProduct); ivLocation = (ImageView) findViewById(R.id.ivLocation); ivLogin = (ImageView) findViewById(R.id.ivLogin); tvIntro = (TextView) findViewById(R.id.tvIntro); tvProduct = (TextView) findViewById(R.id.tvProduct); tvLocation = (TextView) findViewById(R.id.tvLocation); tvLogin = (TextView) findViewById(R.id.tvLogin); llIntro.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(currentSelected == 1){ }else { getSupportActionBar().setTitle("Introduction"); ivIntro.setImageResource(R.mipmap.icon_intro_selected); tvIntro.setTextColor(getResources().getColor(R.color.white)); llIntro.setBackgroundDrawable(getResources().getDrawable(R.drawable.roundleft)); unselectElse(1); removeAllFragment(new IntroFragment(), false,intro); } } }); llProduct.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(currentSelected == 2){ }else { getSupportActionBar().setTitle("Product"); ivProduct.setImageResource(R.mipmap.icon_product_selected); tvProduct.setTextColor(getResources().getColor(R.color.white)); llProduct.setBackgroundColor(getResources().getColor(R.color.colorPrimary)); unselectElse(2); removeAllFragment(new ProductFragment(), false, product); } } }); llLocation.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(currentSelected == 3){ }else { getSupportActionBar().setTitle("Location"); ivLocation.setImageResource(R.mipmap.icon_location_selected); tvLocation.setTextColor(getResources().getColor(R.color.white)); llLocation.setBackgroundColor(getResources().getColor(R.color.colorPrimary)); unselectElse(3); removeAllFragment(new LocationFragment(), false, location); } } }); llLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(currentSelected == 4){ }else { getSupportActionBar().setTitle("Login"); ivLogin.setImageResource(R.mipmap.icon_login_selected); tvLogin.setTextColor(getResources().getColor(R.color.white)); llLogin.setBackgroundDrawable(getResources().getDrawable(R.drawable.roundback)); unselectElse(4); removeAllFragment(new LoginFragment(), false, login); } } }); } private void unselectElse(int current){ switch (currentSelected){ case 1: ivIntro.setImageResource(R.mipmap.icon_intro_normal); tvIntro.setTextColor(getResources().getColor(R.color.colorPrimary)); llIntro.setBackgroundColor(getResources().getColor(R.color.tranparent)); currentSelected = current; break; case 2: ivProduct.setImageResource(R.mipmap.icon_product); tvProduct.setTextColor(getResources().getColor(R.color.colorPrimary)); llProduct.setBackgroundColor(getResources().getColor(R.color.tranparent)); currentSelected = current; break; case 3: ivLocation.setImageResource(R.mipmap.icon_location); tvLocation.setTextColor(getResources().getColor(R.color.colorPrimary)); llLocation.setBackgroundColor(getResources().getColor(R.color.tranparent)); currentSelected = current; break; case 4: ivLogin.setImageResource(R.mipmap.icon_login2); tvLogin.setTextColor(getResources().getColor(R.color.colorPrimary)); llLogin.setBackgroundColor(getResources().getColor(R.color.tranparent)); currentSelected = current; break; } if(currentSelected == 0){ currentSelected = current; } } public void removeAllFragment(Fragment replaceFragment,boolean addToBackStack, String tag) { FragmentManager manager = getSupportFragmentManager(); FragmentTransaction ft = manager.beginTransaction(); manager.popBackStackImmediate(null,FragmentManager.POP_BACK_STACK_INCLUSIVE); if (addToBackStack) { ft.addToBackStack(tag); } ft.replace(R.id.container_body, replaceFragment); ft.commitAllowingStateLoss(); } }
Step 7. Explanation of Main Activity
In the main activity, I have defined four linear layouts which are representing four tabs as per below.
llIntro = (LinearLayout) findViewById(R.id.llIntro); llProduct = (LinearLayout) findViewById(R.id.llProduct); llLocation = (LinearLayout) findViewById(R.id.llLocation); llLogin = (LinearLayout) findViewById(R.id.llLogin);
Now, I have set onclick listeners for each above linear layout.
It will work when the user clicks on any tab.
llIntro.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(currentSelected == 1){ }else { getSupportActionBar().setTitle("Introduction"); ivIntro.setImageResource(R.mipmap.icon_intro_selected); tvIntro.setTextColor(getResources().getColor(R.color.white)); llIntro.setBackgroundDrawable(getResources().getDrawable(R.drawable.roundleft)); unselectElse(1); removeAllFragment(new IntroFragment(), false,intro); } } }); llProduct.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(currentSelected == 2){ }else { getSupportActionBar().setTitle("Product"); ivProduct.setImageResource(R.mipmap.icon_product_selected); tvProduct.setTextColor(getResources().getColor(R.color.white)); llProduct.setBackgroundColor(getResources().getColor(R.color.colorPrimary)); unselectElse(2); removeAllFragment(new ProductFragment(), false, product); } } }); llLocation.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(currentSelected == 3){ }else { getSupportActionBar().setTitle("Location"); ivLocation.setImageResource(R.mipmap.icon_location_selected); tvLocation.setTextColor(getResources().getColor(R.color.white)); llLocation.setBackgroundColor(getResources().getColor(R.color.colorPrimary)); unselectElse(3); removeAllFragment(new LocationFragment(), false, location); } } }); llLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(currentSelected == 4){ }else { getSupportActionBar().setTitle("Login"); ivLogin.setImageResource(R.mipmap.icon_login_selected); tvLogin.setTextColor(getResources().getColor(R.color.white)); llLogin.setBackgroundDrawable(getResources().getDrawable(R.drawable.roundback)); unselectElse(4); removeAllFragment(new LoginFragment(), false, login); } } });
Now you might have noticed that two methods are present in each click listener.
- unselectElse()
- removeAllFragment()
Both these methods are described below.
unselectElse
This method will deselect the current selected tab.
For example, user first clicks on Login fragment, so the icon color and text color for login tab is changes to white.
Now user selects or clicks on the product fragment, so the icon and text color for product is changed to white but here, login tab is also white.
If we do not change icon and text color of login tab back to black, there will be two selected tabs which is not ideal condition.
so unselectElse method will make the look and feel of selected tab back to the deselected.
Code for this method
private void unselectElse(int current){ switch (currentSelected){ case 1: ivIntro.setImageResource(R.mipmap.icon_intro_normal); tvIntro.setTextColor(getResources().getColor(R.color.colorPrimary)); llIntro.setBackgroundColor(getResources().getColor(R.color.tranparent)); currentSelected = current; break; case 2: ivProduct.setImageResource(R.mipmap.icon_product); tvProduct.setTextColor(getResources().getColor(R.color.colorPrimary)); llProduct.setBackgroundColor(getResources().getColor(R.color.tranparent)); currentSelected = current; break; case 3: ivLocation.setImageResource(R.mipmap.icon_location); tvLocation.setTextColor(getResources().getColor(R.color.colorPrimary)); llLocation.setBackgroundColor(getResources().getColor(R.color.tranparent)); currentSelected = current; break; case 4: ivLogin.setImageResource(R.mipmap.icon_login2); tvLogin.setTextColor(getResources().getColor(R.color.colorPrimary)); llLogin.setBackgroundColor(getResources().getColor(R.color.tranparent)); currentSelected = current; break; } if(currentSelected == 0){ currentSelected = current; } }
removeAllFragment()
This method will simply empty the fragment backstack.
Whenever new fragment is loaded in the frame layout, it is added into the backstack also.
This method will be helpful to overcome this issue.
The second parameter of this method will decide whether to add newly loaded fragment into the backstack or not.
Checkout it’s implementation
public void removeAllFragment(Fragment replaceFragment,boolean addToBackStack, String tag) { FragmentManager manager = getSupportFragmentManager(); FragmentTransaction ft = manager.beginTransaction(); manager.popBackStackImmediate(null,FragmentManager.POP_BACK_STACK_INCLUSIVE); if (addToBackStack) { ft.addToBackStack(tag); } ft.replace(R.id.container_body, replaceFragment); ft.commitAllowingStateLoss(); }
That was all the details about android change tab icon when selected.
Useful thread : https://github.com/astuetz/PagerSlidingTabStrip/pull/62/files
Download Source Code For Android Change Tab Icon
[sociallocker]Download Change Tab Icon Source Code[/sociallocker]