Android底部和标签导航栏—TabLayout+Fragment

介绍

Google官方在2014年Google I/O上推出了全新的设计语言——Material Design。一并推出了一系列实现Material Design效果的控件库——Android Design Support Library。其中,有TabLayout, NavigationView,Floating labels for editing text,Floating Action Button,Snackbar, CoordinatorLayout, CollapsingToolbarLayout等等控件。在今后的学习中,我将一一介绍它们的特点和用法。 
在移动应用中切换不同场景/功能,iOS中以底部三按钮、四按钮来实现的,而在Android中,则是抽屉式菜单或左右滑动式设计的。如何实现类似Google Play应用商店式的左右滑动,这就得靠TabLayout来实现了。

基本使用方式

方式一:

1.在布局中加入该控件:

<android.support.design.widget.TabLayout

          android:id="@+id/tabLayout"

          android:layout_width="wrap_content"

          android:layout_height="wrap_content"/>

2.在代码中

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

tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));

tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));

tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));

这里写图片描述

方式二:

<android.support.design.widget.TabLayout

android:layout_width="wrap_content"

android:layout_height="wrap_content">

<android.support.design.widget.TabItem

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Tab1"/>

...

</android.support.design.widget.TabLayout>

参数属性

上面的Tab颜色感觉不好看,打算换换: 
1.改变选中字体的颜色

app:tabSelectedTextColor="@android:color/holo_orange_light"

2.改变未选中字体的颜色

app:tabTextColor="@color/colorPrimary"

3.改变指示器下标的颜色

app:tabIndicatorColor="@android:color/holo_orange_light"

4.改变整个TabLayout的颜色

app:tabBackground="color"

于是现在我的Tab变成了这个样子: 
这里写图片描述

4.改变TabLayout内部字体大小

总觉得这个字体有点小了,于是想找方法把这个字变得大一点,

好像没有直接变大的方法,可是找到了这个:

app:tabTextAppearance="@android:style/TextAppearance.Holo.Large"//设置文字的外貌

效果: 
这里写图片描述

5.改变指示器下标的高度

既然字体变大了,指示器太小就显得不太好看了,

设置指示器下标的高度: 
效果: 
这里写图片描述 
6.添加图标

有时候Tab只有文字感觉有点单调了:

tabLayout.addTab(tabLayout.newTab().setText("Tab 1").setIcon(R.mipmap.ic_launcher));

这里写图片描述 
7.Tab的模式

数据很多的时候我们应该怎么办呢,简书中的第二个Tab就是可以滑动的:

我们先多加几个tab:

tabLayout.addTab(tabLayout.newTab().setText("Tab 4"));

tabLayout.addTab(tabLayout.newTab().setText("Tab 5"));

tabLayout.addTab(tabLayout.newTab().setText("Tab 6"));

tabLayout.addTab(tabLayout.newTab().setText("Tab 7"));

然后设置属性为:

app:tabMode="scrollable"

默认是fixed:固定的,标签很多时候会被挤压,不能滑动。 
这里写图片描述

8.加入Padding

设置Tab内部的子控件的Padding:

app:tabPadding="xxdp"

app:tabPaddingTop="xxdp"

app:tabPaddingStart="xxdp"

app:tabPaddingEnd="xxdp"

app:tabPaddingBottom="xxdp"

设置整个TabLayout的Padding:

app:paddingEnd="xxdp"

app:paddingStart="xxdp"

9.内容的显示模式

app:tabGravity="center"//居中,如果是fill,则是充满

10.Tab的宽度限制

设置最大的tab宽度:

app:tabMaxWidth="xxdp"

设置最小的tab宽度:

app:tabMinWidth="xxdp"

11.Tab的“Margin”

TabLayout开始位置的偏移量:

app:tabContentStart="100dp"

12.TabLayout的监听事件

选中了某个tab的监听事件OnTabSelectedListener():

tabLayout.setOnTabSelectedListener(newTabLayout.OnTabSelectedListener() {

@Override
public void onTabSelected(TabLayout.Tab tab) {
//选中了tab的逻辑
}

@Override
public void onTabUnselected(TabLayout.Tab tab) {
//未选中tab的逻辑
}

@Override
public void onTabReselected(TabLayout.Tab tab) {
//再次选中tab的逻辑
}

});

13.和ViewPager的联动

最后也是最重要的:

tabLayout.setupWithViewPager(Viewpager);

标签导航栏使用

1.获得Android Design Support Library库: 
依赖。

'compile 'com.android.support:design:22.2.1'

2.定义布局文件: 
通过使用可知,上面那些标签时通过TabLayout实现,而下面内容的变化则是ViewPager+Fragment实现的。 
因此在MainActivity中:

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

Fragment: 
切换ViewPager,显示不同的Fragment,在这里用一个布局相同的Fragment示例。

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

3.具体实现代码: 
(1)创建Fragment

public class PageFragment extends Fragment {
    public static final String ARGS_PAGE = "args_page";
    private int mPage;

    public static PageFragment newInstance(int page) {
        Bundle args = new Bundle();

        args.putInt(ARGS_PAGE, page);
        PageFragment fragment = new PageFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPage = getArguments().getInt(ARGS_PAGE);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_page,container,false);
        TextView textView = (TextView) view.findViewById(R.id.textView);
        textView.setText("第"+mPage+"页");
        return view;
    }
}

(2)适配器类

class MyFragmentPagerAdapter extends FragmentPagerAdapter {
    public final int COUNT = 5;
    private String[] titles = new String[]{"Tab1", "Tab2", "Tab3", "Tab4", "Tab5"};
    private Context context;

    public MyFragmentPagerAdapter(FragmentManager fm, Context context) {
        super(fm);
        this.context = context;
    }

    @Override
    public Fragment getItem(int position) {
        return PageFragment.newInstance(position + 1);
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return titles[position];
    }
}

(3)TabLayout的使用: 
根据官方文档说明,TabLayout的使用有以下两种方式:

通过TabLayout的addTab()方法添加新构建的Tab实例到TabLayout中:

  TabLayout tabLayout = ...;
    tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
    tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
    tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));

2.第二种则是使用ViewPager和TabLayout一站式管理Tab,也就是说不需要像第一种方式那样手动添加Tab:

  ViewPager viewPager = ...;
    TabLayout tabLayout = ...;
    viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(tabLayout));

而我们TabLayout的Demo就是用得第二种方式:

      //Fragment+ViewPager+FragmentViewPager组合的使用
        ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
        MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getSupportFragmentManager(),
                this);
        viewPager.setAdapter(adapter);

        //TabLayout
        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
        tabLayout.setupWithViewPager(viewPager);

这里写图片描述 
效果不错,但是TabLayout中的Tab似乎没有占满屏幕的宽度。如何解决呢? 
有代码和XML两种方式: 
1).代码

  tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
  tabLayout.setTabMode(TabLayout.MODE_FIXED);

2).XML布局文件

<android.support.design.widget.TabLayout
        android:id="@+id/tabLayout"
        app:tabGravity="fill"
        app:tabMode="fixed"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

这里写图片描述 
下面就来解释一下TabGravity和TabMode

TabGravity:放置Tab的Gravity,有GRAVITY_CENTER 和 GRAVITY_FILL两种效果。顾名思义,一个是居中,另一个是尽可能的填充(注意,GRAVITY_FILL需要和MODE_FIXED一起使用才有效果)

TabMode:布局中Tab的行为模式(behavior mode),有两种值:MODE_FIXED 和 MODE_SCROLLABLE。

MODE_FIXED:固定tabs,并同时显示所有的tabs。

MODE_SCROLLABLE:可滚动tabs,显示一部分tabs,在这个模式下能包含长标签和大量的tabs,最好用于用户不需要直接比较tabs。

下面用代码来比较这两种模式的不同:

class MyFragmentPagerAdapter extends FragmentPagerAdapter {
    //tabs的数据集
    public final int COUNT = 10;
    private String[] titles = new String[]{"Tab2221", "T2", "Tb3", "Tab4", "Tab5555555555","Tab2221", "T2", "Tb3", "Tab4", "Tab5555555555"};
...
}


        //1.MODE_SCROLLABLE模式
       tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

        //2.MODE_FIXED模式
        tabLayout.setTabMode(TabLayout.MODE_FIXED);

1.MODE_SCROLLABLE模式 
这里写图片描述 
2.MODE_FIXED模式 
这里写图片描述

案例2:标签栏

这里写图片描述

1. 配置build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.0'
    compile 'com.android.support:design:22.2.0'
    compile 'com.android.support:recyclerview-v7:22.2.0'
    compile 'com.android.support:cardview-v7:22.2.0'
}

com.android.support:design:22.2.0就是我们需要引入的Android Design Support Library,其次我们还引入了Recyclerview和Cardview

2.AppBarLayout,Toolbar与TabLayout 
先看看主界面的布局 (activity_tab_layout.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".TabLayoutActivity"
    android:orientation="vertical">
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabIndicatorColor="#ADBE107E"
            app:tabMode="scrollable"/>

        </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</LinearLayout>

这里用到了AppBarLayout和Toolbar,AppBarLayout是Android Design Support Library新加的控件继承自LinearLayout,它用来将Toolbar和TabLayout组合起来作为一个整体。 
这布局文件最关键的一点就是android.support.design.widget.TabLayout 标签中的app:tabMode=”scrollable”,他设置tab的模式为“可滑动的”,现在我们把这句话去掉,来看看效果: 
这里写图片描述 
上面的tab由于太多(13个)却不能滑动就重叠了。 
接下来在Java中引用 (TabLayoutActivity.java)

public class TabLayoutActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;
    private ViewPager mViewPager;
    private TabLayout mTabLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tab_layout);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mViewPager = (ViewPager) findViewById(R.id.viewpager);
        initViewPager();
    }
  private void initViewPager() {
        mTabLayout = (TabLayout) findViewById(R.id.tabs);
        List<String> titles = new ArrayList<>();
        titles.add("精选");
        titles.add("体育");
        titles.add("巴萨");
        titles.add("购物");
        titles.add("明星");
        titles.add("视频");
        titles.add("健康");
        titles.add("励志");
        titles.add("图文");
        titles.add("本地");
        titles.add("动漫");
        titles.add("搞笑");
        titles.add("精选");

        for(int i=0;i<titles.size();i++){
            mTabLayout.addTab(mTabLayout.newTab().setText(titles.get(i)));
        }
        List<Fragment> fragments = new ArrayList<>();
        for(int i=0;i<titles.size();i++){
            fragments.add(new ListFragment());
        }
        FragmentAdapter mFragmentAdapteradapter =
                new FragmentAdapter(getSupportFragmentManager(), fragments, titles);
        //给ViewPager设置适配器
        mViewPager.setAdapter(mFragmentAdapteradapter);
        //将TabLayout和ViewPager关联起来。
        mTabLayout.setupWithViewPager(mViewPager);
        //给TabLayout设置适配器
        mTabLayout.setTabsFromPagerAdapter(mFragmentAdapteradapter);
    }

在这里我们设定了13个标题内容并创建了相应的TabLayout和Fragment,设置了ViewPager适配器和TabLayout适配器并将将TabLayout和ViewPager关联起来。 
ListFragment的代码(ListFragment.java)

public class ListFragment extends Fragment {
    private RecyclerView mRecyclerView;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mRecyclerView =(RecyclerView) inflater.inflate(R.layout.list_fragment, container, false);
        return mRecyclerView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(mRecyclerView.getContext()));
        mRecyclerView.setAdapter(new RecyclerViewAdapter(getActivity()));
    }
}

这里用RecyclerView来代替ListView来看看RecyclerViewAdapter(RecyclerViewAdapter.java)

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    private Context mContext;

    public RecyclerViewAdapter(Context mContext) {
        this.mContext = mContext;
    }

    @Override
    public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view =          LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_card_main, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final RecyclerViewAdapter.ViewHolder holder, int position) {
        final View view = holder.mView;
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
    }

    @Override
    public int getItemCount() {
        return 10;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public final View mView;

        public ViewHolder(View view) {
            super(view);
            mView = view;
        }
    }
}

最后FragmentAdapter(FragmentAdapter.java)

public class FragmentAdapter extends FragmentStatePagerAdapter {
    private List<Fragment> mFragments;
    private List<String> mTitles;

    public FragmentAdapter(FragmentManager fm, List<Fragment> fragments, List<String> titles) {
        super(fm);
        mFragments = fragments;
        mTitles = titles;
    }

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

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

    @Override
    public CharSequence getPageTitle(int position) {
        return mTitles.get(position);
    }
}

底部栏实现

这里写图片描述

布局 
下面我们开始实现底部Tab,layout布局比较简单,我们只用把TabLayout放置在底部即可

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/appbar"
        android:orientation="vertical">


        <android.support.v4.view.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1.0"
            android:scrollbars="none" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            style="@style/MyCustomTabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

</LinearLayout>

我定义了一个自定义的style,把tabIndicatorHeight设为0dp

<style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
        <item name="tabMaxWidth">@dimen/tab_max_width</item>
        <item name="tabIndicatorColor">?attr/colorAccent</item>
        <item name="tabIndicatorHeight">0dp</item>
        <item name="tabPaddingStart">12dp</item>
        <item name="tabPaddingEnd">12dp</item>
        <item name="tabBackground">@color/tab_bgcolor</item>
        <item name="tabSelectedTextColor">?android:textColorPrimary</item>
</style>

我们首先设置好ViewPager,然后设置TabLayout与ViewPager的对应关系,最后最关键的是使用TabLayout的setCustomView设置自定义的TAB View。

public class BottomTabActivity extends AppCompatActivity {

    private ViewPager viewPager;
    private TabLayout tabLayout;

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setTitle(R.string.title_buttom_tab);
        setSupportActionBar(toolbar);
        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onBackPressed();
            }
        });

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

        SampleFragmentPagerAdapter pagerAdapter =
                new SampleFragmentPagerAdapter(getSupportFragmentManager(), this);

        viewPager.setAdapter(pagerAdapter);


        tabLayout.setupWithViewPager(viewPager);

        for (int i = 0; i < tabLayout.getTabCount(); i++) {
            TabLayout.Tab tab = tabLayout.getTabAt(i);
            if (tab != null) {
                tab.setCustomView(pagerAdapter.getTabView(i));
            }
        }
//      viewPager.setCurrentItem(1);
        tabLayout.getTabAt(0).getCustomView().setSelected(true);
    }
}
 public class SampleFragmentPagerAdapter extends FragmentPagerAdapter {
        final int PAGE_COUNT = 3;
        private String tabTitles[] = new String[]{"TAB1","TAB2","TAB3"};
        private Context context;


        public View getTabView(int position) {
            View v = LayoutInflater.from(context).inflate(R.layout.custom_tab, null);
            TextView tv = (TextView) v.findViewById(R.id.news_title);
            tv.setText(tabTitles[position]);
            ImageView img = (ImageView) v.findViewById(R.id.imageView);
            //img.setImageResource(imageResId[position]);
            return v;
        }

        public SampleFragmentPagerAdapter(FragmentManager fm, Context context) {
            super(fm);
            this.context = context;
        }

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

        @Override
        public Fragment getItem(int position) {
            return PageFragment.newInstance(position + 1);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return tabTitles[position];
        }
    }
 public static class PageFragment extends Fragment {
        public static final String ARG_PAGE = "ARG_PAGE";

        private int mPage;

        public static PageFragment newInstance(int page) {
            Bundle args = new Bundle();
            args.putInt(ARG_PAGE, page);
            PageFragment fragment = new PageFragment();
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mPage = getArguments().getInt(ARG_PAGE);
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_page, container, false);
            TextView textView = (TextView) view;
            textView.setText("Fragment #" + mPage);
            return view;
        }
    }

猜你喜欢

转载自blog.csdn.net/suyimin2010/article/details/81805209