0

I am implementing an viewpager with icons,i have implemented as below:

public class JobDetailTabbedActivity extends AppCompatActivity {

    private int tabPositionToDisplay=0;
    private String productId="";
    private JobDetailPagerAdapter mJobDetailPagerAdapter;
    private ViewPager mViewPager;
    private TabLayout tabLayout;

    private int[] tabIcons = {
            R.drawable.ic_emoji_objects_light_normal,
            R.drawable.ic_emoji_objects_light,
            R.drawable.ic_cast_disabled_light,
            R.drawable.ic_cast_disabled_light
    };

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

        mJobDetailPagerAdapter = new JobDetailPagerAdapter(getSupportFragmentManager());


        mViewPager = (ViewPager) findViewById(R.id.tab_anim_viewpager);
        mViewPager.setAdapter(mJobDetailPagerAdapter);
        mViewPager.setCurrentItem(tabPositionToDisplay);
        tabLayout = (TabLayout) findViewById(R.id.tab_anim_tabs);
        tabLayout.setupWithViewPager(mViewPager);


    }

    public class JobDetailPagerAdapter extends FragmentPagerAdapter {


        public JobDetailPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment (defined as a static inner class below).
            switch (position){
                case 0:
                    return JobDetailInfoFragment.newInstance();
                case 1:
                    return JobDetailServiceFragment.newInstance();
                case 2:
                    return JobDetailChatFragment.newInstance();
                case 3:
                    return JobDetailNotesFragment.newInstance();
                default:
                    return JobDetailInfoFragment.newInstance();
            }
        }

        @Override
        public int getCount() {
            return 4;
        }


        @Override
        public CharSequence getPageTitle(int position) {
            Drawable image = ContextCompat.getDrawable(JobDetailTabbedActivity.this, tabIcons[position]);
            image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());

            SpannableString sb = new SpannableString(" ");
            ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
            sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            return sb;
        }
    }

}

I'm able to get icons at tabs, but how do i set tint color to the selected icon of tab?

I have searched in google, but none if the tutorials available(whatever i have seen) are telling about setting tint for icon anyone please help me.

Anoop M Maddasseri
  • 10,213
  • 3
  • 52
  • 73
Manikanta
  • 3,421
  • 4
  • 30
  • 51

3 Answers3

4

Finally i have solved the problem like this:

Create a custom widget:

public class TintableImageView extends ImageView {

    private ColorStateList tint;

    public TintableImageView(Context context) {
        super(context);
    }

    public TintableImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public TintableImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        TypedArray a =
                context.obtainStyledAttributes(attrs, R.styleable.TintableImageView, defStyle, 0);
        tint = a.getColorStateList(R.styleable.TintableImageView_tintSelector);
        a.recycle();
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if (tint != null && tint.isStateful()) updateTintColor();
    }

    public void setColorFilter(ColorStateList tint) {
        this.tint = tint;
        super.setColorFilter(tint.getColorForState(getDrawableState(), 0));
    }

    private void updateTintColor() {
        int color = tint.getColorForState(getDrawableState(), 0);
        setColorFilter(color);
    }
}

add this value to attrs.xml:

<declare-styleable name="TintableImageView">
    <attr name="tintSelector" format="reference|color" />
</declare-styleable>

create a selector for the tab image you want to change in color directory(repeating again selector file inside color directory not colors.xml):

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:color="#FFFFFF"
        android:state_pressed="true" />
    <item android:color="#FFFFFF"
        android:state_selected="true" />

    <item android:color="#5F9EA0" />
</selector>

create an xml layout with only the custom widget in it:

<?xml version="1.0" encoding="utf-8"?>
<TintableImageView xmlns:custom="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    custom:tintSelector="@color/selector_tab" />

Thats it you are good to go, you have to implement tabs like this(showing only the changed done to my posted code):

public class JobDetailTabbedActivity extends AppCompatActivity {



        private JobDetailPagerAdapter mJobDetailPagerAdapter;
        private ViewPager mViewPager;
        private TabLayout tabLayout;


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            //old code which i have posted
            mJobDetailPagerAdapter = new JobDetailPagerAdapter(getSupportFragmentManager());


            mViewPager = (ViewPager) findViewById(R.id.tab_anim_viewpager);
            mViewPager.setAdapter(mJobDetailPagerAdapter);
            mViewPager.setCurrentItem(tabPositionToDisplay);
            tabLayout = (TabLayout) findViewById(R.id.tab_anim_tabs);
            tabLayout.setupWithViewPager(mViewPager);
            setUpViewPagerIcons(tabLayout);
        }

        private void setUpViewPagerIcons(TabLayout tabLayout) {
            for(int i=0;i<tabLayout.getTabCount();i++){
                int iconId=-1;
                switch (i){
                    case 0:
                        iconId = R.drawable.ic_cast_on_0_light;
                        break;
                    case 1:
                        iconId = R.drawable.ic_cast_on_0_light;
                        break;
                    case 2:
                        iconId = R.drawable.ic_cast_on_0_light;
                        break;
                    case 3:
                        iconId = R.drawable.ic_cast_on_0_light;
                        break;
                }

                TintableImageView tab1 = (TintableImageView) LayoutInflater.from(this).inflate(R.layout.tint_layout, null);
                tab1.setImageResource(iconId);

                tabLayout.getTabAt(i).setCustomView(tab1);
            }
        }



        /**
         * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
         * one of the sections/tabs/pages.
         */
        public class JobDetailPagerAdapter extends FragmentPagerAdapter {

        // old code


        @Override
        public CharSequence getPageTitle(int position) {
            return "";
        }
    }

}

I hope it will be helpful to someone, i have wasted one day for it.

Manikanta
  • 3,421
  • 4
  • 30
  • 51
0

There are a few ways to achive this.

First Way

Create a selector file and use them in your tabIcon array. Also whenever viewpager change set the state of drawables as selected and others are unselected like

int[] state = new int[] {android.R.attr.state_selected}; drawable.setState(state).

So it will take automagically state_selected drawable.

Second Way

You have icon in tabs. Whenever viewpager changes or tab icon clicked you can call drawable.setColorFilter(Color.YOUR_COLOR, PorterDuff.Mode.MULTIPLY) also dont forget to call drawable.clearColorFilter() for other drawables.

Good luck there

Emre Aktürk
  • 3,306
  • 2
  • 18
  • 30
  • You're basically right but I don't think this will work for him since he uses `SpannableStrings` for the title instead of "real" drawables that are accessible and modifiable at a later stage. – reVerse Nov 24 '15 at 11:03
  • Hmmm your right. He should implement custom view for tablayout. – Emre Aktürk Nov 24 '15 at 11:24
  • @EmreAktürk what does "'Drawable" refers in your answer?, because in my code there is nothing called drawable.Can you be a bit clear about it? – Manikanta Nov 24 '15 at 12:05
  • Sure, if you check getPageTitle method you can see there is a drawable to you put into a text. Then, that text is used to display in TextView in TabLayout. So its a little bit tricky and dirty way to implement iconic layout. – Emre Aktürk Nov 24 '15 at 12:12
  • http://www.androidhive.info/2015/09/android-material-design-working-with-tabs/ You should check this link about how to implement icons in proper way. So you can have drawable objects. – Emre Aktürk Nov 24 '15 at 12:12
0

You can easily modify this tutorial as per your requirement.

Result

You can get the tab using getTabAt(int index) method available in TabLayout class and update the tab icon using setIcon(int drawable_id).Code demo follows.

 tabLayout.getTabAt(tab_index).setIcon(highlighted_icon);

Using ViewPager.OnPageChangeListener or TabLayout.TabLayoutOnPageChangeListener you can get the selected tab.

I haven't tried yet but believe this would be enough.

Or you can try TabView which i created personally with support of SlidingTabLayout.

You can download the files here.

Usage

    Integer[] iconUnselectedResourceArray = {R.drawable.ic_tab_post,
                        R.drawable.ic_tab_like, R.drawable.ic_tab_about
                };

                Integer[] iconSelectedResourceArray = {R.drawable.ic_tabactive_post,
                        R.drawable.ic_tabactive_like, R.drawable.ic_tabactive_about
                };

            final SlidingTabLayoutIcons mSlidingTabLayout = (SlidingTabLayoutIcons) findViewById(R.id.tabs);
            mSlidingTabLayout.setCustomTabView(R.layout.profile_tab_items, R.id.tabtext);
            mSlidingTabLayout.setIconResourceArray(iconUnselectedResourceArray);
            mSlidingTabLayout.setIconSelectedResourceArray(iconSelectedResourceArray);
            mSlidingTabLayout.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width
            mSlidingTabLayout.setColorStateList(getResources().getColorStateList(R.color.profile_view_tab));
            // Setting Custom Color for the Scroll bar indicator of the Tab View
            mSlidingTabLayout.setCustomTabColor(new SlidingTabLayoutIcons.TabColorIcons() {
                @Override
                public int getIndicatorColor(int position) {
                    return getResources().getColor(R.color.base_color);
                }
            });
            mSlidingTabLayout.setViewPager(mViewPager);

XML

  <com.example.SlidingTabLayoutIcons
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/profile_tab_border"
            android:elevation="2dp" />

And take a look at this too.

Community
  • 1
  • 1
Anoop M Maddasseri
  • 10,213
  • 3
  • 52
  • 73
  • using the given solution you can set icon, but how can you set tint for it(setTint() is available from sdk 21), and while setting tint for one icon the other icons colors should become normal. After looking that tutorial and implementing that way i have posted this question. Sorry that i have not specified it in my question. – Manikanta Nov 24 '15 at 11:50
  • So for every tab change, all the icons should be updated!!!, then it won't be an efficient approach i guess... – Manikanta Nov 24 '15 at 12:09
  • Not the entire icons. at a time two icons ie, previous selected and currently selected.i said this is one of the way alternative is use selector like emre said . – Anoop M Maddasseri Nov 24 '15 at 12:14
  • Emree said about drawables but i am not using drawable, you can see in my code that i'm using spannable string. Please help me in case if you have any other idea. – Manikanta Nov 24 '15 at 12:17
  • Using `SpannableString` you can't make perfect tabs try to follow the tutorial which is written from official docs. – Anoop M Maddasseri Nov 24 '15 at 12:20
  • I think you are right @Anoop M, even i'm feeling the same, can you comment the official doc link. – Manikanta Nov 24 '15 at 12:28
  • http://developer.android.com/reference/android/support/design/widget/TabLayout.html – Anoop M Maddasseri Nov 24 '15 at 12:36