Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom icon on Tabs

I am using PagerSlidingTabStrip with a ViewPager.

Is there a way I can change the Tab icons dynamically, depending on some actions. Like when a notification is received, I want to change the icon on notifications tab to show how many notifications are unread.

Or any other library which would support that without much tweaking.

like image 373
Housefly Avatar asked Dec 02 '22 14:12

Housefly


1 Answers

You can do it by implementing PagerSlidingTabStrip.CustomTabProvider interface. I made example project for your case, so let's explore it step by step.

Firstly, create a layout for our tab called tab_layout, for example. It will contain 2 TextView's for title and badge. In my case it looks like:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:id="@+id/tab_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:textColor="@android:color/white"
    android:textStyle="bold"
    android:textSize="16sp"
    android:singleLine="true" />

<TextView
    android:id="@+id/badge"
    android:layout_width="16dp"
    android:layout_height="16dp"
    android:layout_toRightOf="@+id/tab_title"
    android:textSize="12sp"
    android:gravity="center"
    android:layout_marginLeft="8dp"
    android:layout_centerVertical="true"
    android:textColor="@android:color/white"
    android:background="@drawable/badge_background" />

</RelativeLayout>

Secondly, create a simple model for Tab, that will containt a tab title and number of notifications. I've called it ViewPagerTab:

public class ViewPagerTab {
    public String title;
    public int notifications;

    public ViewPagerTab(String title, int notifications) {
        this.title = title;
        this.notifications = notifications;
    }
}

Thirdly, implement PagerSlidingTabStrip.CustomTabProvider interface on your FragmentPagerAdapter. Here we will inflate tab layout and initialize the tab views, also we will define fragments for positions:

public class MainAdapter extends FragmentPagerAdapter
        implements PagerSlidingTabStrip.CustomTabProvider {

    ArrayList<ViewPagerTab> tabs;

    public MainAdapter(FragmentManager fm, ArrayList<ViewPagerTab> tabs) {
        super(fm);
        this.tabs = tabs;
    }

    @Override
    public View getCustomTabView(ViewGroup viewGroup, int i) {
        RelativeLayout tabLayout = (RelativeLayout)
                LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.tab_layout, null);

        TextView tabTitle = (TextView) tabLayout.findViewById(R.id.tab_title);
        TextView badge = (TextView) tabLayout.findViewById(R.id.badge);

        ViewPagerTab tab = tabs.get(i);

        tabTitle.setText(tab.title.toUpperCase());
        if (tab.notifications > 0) {
            badge.setVisibility(View.VISIBLE);
            badge.setText(String.valueOf(tab.notifications));
        } else {
            badge.setVisibility(View.GONE);
        }

        return tabLayout;
    }

    @Override
    public void tabSelected(View view) {
        //if you don't want badges disappear when you select tab comment next lines
        RelativeLayout tabLayout = (RelativeLayout) view;
        TextView badge = (TextView) tabLayout.findViewById(R.id.badge);
        badge.setVisibility(View.GONE);
    }

    @Override
    public void tabUnselected(View view) {

    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return new OneFragment();
            case 1:
                return new TwoFragment();
            case 2:
                return new ThreeFragment();
        }
        return new OneFragment();
    }

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

Fourthly, initialize tabs and pager in MainActivity's onCreate method:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
    pager = (ViewPager) findViewById(R.id.pager);

    ArrayList<ViewPagerTab> tabsList = new ArrayList<>();
    tabsList.add(new ViewPagerTab("One", 0));
    tabsList.add(new ViewPagerTab("Two", 1));
    tabsList.add(new ViewPagerTab("Three", 2));

    adapter = new MainAdapter(getSupportFragmentManager(), tabsList);

    pager.setAdapter(adapter);
    tabs.setViewPager(pager);

    pager.setOffscreenPageLimit(3);
    getSupportActionBar().hide();
}

You will get something like this: enter image description here

And finally, to get and change tab views in runtime, you can simply call getChildAt function of PagerSlidingTabStrip object in your Activity or Fragment, and do what you want:

private void notifyTabStripChanged(int position, int notificationsCount) {
    LinearLayout tabHost = (LinearLayout) tabs.getChildAt(0);
    RelativeLayout tabLayout = (RelativeLayout) tabHost.getChildAt(position);
    TextView badge = (TextView) tabLayout.findViewById(R.id.badge);
    if (notificationsCount > 0) {
        badge.setVisibility(View.VISIBLE);
        badge.setText(String.valueOf(notificationsCount));
    } else {
        badge.setVisibility(View.GONE);
    }
}

Don't forget, that child views count is starting from 0. If you want to use images, just replace ImageView with TextView badge and change it's image resource instead of text. Enjoy!

like image 182
romtsn Avatar answered Dec 18 '22 00:12

romtsn