Search code examples
androidandroid-layoutandroid-tabhostandroid-tabs

create custom android tabs


I want create my own tabs and I want to have my own layout

Let's say I want this result exactly

enter image description here

But the original tab looks like

enter image description here

Is there a way to create my own tab layout?


Solution

  • Watch this video from the Android Dev team showing how to use Sliding Tabs

    I got a handy class if you want to dynamically edit the layout of the pages:

    Create a file called SmartFragmentStatePagerAdapter.java and enter this code:

    package com.package.name;
    
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentStatePagerAdapter;
    import android.util.SparseArray;
    import android.view.ViewGroup;
    
    /* 
    Extension of FragmentStatePagerAdapter which intelligently caches 
    all active fragments and manages the fragment lifecycles. 
    Usage involves extending from SmartFragmentStatePagerAdapter as you would any other PagerAdapter.
    */
    public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
        // Sparse array to keep track of registered fragments in memory
        private SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
    
    public SmartFragmentStatePagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }
    
    // Register the fragment when the item is instantiated
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }
    
    // Unregister when the item is inactive
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }
    
    // Returns the fragment for the position (if instantiated)
    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }
    }
    

    In your PageAdapter class do this:

    public class PageAdapter extends SmartFragmentStatePagerAdapter {
    
        final String TAG = "PageAdapter";
    
        ArrayList<Fragment> cards = new ArrayList<Fragment>();
    
        private final String[] TITLES = { getResources().getString(R.string.home) , getResources().getString(R.string.second_home) , getResources().getString(R.string.third_home) , getResources().getString(R.string.fourth_home) };  
    
        FragmentManager fm = null;
    
        public PageAdapter(FragmentManager fm) {
            super(fm);
            this.fm = fm;       
            Log.d(TAG, "Tiles are being created");
        }
    
        @Override
        public int getCount() {
            return TITLES.length;
        }
    
        @Override
        public CharSequence getPageTitle(int position){
            return TITLES[position];        
        }
    
        @Override
        public Fragment getItem(int position) {
            Fragment card = CardFragment.newInstance(position);
            Log.d(TAG, "getItem has been called");
            cards.add(card);
            return card;
        }
        }
    

    My CardFragment.class:

    package com.package.name;
    
    import java.util.List;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.util.Log;
    import android.util.TypedValue;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.FrameLayout;
    import android.widget.FrameLayout.LayoutParams;
    
    public class CardFragment extends Fragment{
    
    final String TAG = "CardFragment";
    
    ViewGroup cards = null;
    FrameLayout fl = null;
    
    static Context context;
    
    static FragmentManager fragmentManager = null;
    
    private static final String ARG_POSITION = "position";
    
    private int position;
    
    public static CardFragment newInstance(int position) {
        CardFragment f = new CardFragment();
        Bundle b = new Bundle();
        b.putInt(ARG_POSITION, position);
        f.setArguments(b);
        return f;
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        fragmentManager = this.getFragmentManager();
        position = getArguments().getInt(ARG_POSITION);
    }
    
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        cards = container;
        View v = null;
        if(fragmentManager == null){
            fragmentManager = this.getFragmentManager();
        }
    
        switch (position){ 
            case 0: 
                v = inflater.inflate(R.layout.tab_home,null);
                Log.d(TAG, "Layout for position " + position + " inflated");
                break;
            case 1:
                v = inflater.inflate(R.layout.tab_second_home,null);
                Log.d(TAG, "Layout for position " + position + " inflated");
                break;
            case 2:
                v = inflater.inflate(R.layout.tab_third_home,null);
                Log.d(TAG, "Layout for position " + position + " inflated");
                break;
            case 3:
                v = inflater.inflate(R.layout.tab_fourth_home,null);
                Log.d(TAG, "Layout for position " + position + " inflated");
                break;
        }
    
    
    
        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    
        fl = new FrameLayout(getActivity());
        fl.setLayoutParams(params);
    
        final int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources()
                .getDisplayMetrics());
    
    
        params.setMargins(margin, margin, margin, margin);
    
    
        fl.addView(v);
        return fl;
    }
    

    }

    And finally do this in your onCreate():

    tabs = (HorizontalScrollView)v.findViewById(R.id.tabs);
            pager = (ViewPager)v.findViewById(R.id.pager);
            adapter = new PageAdapter(getSupportFragmentManager()); 
            // Initialize the ViewPager and set an adapter
    
            pager.setAdapter(adapter);
    
            final int pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources()
                    .getDisplayMetrics()); // The space between pages.
    
            pager.setPageMargin(pageMargin);
    
            // Bind the tabs to the ViewPager
            tabs.setViewPager(pager);
    

    In total there will be 4 pages created because your TITLES contains 4 strings. Edit the CardFragment class to use different layouts, for convenience I've called them tab_home, tab_second_home, tab_third_home and tab_fourth_home If you want the root layout of the card use this:

    Fragment card = adapter.getRegisteredFragment(pager.getCurrentItem());
    
     if(card != null){
                         textView = (TextView)card.getView().findViewById(R.id.textView); // This will use the textView you are seeing on the screen of the selected page right now. Change this to any view you would like to edit
    
                       }else{
                           System.out.println("card is null nothing has been added to the layout!");
                       }