原文出处:http://chenfuduo.me/2015/07/30/TabLayout-of-design-support-library/ 

在开发中,我们常常需要ViewPager结合Fragment一起使用,如下图:
1

我们可以使用三方开源的PagerSlidingTabStrip去实现,或者viewpagerindicator,我一般都偏向前者。现在我们可以使用Design support library库的TabLayout去实现了。最终的效果图:

效果图

创建布局

<?xml version="1.0" encoding="utf-8"?>               在xml添加TabLayout,如同ViewPager,直接`android.support.design.widget.TabLayout`即可。还有其他的属性我会在代码中设置。

创建Fragment

package me.chenfuduo.myfragmentdemo.fragment;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import me.chenfuduo.myfragmentdemo.R;/** * Created by Administrator on 2015/7/30. */public 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 pageFragment = new PageFragment();        pageFragment.setArguments(args);        return pageFragment;    }    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mPage = getArguments().getInt(ARG_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;        textView.setText("Fragment #" + mPage);        return view;    }}

其中Fragment的布局为:

<?xml version="1.0" encoding="utf-8"?>


ViewPager的适配器

package me.chenfuduo.myfragmentdemo.adapter;import android.content.Context;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentPagerAdapter;import me.chenfuduo.myfragmentdemo.fragment.PageFragment;/** * Created by Administrator on 2015/7/30. */public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {    final int PAGE_COUNT = 3;    private String tabTitles[] = new String[]{"tab1","tab2","tab3"};    private Context context;    public SimpleFragmentPagerAdapter(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 PAGE_COUNT;    }    @Override    public CharSequence getPageTitle(int position) {        return tabTitles[position];    }}

设置TabLayout

package me.chenfuduo.myfragmentdemo;import android.os.Bundle;import android.support.design.widget.TabLayout;import android.support.v4.app.FragmentActivity;import android.support.v4.view.ViewPager;import android.view.Menu;import android.view.MenuItem;import me.chenfuduo.myfragmentdemo.adapter.SimpleFragmentPagerAdapter;public class ThirdActivity extends FragmentActivity {    private SimpleFragmentPagerAdapter pagerAdapter;    private ViewPager viewPager;    private TabLayout tabLayout;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_third);        pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);        viewPager = (ViewPager) findViewById(R.id.viewpager);        viewPager.setAdapter(pagerAdapter);        tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);        tabLayout.setupWithViewPager(viewPager);        tabLayout.setTabMode(TabLayout.MODE_FIXED);    }}

这里提几点我遇到的问题

  • tabLayout.setTabMode(TabLayout.MODE_FIXED);

开始我设置的是:

tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);


运行后,三个TabLayout标签挤到一块去了。如下:


查看api,找到结果了。这个tabmode有两个属性值:

  • MODE_FIXED:Fixed tabs display all tabs concurrently and are best used with content that benefits from quick pivots between tabs.

  • MODE_SCROLLABLE:Scrollable tabs display a subset of tabs at any given moment, and can contain longer tab labels and a larger number of tabs.

不做过多的解释,MODE_SCROLLABLE适合很多tabs的情况。

  • setupWithViewPager必须在ViewPager.setAdapter()之后调用

查看下源码就知道了:

public void setupWithViewPager(ViewPager viewPager) {    PagerAdapter adapter = viewPager.getAdapter();    if(adapter == null) {        throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");    } else {        ...    }}


以上就是最基本的用法,是不是很简单。哈~

定义TabLayout的样式

默认的情况下,TabLayout的tab indicator的颜色是Material Design中的accent color(#009688),我们可以稍作修改:

    #0000FF


在布局中使用:

 


还有一些其他的样式可供选择:

    @dimen/tab_max_width    ?attr/colorAccent    2dp    12dp    12dp    ?attr/selectableItemBackground    @style/MyCustomTabTextAppearance    ?android:textColorPrimary    14sp    ?android:textColorSecondary    true


添加icon到tab

当前的TabLayout没有方法让我们去添加icon,我们可以使用SpannableString结合ImageSpan来实现,在SimpleFragmentPagerAdapter中:

private int[] imageResId = {        R.drawable.ic_one,        R.drawable.ic_two,        R.drawable.ic_three};// ...@Overridepublic CharSequence getPageTitle(int position) {    // Generate title based on item position    // return tabTitles[position];    Drawable image = context.getResources().getDrawable(imageResId[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;}


运行,发现没有显示,这是因为TabLayout创建的tab默认设置textAllCaps属性为true,这阻止了ImageSpan被渲染出来,可以通过下面的样式文件定义来改变:

      @style/MyCustomTextAppearance      false


现在运行,效果就出来了。

添加icon和text到tab

@Overridepublic CharSequence getPageTitle(int position) {    // Generate title based on item position    Drawable image = context.getResources().getDrawable(imageResId[position]);    image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());    // Replace blank spaces with image icon    SpannableString sb = new SpannableString("   " + tabTitles[position]);    ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);    sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);    return sb;}

我们看到在实例化SpannableString的时候,我在tabTitles[position]前面加了几个空格,这些空格的位置是用来放置icon的。

添加自定义的view到tab

适配器中增加getTabView(...)方法:

package me.chenfuduo.myfragmentdemo.adapter;import android.content.Context;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentPagerAdapter;import android.view.LayoutInflater;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import me.chenfuduo.myfragmentdemo.R;import me.chenfuduo.myfragmentdemo.fragment.PageFragment;/** * Created by Administrator on 2015/7/30. */public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {    final int PAGE_COUNT = 3;    private String tabTitles[] = new String[]{"tab1", "tab2", "tab3"};    private int[] imageResId = {R.drawable.avatar_enterprise_vip,            R.drawable.avatar_grassroot,            R.drawable.avatar_vip};    private Context context;    public SimpleFragmentPagerAdapter(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 PAGE_COUNT;    }    @Override    public CharSequence getPageTitle(int position) {        //第一次的代码        //return tabTitles[position];        //第二次的代码       /**         Drawable image = context.getResources().getDrawable(imageResId[position]);        image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());        SpannableString sb = new SpannableString(" " + tabTitles[position]);        ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);        sb.setSpan(imageSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);        return sb;*/        return null;    }    public View getTabView(int position){        View view = LayoutInflater.from(context).inflate(R.layout.tab_item, null);        TextView tv= (TextView) view.findViewById(R.id.textView);        tv.setText(tabTitles[position]);        ImageView img = (ImageView) view.findViewById(R.id.imageView);        img.setImageResource(imageResId[position]);        return view;    }}


简单的布局:

<?xml version="1.0" encoding="utf-8"?>        


使用:

@Override   protected void onCreate(Bundle savedInstanceState) {       super.onCreate(savedInstanceState);       setContentView(R.layout.activity_third);       pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);       viewPager = (ViewPager) findViewById(R.id.viewpager);       viewPager.setAdapter(pagerAdapter);       tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);       tabLayout.setupWithViewPager(viewPager);       tabLayout.setTabMode(TabLayout.MODE_FIXED);       for (int i = 0; i < tabLayout.getTabCount(); i++) {           TabLayout.Tab tab = tabLayout.getTabAt(i);           tab.setCustomView(pagerAdapter.getTabView(i));       }   }


处理配置改变

当屏幕旋转或者配置改变的时候,我们需要保存当前的状态。

@Override   public void onSaveInstanceState(Bundle outState) {       super.onSaveInstanceState(outState);       outState.putInt(POSITION,tabLayout.getSelectedTabPosition());   }   @Override   protected void onRestoreInstanceState(Bundle savedInstanceState) {       super.onRestoreInstanceState(savedInstanceState);       viewPager.setCurrentItem(savedInstanceState.getInt(POSITION));   }


需要注意的是getSelectedTabPosition()方法是最新的design support library才有的。
最后的效果如下:

更多相关文章

  1. Android用软键盘将整个界面推上去
  2. Android实现计算器布局(四种布局方式)之GridLayout网格布局
  3. Android如何在初始化的时候获取加载的布局的宽高
  4. Android(安卓)Studio App 播放工程内部音乐文件
  5. Android半透明提示效果的实现
  6. Android5.X之百分比布局库(percent-support-lib) 解析与扩展
  7. android SDK中java环境变量配置
  8. Android:控件布局(表格布局)TableLayout
  9. Android实战技巧:常用开发FAQ(续)

随机推荐

  1. ScrollView常用属性汇总
  2. Android平滑移动——Scroller类研究
  3. 声波通信、声波传输原理及源代码
  4. Android Studio连接STF失效
  5. android弹出对话框
  6. Android高效加载大图、多图解决方案,有效
  7. android基础入门(一)――搭建android开发
  8. 如何看待安卓未来的发展
  9. 二维码的生成细节和原理
  10. 我的DIY Android 之旅--gps框架及简析