Android: How to add custom tab to TabbedActivity?

I have this activity:

I created it with New Activity->Tabbed Activity in Android Studio 1.5

They provided me with the following code which is generated when you create this kind of activity:

public class Main2Activity extends AppCompatActivity {

/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a
 * {@link FragmentPagerAdapter} derivative, which will keep every
 * loaded fragment in memory. If this becomes too memory intensive, it
 * may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
private SectionsPagerAdapter mSectionsPagerAdapter;

/**
 * The {@link ViewPager} that will host the section contents.
 */
private ViewPager mViewPager;

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

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(mViewPager);

    //--------------------------------------------------------------------
    //Here is the custom code

    View view = getLayoutInflater().inflate(R.layout.custom_tab,null);
    view.findViewById(R.id.custom_tab_imageView).setBackgroundResource(R.mipmap.ic_launcher);
    TabLayout.Tab tab = tabLayout.newTab().setCustomView(view);
    tabLayout.addTab(tab);
    //----------------------------------------------------------------------

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main2, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    public PlaceholderFragment() {
    }

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main2, container, false);
        TextView textView = (TextView) rootView.findViewById(R.id.section_label);
        textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
        return rootView;
    }
}

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

    public SectionsPagerAdapter(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).
        return PlaceholderFragment.newInstance(position + 1);
    }

    @Override
    public int getCount() {
        // Show 3 total pages.
        return 3;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return "SECTION 1";
            case 1:
                return "SECTION 2";
            case 2:
                return "SECTION 3";
        }
        return null;
    }
}

I wanted to add a new custom tab besides the three existing so I created custom_tab.xml that contains an ImageView with id=custom_tab_imageView and added the following to onCreate():

View view = getLayoutInflater().inflate(R.layout.custom_tab,null);
  view.findViewById(R.id.custom_tab_imageView).setBackgroundResource(R.mipmap.ic_launcher);
TabLayout.Tab tab = tabLayout.newTab().setCustomView(view);
tabLayout.addTab(tab);

In SECTION 1,2,3 there is a PlaceholderFragment shown that say "Hello World from section..."

How do I need to modify the SectionsPagerAdapter in order to show "Hello world from section 4" when user tap the custom tab? Or how do I make the adapter recognize it as the fourth tab?

Answers


All the magic happens in FragmentPagerAdapter.

In short,

Override getCount() method to define number of tabs.

Define titles of each tab in getPageTitle() method

and of course, getItem() to return Fragment for ViewPager - and link it's position with TabLayout.

In your case, to add a new tab...

  1. Create a Fragment

  2. Add the following case in switch block of getPageTitle() method to add Tab at the last position:

    case 3:
        return 'SECTION 4';
    
  3. return the Fragment from getItem() method when position is 3:

    if (position == 3) {
        return <new instance of your Fragment>;
    }
    

Update:

Well, how about this?

view.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mViewPager.setCurrentItem(3);
    }
});

If this is what you want, then you need to modify your code. Almost all of it.


This will allow you to set a custom tab view along with Image and text

Create an xml layout named custom_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tab"
    android:textColor="@color/colorAccent"
    android:textSize="@dimen/tab_label"
    android:fontFamily="@string/font_fontFamily_medium"/>

Render custom_tab.xml layout in each tab using below lines of code.

TextView tabOne = (TextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
tabOne.setText("ONE");
tabOne.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_tab_favourite, 0, 0);
tabLayout.getTabAt(0).setCustomView(tabOne);

Complete class code:

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() {

        TextView tabOne = (TextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
        tabOne.setText("ONE");
        tabOne.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_tab_favourite, 0, 0);
        tabLayout.getTabAt(0).setCustomView(tabOne);

        TextView tabTwo = (TextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
        tabTwo.setText("TWO");
        tabTwo.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_tab_call, 0, 0);
        tabLayout.getTabAt(1).setCustomView(tabTwo);

        TextView tabThree = (TextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
        tabThree.setText("THREE");
        tabThree.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_tab_contacts, 0, 0);
        tabLayout.getTabAt(2).setCustomView(tabThree);
    }

    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);
        }
    }
}

I found the solution:

public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(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 PlaceholderFragment.newInstance("Gallery");
            case 1:
                return PlaceholderFragment.newInstance("Chat");
            case 2:
                return PlaceholderFragment.newInstance("People");
            default:
                return null;
        }
    }

    @Override
    public int getCount() {
        // Show 3 total pages.
        return 3;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        /*switch (position) {
            case 0:
                return "Gallery";
            case 1:
                return "Chat";
            case 2:
                return "People";
        }*/

        // Return null to display only icons
        return null;
    }
}

Create a custom tab and call setCustomView() method:

private void setupTabIcons() {

    View view0 = getLayoutInflater().inflate(R.layout.custom_tab, null);
    view0.findViewById(R.id.custom_imageView).setBackgroundResource(tabIcons[0]);

    View view1 = getLayoutInflater().inflate(R.layout.custom_tab, null);
    view1.findViewById(R.id.custom_imageView).setBackgroundResource(tabIcons[1]);

    View view2 = getLayoutInflater().inflate(R.layout.custom_tab, null);
    view2.findViewById(R.id.custom_imageView).setBackgroundResource(tabIcons[2]);

    tabLayout.getTabAt(0).setCustomView(view0);
    tabLayout.getTabAt(1).setCustomView(view1);
    tabLayout.getTabAt(2).setCustomView(view2);

}

In onCreate() call setupTabIcons() and that's it. You have 3 custom tabs connected to 3 fragments for your TabbedActivity.


Need Your Help

Parsing code files faster

c++ string parsing c++11

I wrote a fairly complex parser for a stack-based language which loads a file into memory and then proceeds by comparing tokens to see if it is recognized as operand or instruction.

Could not extract Cloudera Hadoop VM archive

windows hadoop cloudera 7zip

I am new to Cloudera. I have worked on hadoop previously, now I want to try Cloudera Hadoop. For this I started with Cloudera Hadoop VM.