Android快速開發-選項卡

介紹

幾行代碼實現Android選項卡界面,支持標準底部Tab自定義視圖選項卡,頭部文字選項卡。

底部自定義視圖選項卡

先來看看實現下圖中的效果我們代碼應該怎麼寫?
底部自定義視圖選項卡

實現上圖效果只需以下代碼:

public class TestBottomTabActivity extends TabActivity {

    @Override
    protected List<TabItemView> getTabViews() {
        List tabviews = new ArrayList();
        tabviews.add(new TabItemView(this,"1",R.color.colorPrimary,R.mipmap.ic_launcher,0));
        tabviews.add(new TabItemView(this,"2",R.color.colorPrimary,R.mipmap.ic_launcher,0));
        tabviews.add(new TabItemView(this,"3",R.color.colorPrimary,R.mipmap.ic_launcher,0));
        tabviews.add(new TabItemView(this,"4",R.color.colorPrimary,R.mipmap.ic_launcher,0));
        return tabviews;
    }

    @Override
    protected List<Fragment> getFragments() {
        List fragments = new ArrayList();
        fragments.add(BlankFragment.newInstance("1",null));
        fragments.add(BlankFragment.newInstance("2",null));
        fragments.add(BlankFragment.newInstance("3",null));
        fragments.add(BlankFragment.newInstance("4",null));
        return fragments;
    }

    @Override
    protected List<String> getTitles() {
        return null;
    }

    @Override
    protected TabType getTabType() {
        return TabType.BottomCustomViewTab;
    }
}

頭部文字選項卡

先來看看實現下圖中的效果我們代碼應該怎麼寫?

頭部文字選項卡

實現上圖效果只需以下代碼:

public class TestTopTabActivity extends TabActivity {

    @Override
    protected List<TabItemView> getTabViews() {
        return null;
    }

    @Override
    protected List<Fragment> getFragments() {
        List fragments = new ArrayList();
        fragments.add(BlankFragment.newInstance("1",null));
        fragments.add(BlankFragment.newInstance("2",null));
        fragments.add(BlankFragment.newInstance("3",null));
        fragments.add(BlankFragment.newInstance("4",null));
        return fragments;
    }

    @Override
    protected List<String> getTitles() {
        List list = new ArrayList();
        list.add("待支付");
        list.add("待發貨");
        list.add("待收貨");
        list.add("待評價");
        return list;
    }

    @Override
    protected TabType getTabType() {
        return TabType.TopTitleTab;
    }
}

實現

準備知識

我們都知道在android.support.design.widget包中爲我們提供了TabLayout用來進行水平方向的tab展示,不清楚的同學可以先百度瞭解一下,用法很簡單,大致如下:

        viewPager = (ViewPager) findViewById(R.id.viewPager);
        tabLayout = (TabLayout) findViewById(R.id.tabLayout);

         //爲viewPager設置一個FragmentPagerAdapter
        pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);
        viewPager.setAdapter(pagerAdapter);
        //進行關聯
        tabLayout.setupWithViewPager(viewPager);
        tabLayout.setTabMode(TabLayout.MODE_FIXED);

實現一個頭部文字選項卡

爲了能夠快速實現一個頭部文字選項卡,我們可以將一些不變的代碼寫在一個父類Activity,讓後提供抽象方法來讓子類去實現會變化的代碼,由此如果我們實現一個頭頭部文字選項卡抽象類如下:

1、首先定義佈局
activity_tab_top.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <android.support.design.widget.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="48dp"></android.support.design.widget.TabLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#d3d3d3"
        android:orientation="vertical">
    </View>
    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"></android.support.v4.view.ViewPager>
</LinearLayout>

2、抽象類實現

public abstract class TabActivity extends AppCompatActivity{

    private ViewPager viewPager;
    private TabLayout tabLayout;
    private SimpleFragmentPagerAdapter pagerAdapter;

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

    private void initView() {
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        tabLayout = (TabLayout) findViewById(R.id.tabLayout);

        pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);
        viewPager.setAdapter(pagerAdapter);
        tabLayout.setupWithViewPager(viewPager);
        tabLayout.setTabMode(TabLayout.MODE_FIXED);
    }

    protected abstract List<Fragment> getFragments();//返回tab對應的fragment
    protected abstract List<String> getTitles();//頭部顯示的title列表


    public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {


        public SimpleFragmentPagerAdapter(FragmentManager fm, Context context) {
            super(fm);
        }

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

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

        @Override
        public CharSequence getPageTitle(int position) {
            if (getTitles()!=null&&!getTitles().isEmpty()){
                return getTitles().get(position);
            }
            return null;
        }

    }
}

以上代碼便實現了一個通用的頭部文字選項卡抽象類,以後要實現類似上面圖2界面只需要這樣:

public class TestTopTabActivity extends TabActivity {

    @Override
    protected List<Fragment> getFragments() {
        List fragments = new ArrayList();
        fragments.add(BlankFragment.newInstance("1",null));
        fragments.add(BlankFragment.newInstance("2",null));
        fragments.add(BlankFragment.newInstance("3",null));
        fragments.add(BlankFragment.newInstance("4",null));
        return fragments;
    }

    @Override
    protected List<String> getTitles() {
        List list = new ArrayList();
        list.add("待支付");
        list.add("待發貨");
        list.add("待收貨");
        list.add("待評價");
        return list;
    }
}

實現一個底部自定義視圖選項卡

要實現一個底部自定義視圖要相對麻煩一點,因爲底部的視圖是由我們提供的,所以需要一個我們的自定義視圖,那麼怎麼實現呢,我們可能想到在底部設置寫一個自定義能添加底部視圖的view,然後做不同的點擊處理。但是TabLayout下的每個tab其實是支持設置自定義視圖的,只需要調用TabLayout.Tab對象提供的setCustomView方法即可。

這樣我們提供一個底部自定義視圖選項卡的抽象類如下:

1、首先定義佈局
activity_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"></android.support.v4.view.ViewPager>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#d3d3d3"
        android:orientation="vertical">
    </View>
    <android.support.design.widget.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        app:tabIndicatorHeight="0dp"
        android:layout_height="48dp"></android.support.design.widget.TabLayout>
</LinearLayout>

2、抽象類實現

public abstract class TabActivity extends AppCompatActivity{

    private ViewPager viewPager;
    private TabLayout tabLayout;
    private SimpleFragmentPagerAdapter pagerAdapter;
    private TabType mTabType = TabType.BottomCustomViewTab;


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

    private void initView() {
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        tabLayout = (TabLayout) findViewById(R.id.tabLayout);

        pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);
        viewPager.setAdapter(pagerAdapter);
        tabLayout.setupWithViewPager(viewPager);
        tabLayout.setTabMode(TabLayout.MODE_FIXED);

        if (getTabViews()!=null){
            for (int i = 0; i < tabLayout.getTabCount(); i++) {
                TabLayout.Tab tab = tabLayout.getTabAt(i);
                tab.setCustomView(pagerAdapter.getTabView(i));
            }
        }
    }


    protected abstract List<TabItemView> getTabViews();//返回底部自定義tab視圖
    protected abstract List<Fragment> getFragments();//返回tab對應的fragment

    public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {


        public SimpleFragmentPagerAdapter(FragmentManager fm, Context context) {
            super(fm);
        }

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

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

        public View getTabView(int position) {
            return getTabViews().get(position);
        }

    }}

上面代碼和之前實現一個頭部標題選項卡的抽象類大致一樣,只是提供了 protected abstract List getTabViews()方法用於讓子類提供底部自定義tab視圖TabItemView,底部視圖一般就是一個圖片加一個文字,那麼我們自定義一個底部視圖TabItemView如下。

TabItemView實現如下:

public class TabItemView extends LinearLayout {

    /**
     * Item 的標題
     */
    public String title;

    public int textColor;
    public int iconDrawable;
    public int bgDrawable;

    public TextView tvTitle;
    public ImageView ivIcon;

    public TabItemView(Context context, String title, int textColor, int iconDrawable,
                       int bgDrawable) {
        super(context);
        this.title = title;
        this.iconDrawable = iconDrawable;
        this.textColor = textColor;
        this.bgDrawable = bgDrawable;
        init();
    }

    /**
     * 初始化
     */
    public void init(){
        View view = LayoutInflater.from(super.getContext()).inflate(R.layout.view_tab_item, this);
        tvTitle = (TextView) view.findViewById(R.id.tvTitle);
        ivIcon = (ImageView) view.findViewById(R.id.ivIcon);

        LinearLayout.LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        layoutParams.weight = 1;
        view.setLayoutParams(layoutParams);

        if (iconDrawable!=0){
            ivIcon.setImageResource(iconDrawable);
        }
        if (bgDrawable!=0) {
            this.setBackgroundResource(bgDrawable);
        }
        if (textColor!=0){
            tvTitle.setTextColor(textColor);
        }
        tvTitle.setText(title);

    }
}

TabItemView對應佈局:
view_tab_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/viewTabView"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:background="?android:selectableItemBackground"
    android:gravity="center"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/ivIcon"
        android:layout_weight="1"
        android:src="@mipmap/ic_launcher"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TextView
        android:id="@+id/tvTitle"
        android:layout_weight="1"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="首頁"/>

</LinearLayout>

很簡單就是提供一個構造方法在初始化的時候設置圖片、文字、文字顏色等信息。

那麼到此,我們如果遇到如上圖1要實現一個底部視圖選項卡只需要這樣:

public class TestBottomTabActivity extends TabActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected List<TabItemView> getTabViews() {
        List tabviews = new ArrayList();
        tabviews.add(new TabItemView(this,"1",R.color.colorPrimary,R.mipmap.ic_launcher,0));
        tabviews.add(new TabItemView(this,"2",R.color.colorPrimary,R.mipmap.ic_launcher,0));
        tabviews.add(new TabItemView(this,"3",R.color.colorPrimary,R.mipmap.ic_launcher,0));
        tabviews.add(new TabItemView(this,"4",R.color.colorPrimary,R.mipmap.ic_launcher,0));
        return tabviews;
    }

    @Override
    protected List<Fragment> getFragments() {
        List fragments = new ArrayList();
        fragments.add(BlankFragment.newInstance("1",null));
        fragments.add(BlankFragment.newInstance("2",null));
        fragments.add(BlankFragment.newInstance("3",null));
        fragments.add(BlankFragment.newInstance("4",null));
        return fragments;
    }
}

二者結合

到此相信你們已經發現實現頭部文字選項卡或者底部自定義視圖選項卡這裏都用了TabLayout+ViewPager的方式,那麼我們來個結合。

提供一個枚舉指定tab類型,根據tab類型進行數據的獲取即可。
組合之後的抽象類如下:

public abstract class TabActivity extends AppCompatActivity{

    private ViewPager viewPager;
    private TabLayout tabLayout;
    private SimpleFragmentPagerAdapter pagerAdapter;
    private TabType mTabType = TabType.BottomCustomViewTab;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mTabType = getTabType()==null?TabType.BottomCustomViewTab:getTabType();
        if (mTabType==TabType.BottomCustomViewTab){
            setContentView(R.layout.activity_tab);
        }else{
            setContentView(R.layout.activity_tab_top);
        }
        initView();
    }

    private void initView() {
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        tabLayout = (TabLayout) findViewById(R.id.tabLayout);

        pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);
        viewPager.setAdapter(pagerAdapter);
        tabLayout.setupWithViewPager(viewPager);
        tabLayout.setTabMode(TabLayout.MODE_FIXED);

        if (getTabViews()!=null){
            for (int i = 0; i < tabLayout.getTabCount(); i++) {
                TabLayout.Tab tab = tabLayout.getTabAt(i);
                tab.setCustomView(pagerAdapter.getTabView(i));
            }
        }
    }


    protected abstract List<TabItemView> getTabViews();//返回底部自定義tab視圖
    protected abstract List<Fragment> getFragments();//返回tab對應的fragment
    protected abstract List<String> getTitles();//頭部顯示的title列表
    protected abstract TabType getTabType();//tab類型-分爲底部tab和頭部tab

    public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {


        public SimpleFragmentPagerAdapter(FragmentManager fm, Context context) {
            super(fm);
        }

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

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

        @Override
        public CharSequence getPageTitle(int position) {
            if (getTitles()!=null&&!getTitles().isEmpty()){
                return getTitles().get(position);
            }
            return null;
        }

        public View getTabView(int position) {
            return getTabViews().get(position);
        }

    }

    public enum TabType{//Tab類型
        BottomCustomViewTab,//底部自定義tab
        TopTitleTab//頭部標題tab
    }
}

這樣就實現了統一,以後不管是底部還是頭部,只需要繼承TabActivity之後實現相應的抽象方法即可(參考文章開頭)。

結束

源碼下載請點擊http://download.csdn.net/detail/yissan/9861159
是不是節省了一點點時間啊。如果本文對你有一點點幫助請關注我或者爲我點贊!不勝感激!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章