30

I am working on a screen which contains Three tabs I am trying to add an icon with My text in tabs and i want the image to be upper the text and there should be some space between them it is my code.

public class HomeScreen extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {

private Toolbar toolbar;
private ViewPager pager;
private ViewPagerAdapter adapter;
private SlidingTabLayout tabs;
private CharSequence Titles[] = {"News", "Most Views", "Chart"};
int Numboftabs = 3;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home_screen);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    //MAhmoud Code Addtion
    // getSupportActionBar().setDisplayHomeAsUpEnabled(true);
   // getSupportActionBar().setIcon(R.drawable.ic_launcher);

    // Creating The ViewPagerAdapter and Passing Fragment Manager, Titles
    // fot the Tabs and Number Of Tabs.
    adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles,
            Numboftabs);

    // Assigning ViewPager View and setting the adapter
    pager = (ViewPager) findViewById(R.id.pager);
    pager.setAdapter(adapter);

    // Assiging the Sliding Tab Layout View
    tabs = (SlidingTabLayout) findViewById(R.id.tabs);
    tabs.setDistributeEvenly(true);
    tabs.setViewPager(pager);

}

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}}

ViewPagerAdapter

public class ViewPagerAdapter extends FragmentStatePagerAdapter {

CharSequence Titles[];
int NumbOfTabs;

public ViewPagerAdapter(FragmentManager fm, CharSequence mTitles[],
        int mNumbOfTabsumb) {
    super(fm);
    this.Titles = mTitles;
    this.NumbOfTabs = mNumbOfTabsumb;
}
// This method return the fragment for the every position in the View Pager
@Override
public Fragment getItem(int position) {
    switch (position) {
    case 0:
        return new Tap1();

    case 1:
        return new Tap2();
    case 2:
        return new Tap3();
    }
    return null;
}
// This method return the titles for the Tabs in the Tab Strip
@Override
public CharSequence getPageTitle(int position) {
    return Titles[position];
}
// This method return the Number of tabs for the tabs Strip
@Override
public int getCount() {
    return NumbOfTabs;
}}
Aditya Vyas-Lakhan
  • 13,409
  • 16
  • 61
  • 96
Mahmoud Ahmed
  • 307
  • 1
  • 3
  • 7

4 Answers4

65

Try this way this is exactly what you looking for

http://www.androidhive.info/2015/09/android-material-design-working-with-tabs/

public class MainActivity extends AppCompatActivity {

    private Toolbar toolbar;
    private TabLayout tabLayout;
    private ViewPager viewPager;
    private int[] tabIcons = {
            R.drawable.ic_tab_favourite,
            R.drawable.ic_tab_call,
            R.drawable.ic_tab_contacts
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
        setupTabIcons();
    }

    private void setupTabIcons() {
        tabLayout.getTabAt(0).setIcon(tabIcons[0]);
        tabLayout.getTabAt(1).setIcon(tabIcons[1]);
        tabLayout.getTabAt(2).setIcon(tabIcons[2]);
    }

    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFrag(new OneFragment(), "ONE");
        adapter.addFrag(new TwoFragment(), "TWO");
        adapter.addFrag(new ThreeFragment(), "THREE");
        viewPager.setAdapter(adapter);
    }

    class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        public ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        public void addFrag(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }
}

enter image description here

Aditya Vyas-Lakhan
  • 13,409
  • 16
  • 61
  • 96
  • 14
    I have done the same thing , but don't know why image is coming above the text but not adjacent to it . What could be the reason? – rajat44 Apr 27 '17 at 11:32
  • 3
    You can set the `icon` attribute for each `TabItem` right in your layout XML. The layout editor will even show you how it's going to look! But of course, then you actually run your app, and...NOTHING! Thanks AGAIN Android SDK. I love having to search SO after every key stroke. – rmirabelle May 21 '19 at 02:12
  • 25
    @rajat44, app:tabInlineLabel="true" for your TabLayout xml view will do the trick – Roman T. May 26 '19 at 09:01
36

first create a layout xml file that has the structure you desire for the tab as an example a simple icon at the top of a text. like so: enter image description here

1. create the navigation tab layout xml: in layout folder > nav_tab.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_tab"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="@dimen/nav_icon"
        android:scaleType="centerInside"
        android:id="@+id/nav_icon"
        android:layout_marginBottom="@dimen/tiny_padding"/>

    <TextView
        android:id="@+id/nav_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@string/font_fontFamily_medium"
        android:shadowColor="@android:color/black"
        android:textColor="@color/dark_grey"
        android:textSize="@dimen/nav_tab_label_font_size"
        tools:text="@string/nav_home" />

</LinearLayout>

give your layout and id to inflate, and give the ImageView and the TextView ids too to reference later after inflating the parent layout.


2. Define your icons in drawable folder, and labels in strings.xml file

and reference them by their resource id in array ordered as you wish your icons to appear:

private int[] navIcons = {
        R.drawable.ico_home,
        R.drawable.ico_search,
        R.drawable.ico_notification,
        R.drawable.ico_profile
};
private int[] navLabels = {
        R.string.nav_home,
        R.string.nav_search,
        R.string.nav_notifications,
        R.string.nav_profile
};
// another resouces array for active state for the icon
private int[] navIconsActive = {
        R.drawable.ico_home_red,
        R.drawable.ico_search_red,
        R.drawable.ico_notification_red,
        R.drawable.ico_profile_red
};

3. setup your TabLayout with your ViewerPager:

TabLayout navigation = (TabLayout) findViewById(R.id.navigation);
navigation.setupWithViewPager(mainView/* the viewer pager object*/);

now customization part:

// loop through all navigation tabs
for (int i = 0; i < navigation.getTabCount(); i++) {
    // inflate the Parent LinearLayout Container for the tab
    // from the layout nav_tab.xml file that we created 'R.layout.nav_tab
    LinearLayout tab = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.nav_tab, null);

    // get child TextView and ImageView from this layout for the icon and label
    TextView tab_label = (TextView) tab.findViewById(R.id.nav_label);
    ImageView tab_icon = (ImageView) tab.findViewById(R.id.nav_icon);

    // set the label text by getting the actual string value by its id
    // by getting the actual resource value `getResources().getString(string_id)`
    tab_label.setText(getResources().getString(navLabels[i]));

    // set the home to be active at first
    if(i == 0) {
        tab_label.setTextColor(getResources().getColor(R.color.efent_color));
        tab_icon.setImageResource(navIconsActive[i]);
    } else {
        tab_icon.setImageResource(navIcons[i]);
    }

    // finally publish this custom view to navigation tab
    navigation.getTabAt(i).setCustomView(tab);
}

---

Final touch to set an active state and get the icon and text color changed when the tab is selected:

you can continue to my answer here

change image and color of the text to the tab when selected

that will achieve: enter image description here

Biskrem Muhammad
  • 4,074
  • 3
  • 31
  • 38
  • If anyone is facing height issues with tab layout, we can set it dynamically by getting the height of the inflated layout `LinearLayout tab` with a `ViewTreeObserver` Refer this [link](https://stackoverflow.com/a/24035591/7710739) and set the height of the Tab layout dynamically by using [this](https://stackoverflow.com/a/5257851/7710739) – Reejesh PK Jan 10 '19 at 13:35
  • Refer this if you face issues with `tab.getCustomView()` giving null pointer exception, try [this](https://stackoverflow.com/a/40897198/7710739) – Reejesh PK Jan 10 '19 at 15:27
  • Thanks for `navigation.getTabAt(i).setCustomView(tab);`. I created new tabs with `newTab()` instead of replacing existing, that was my mistake. – CoolMind Jan 19 '19 at 11:31
  • @ReejeshPK, can you provide a solution for TabLayout height? I tried many times but didn't succeed. – CoolMind Jan 19 '19 at 13:14
  • @CoolMind is Your Tab layout height too short? – Reejesh PK Jan 19 '19 at 13:42
  • @CoolMind First I added a `addOnTabSelectedListener` to my tab layout, and inside the callback `onTabSelected` , I got the view instance using `View tabView = tab.getCustomView();` and then I Wrote a function to setup height dynamically by calling `setupDymanicHeight(tabView);` and here is the custom function below.. – Reejesh PK Jan 19 '19 at 13:46
  • @CoolMind `private void setupDymanicHeight(final View tab) { tab.getViewTreeObserver().addOnGlobalLayoutListener(->{ @Override public void onGlobalLayout() { tab.getViewTreeObserver().removeOnGlobalLayoutListener(this); if (dynamicHeight == 0) { Log.i(TAG, "Height changed to:" + tab.getHeight()); tabLayout.getLayoutParams().height = tab.getHeight(); } } }); }` – Reejesh PK Jan 19 '19 at 13:48
  • @ReejeshPK, thanks! Yes, it's too small. You should better add your code as an answer here. I tried to test, but TabLayout hasn't changed. Do you assume that height will change on tab swiping? Probably you should calculate TabLayout height for all tabs inside it. – CoolMind Jan 19 '19 at 14:43
5

If you want to put icons and text in a single line in a tablayout you have to make a custom layout as below.

custom_tab_heading.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"
    android:gravity="center">
    <TextView
        android:id="@+id/tabContent"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:textAlignment="center"
        android:textColor="@android:color/black"
        android:gravity="center"/>
</LinearLayout>

At your java side you can write below code to put image and title to your tabs.

val tabTitles = arrayListOf<String>("  Text Jokes","  Funny Images")
val tabIcons = arrayListOf<Int>(R.drawable.text_jokes,R.drawable.image_jokes)


val tabLinearLayout = LayoutInflater.from(context).inflate(R.layout.custom_tab_heading, null) as LinearLayout
val tabContent = tabLinearLayout.findViewById<View>(R.id.tabContent) as TextView
tabContent.text = tabTitles.get(0)
tabContent.setCompoundDrawablesWithIntrinsicBounds(tabIcons[0], 0, 0, 0)
myTabLayout.getTabAt(0)!!.setCustomView(tabContent)

val tabLinearLayout1 = LayoutInflater.from(context).inflate(R.layout.custom_tab_heading, null) as LinearLayout
val tabContent1 = tabLinearLayout1.findViewById<View>(R.id.tabContent) as TextView
tabContent1.text = tabTitles.get(1)
tabContent1.setCompoundDrawablesWithIntrinsicBounds(tabIcons[1], 0, 0, 0)
var l = tabLinearLayout1.layoutParams
myTabLayout.getTabAt(1)!!.setCustomView(tabContent1)

Note:- In tabTitles array notice that i have given a space before text(<space>Title 1) because it will keep space between your image and title.

Sorry for i am providing kotlin code here but you can easily convert it to java. If anyone having a problem then comment in this answer and i will try to help them.

Jaydip Kalkani
  • 2,493
  • 6
  • 24
  • 56
2

All the answers that my good felows have mentioned are valid of course, but since ViewPager2 is out there it is good to post solution accordingly.

private ViewPager2 viewPager2;
private TabLayout tablayout;



private void tabLayoutValueSetter(){
    viewPager2 = findViewById(R.id.viewPager2);
    tablayout = findViewById(R.id.TabLayout);


    final String[] tabTitles = {"Tab One", "Tab Two", "Tab Three"};//put titles based on your need
    final int[] tabIcons = {R.drawable.icon_1, R.drawable.icon_2, R.drawable.icon_13};

    
     TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager2,
            ((tab, position) -> {
                tab.setText(tabTitles[position]);
                tab.setIcon(tabIcons[position]);
            }
            ));
      tabLayoutMediator.attach();
      //and whereever you want you can detach it (tabLayoutMediator.detach())

 }

Result is a Tablayout with three icons and titles beneath it.

StackOverflower
  • 369
  • 2
  • 12