ToolBar、TabLayout、Fragment+ViewPager的开发实践

此文优先发布于个人我的博客:TB+TableLayout+Fragment+VP开发实践html

研究ToolBar、TabLayout、Fragment+ViewPager的开发实践复盘以及还没有解决的问题。欢迎评论留言。java

XML

TabLayout

添加依赖android

'android.support.design:28.0.0'

此处添加AppBarLayout做为完整的布局1:git

AppBarLayout是Android Design Support Library新加的控件继承自LinearLayout,
它用来将Toolbar和TabLayout组合起来做为一个总体。
<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/main_tablayout"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"         
          android:background="@color/color_title_bar"/>

<android.support.v4.view.ViewPager <!--TabLayout相关联的ViewPager-->
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1"
        android:background="@android:color/white" />

TabLayout可选属性

tab
可更改属性 属性说明
tabBackground TabLayout的背景
tabSelectedTextColor 当前标签的字体颜色
tabIndicator

能够写一个style,下文中会提到github

可更改属性 属性说明
tabIndicatorColor 选中线的颜色
tabIndicatorHeight 选中线的高度
tabMode
可更改属性 属性说明
FIXED 不可左右滑动,用于标签较少时
SCROLLABLE 可左右滑动,用于标签较多时

Fragment

为何要建立Fragment:TabLayout中的ViewPager对应着相应的Fragment,因此须要建立。segmentfault

有的示例仅建立了一个Fragment,其中为定义文字数组实现,若开发中则须要多个Fragment添加,均用Arratlist于Activity中。数组

XXXFragment.java:app

public class XXXFragment extends Fragment {
    
    private Page/View;  //建立变量
 
    @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; //参考[^6]
        textView.setText("Fragment #" + mPage); 
        return view;
    }
 
}

一些暂未明确的代码段框架

public static final String TYPE = "TYPE"; //此处未知含义

参考2ide

//此处的含义多是新增实例,存储值?
    public static XXXFragment newInstance(int page) { 
        Bundle args = new Bundle();
        args.putInt(ARG_PAGE, page);
        PageFragment pageFragment = new PageFragment();
        pageFragment.setArguments(args);
        return pageFragment;
    }

Activity

若是须要定义TableLayout的tab文字,则在其中定义:public static final String[] titles,以后添加集合。

这里把2定义文字放在了Adapter中,缘由未知。

关于添加图片,下文有提到。

private Toolbar toolbar; //增长相关变量
    private TabLayout tabLayout;
    private ViewPager viewPager;

    public static final String[] titles = {"", ""};

    private List<Fragment> fragments; //定义fragment的集合缩写
    private List<String> tabNames;
    private List<Integer> tabIcs;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_xxx);
        initView();        //各类初始化:界面、添加的fragment值、事件
        initValue();
        initEvent();
    }

    //各类初始化开始

    private void initView() { //初始化实例

        toolbar = (Toolbar) findViewById(R.id.Toolbar); 
        setSupportActionBar(toolbar); //支持actionbar,此处多种写法
        getSupportActionBar().setDisplayHomeAsUpEnabled(true); //在首页显示

        viewPager = (ViewPager) findViewById(R.id.viewpager); //实例化控件
        tabLayout = (TabLayout) findViewById(R.id.tabs);
    }

    private void initValue() { 
    //初始化值,添加每个TableLayout里的ArrayList,设置与标题栏一一对应的视图(片断)集合

        fragments = new ArrayList<>();
        fragments.add(new xxxFragment());
        fragments.add(new xxxFragment()); //有多少个fragment就在这里添加多少

        tabNames = new ArrayList<>(); //添加标题集合,同上
        tabNames.add(" ");
        tabNames.add(" ");

        /*tabIcs = new ArrayList<>(); 此处尚不明确是否有,使用spanstring或其余方法此处是否须要
        tabIcs.add(R.drawable.tab_xxx);
        tabIcs.add(R.drawable.tab_xxx);*/
        
        //给tabLayout添加选项卡
        for(int i=0;i< fragments.size();i++){
            tabLayout.addTab(tabLayout.newTab().setText((CharSequence) fragments.get(i)));
        }

        FragmentViewPagerAdapter adapter = new FragmentViewPagerAdapter
        (getSupportFragmentManager(), fragments, tabNames,tabIcs); 
        // 初始化ViewPager适配器        //此处须要增长与添加的集合以及上述定义的值匹配,若未定义则无需添加

        viewPager.setAdapter(adapter); //给ViewPager设置适配器
        tabLayout.setupWithViewPager(viewPager);  //将TabLayout和ViewPager关联起来      
        /*setupWithViewPager这个方法会先将tab清除而后再根据ViewPager的adapter里的count去取pagetitle,这也就是有时遇到用addTab方法添加tab不起做用的问题。*/

        //setupTabIcons();
        viewPager.setCurrentItem(1);
        viewPager.setCurrentItem(0);
    }

此处的setupTabIcons()方法,在下文添加图片会提到。[参考连接]()

默认显示第一个Tab3

tab.addTab(tab,i == 0, ? true:false);

FragmentPagerAdapter

须要使用Fragment的话就须要这个适配器

public class一个自定义的适配器名称继承自FragmentPagerAdapter。

List<Fragment> xxxfragment;
    List<String> titleList;

public MyTableViewAdapter(FragmentManager fm , List<Fragment> pagerList , List<String> titleList) {
        super(fm);
    this.pagerList = pagerList; // 此处使用this.与上述定义匹配
  
}
    
public Fragment getItem(int poition)
    super.

public int getCount(int poition) { return (tab个数) } 
   return xxxfragment.get(position); //普通状况
   return xxxfragment != null ? pagerList.size() : 0; //设置不等于null的状况,参考[^4]

public long getItemId(int poition)  { return super.getItemId(position) }
return xxxfragment.get(position);

此处可能还有,参考 3

public destoryItemId(View view contain,int poition,Object object)

点击切换Tab的操做(两种方式)

  1. .setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() 方法3

当tab页面被选中时,会调用这个方法,当tab页面被选中时,切换目前的fragment:

@Override
public void onTabSelected(TabLayout.Tab tab) {
int position = tab.getPosition();
    
Fragment fragment = (Fragment)adapter.instantiateItem(container, position);
    
adapter.setPrimaryItem(container, pos, fragment);
adapter.finishUpdate(container);
    
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
  1. 使用selector代替4

高级

在TabLayout中添加图片

方法

getTabView()4

此方法为我首先尝试使用,能够更改图标颜色以及状态。

步骤:

  1. 在Activity.java中设置图片点击(使用selector)数组public int[]
  2. 设置setupTabIcons();
  3. 建立getTabView()方法

这里52把此方法放到了FragmentAdapter中,我的猜想缘由多是一同将getTabView()或imagespan使用。

SpannableString

更多支持:介绍参考连接6

SpannableString这个类实现了CharSequence这个接口,因此能够在Adapter中的getPageTitle()中返回。

SpannableString的构造方法须要一个参数:CharSequence(超级字符串的基本显示内容),

setSpan为核心方法

方法值:

public void setSpan(Object what, int start, int end, int flags) {
    super.setSpan(what, start, end, flags);
          //what:向这个超级字符串中添加的内容。例如:前景色、背景色、图片、连接、下划线等
          //start:开始的位置(0为开始)
          //结束的位置
          //flags:标识在span范围内的文本先后输入新的字符时是否也应用这个效果
}

SpanString举例因为众多,表格与文末7

经搜索:

其中使用ImageSpan的两种方法,发现如下两种均为仅添加图标方法,而不适用于点击切换颜色:

使用SpanString和Imagespan:2
  1. 在SimpleFragmentPagerAdapter中设置数组int[]
  2. 样式文件定义
保留字符串并设置空,添加图片方法8
  1. 修改Adapter的构造方法:设置tabName和tabIcons变量:每一个Tab上的文字和图标的变量
  2. 修改getPageTitle()方法:if-else语句:若是不设置文字,则保留一个字符,若是设置图标,则使用span
  3. 添加定义style(关键):textAllCaps、android:textAllCaps必须设置为false,以后XML中TabLayout设置style。

SpanString举例,示例代码7,项目完整地址9.

可更改属性 属性说明
AbsoluteSizeSpan 单位为物理像素
AlignmentSpan 支持ALIGN_NORMAL,ALIGN_OPPOSITE,ALIGN_CENTER
BackgroundColorSpan 文字背景色改变
BulletSpan 小圆圈
ClickableSpan 可点击
DrawableMarginSpan Drawable,不占位
DynamicDrawableSpan DynamicDrawable,占位
ForegroundColorSpan 前景色
IconMarginSpan 图标margin,不占位
ImageSpan 图片,占位
LeadingMarginSpan 控制行前空隙
QuoteSpan 左侧出现引用符号 竖线
RelativeSizeSpan 字体放大
ScaleXSpan 字体宽度放大
StrikethroughSpan 删除线
StyleSpan 主要由正常、粗体、斜体和同时加粗倾斜四种样式,常量值定义在Typeface类中
SubscriptSpan 下标
SuperscriptSpan 上标
TextAppearanceSpan Sets the text color, size, style, and typeface to match a TextAppearance
TypefaceSpan 字体设置
UnderlineSpan 下划线
URLSpan URL


  1. Android Design Support Library(一)用TabLayout实现相似网易选项卡动态滑动效果
  2. android design library提供的TabLayout的用法,不少教程都参考了此文章。
  3. 利用TabLayout和fragment搭建app框架
  4. Android TabLayout setCustomView 实现带图标的tab
  5. 4
  6. android设计库提供的TabLayout的简单使用(TabLayout + ViewPager + Fragment)
  7. SpannableString
  8. TabLayout与ViewPager的联合使用
  9. onlyloveyd/SpannableDemo
相关文章
相关标签/搜索