上一篇文章介绍了使用 FragmenttabHost 来使用 tab 导航;到 Android 5.0 的时候,又推出了 TabLayout。因此,有必要对tablayout 进行了解下。

首先我们来看MainActivity,看起来有点多,那是因为包含了 toolbar 的代码:

public class MainActivity extends AppCompatActivity {

    private TabLayout tabLayout;
private ViewPager viewPager;
private MyViewPagerAdapter adapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
}); tabLayout = (TabLayout) findViewById(R.id.tab_layout);
viewPager = (ViewPager) findViewById(R.id.pager); int s = 0; if (viewPager != null) {
setupViewPager(viewPager);
}
} private void setupViewPager(ViewPager viewPager) {
adapter = new MyViewPagerAdapter(getSupportFragmentManager(), this);
adapter.addFragment(new TabFragment1().newInstance("Page1"), "Tab 1");
adapter.addFragment(new TabFragment2().newInstance("Page2"), "Tab 2");
adapter.addFragment(new TabFragment3().newInstance("Page3"), "Tab 3");
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId(); //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} return super.onOptionsItemSelected(item);
}

首先是初始化 tabLayout 和 viewPager,接着是建立一个 MyViewPagerAdapter 的实例,并向里面添加 fragment。

那我们就去看看神秘的 MyViewPagerAdapter。

public class MyViewPagerAdapter extends FragmentStatePagerAdapter {

    private final List<Fragment> myFragments = new ArrayList<>();
private final List<String> myFragmentTitles = new ArrayList<>();
private Context context; public MyViewPagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
} public void addFragment(Fragment fragment, String title) {
myFragments.add(fragment);
myFragmentTitles.add(title);
} @Override
public Fragment getItem(int position) {
return myFragments.get(position);
} @Override
public int getCount() {
return myFragments.size();
} @Override
public CharSequence getPageTitle(int position) {
return myFragmentTitles.get(position);
}
}

这里我们重写了其中几个方法,分别是 getItem,getCount,getPageTitle。那这样我们的数量能够传进去嘛?

不用怕,当我们调用 setAdapt 的时候,其实就把 adapt 传进 ViewPager 了,当需要获取数量的时候,直接调用这个方法就可以了。

tabLayout.setupWithViewPager(viewPager) 则是把tab 与ViewPage 建立联系,这样在变动的时候一起变,在TabLaout 中,可以通过 viewPager.getAdapt 来获取我们刚刚穿进去的adapt;这样两者都有 adapt 这个变量了。

public void setupWithViewPager(ViewPager viewPager) {
PagerAdapter adapter = viewPager.getAdapter();
if(adapter == null) {
throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
} else {
this.setTabsFromPagerAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(this));
this.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
}
}

看源码可以发现 tablayout 和 viewpager 互相设置或者添加监听器,这样无论是滑动 viewPager,还是点击tab都可以实现 view 的切换,两者就可以同步了。

public static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {
private final ViewPager mViewPager; public ViewPagerOnTabSelectedListener(ViewPager viewPager) {
this.mViewPager = viewPager;
} public void onTabSelected(TabLayout.Tab tab) {
this.mViewPager.setCurrentItem(tab.getPosition());
} public void onTabUnselected(TabLayout.Tab tab) {
} public void onTabReselected(TabLayout.Tab tab) {
}
}

我们可以具体看看 ViewPagerOnTabSelectedListener,发现其实现了 TabLayout.OnTabSelectedListener 的接口,在构造函数中,将 viewPager 变量赋值给内部变量,这样在 tab 选中的时候,获取选中 tab 的 position,然后再将设置显示 同样位置的 fragment 即可。

public static class TabLayoutOnPageChangeListener implements OnPageChangeListener {
private final WeakReference<TabLayout> mTabLayoutRef;
private int mScrollState; public TabLayoutOnPageChangeListener(TabLayout tabLayout) {
this.mTabLayoutRef = new WeakReference(tabLayout);
} public void onPageScrollStateChanged(int state) {
this.mScrollState = state;
} public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
TabLayout tabLayout = (TabLayout)this.mTabLayoutRef.get();
if(tabLayout != null) {
tabLayout.setScrollPosition(position, positionOffset, this.mScrollState == 1);
} } public void onPageSelected(int position) {
TabLayout tabLayout = (TabLayout)this.mTabLayoutRef.get();
if(tabLayout != null) {
tabLayout.getTabAt(position).select();
} }
}

当滑动页面,回掉  onPageSelected,传入目前选中的 pager,这时候只要指定对应的 tab 即可。这样两者很好的进行同步了。

我们再来看看布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity"> <android.support.design.widget.AppBarLayout android:layout_height="wrap_content"
android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:layout_scrollFlags="scroll|enterAlways" /> <android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#eeeeee"
app:tabTextColor="#888888"
app:tabSelectedTextColor="#000000"
app:tabGravity="fill"
app:tabMode="fixed"/> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout>

因为有 toolbar ,所以布局文件看上去有些复杂,但其实很简单。

简化后的布局(id 不一定对得上,其他地方 copy 过来的):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tabLayout"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#cdc36e"
app:tabMode="fixed"
app:tabGravity="fill"/> <android.support.v4.view.ViewPager
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/viewPager"
android:layout_below="@+id/tabLayout"
android:layout_centerHorizontal="true" />
</RelativeLayout>

至于 fragment 文件可以参考上一篇文章中的布局

fragmentTabHost 使用示例

或者直接查看源码所在地:

https://github.com/huanshen/Learn-Android/tree/master/TablayoutViewpager

Tablayout ViewPage 使用示例的更多相关文章

  1. 【Scroller】scrollTo scrollBy startScroll computeScroll 自定义ViewPage 简介 示例

    简介 android.widget.Scroller是用于模拟scrolling行为,它是scrolling行为的一个帮助类.我们通常通过它的 startScroll 函数来设置一个 scrollin ...

  2. 仿9GAG制作过程(一)

    有话要说: 准备开始学习Android应用程序的一个完整的设计过程.准备做一个仿9GAG的APP,前端界面设计+后台数据爬虫+后台接口设计,整个流程体验一遍.今天准备先把前端界面的框架给完成了. 成果 ...

  3. viewpage和tablayout导航栏

    引入material库: implementation 'com.google.android.material:material:1.2.1' <?xml version="1.0& ...

  4. ViewPage 大圣归来 原生示例

    VP简介 android-support-v4.jar 是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api.而ViewPage就是其中之一,利用它,我 ...

  5. TabLayout 简单使用。

    先上效果图 在使用TabLayout 之前需要导入design包. 我使用的是android studio 只要在build.gradle中加入 compile 'com.android.suppor ...

  6. ViewPager导航栏TabLayout

    ViewPager中加入TabLayout导航 需要导入依赖包:  'com.android.support:appcompat-v7:xxxxx' compile 'com.android.supp ...

  7. Android Material Design控件学习(一)——TabLayout的用法

    前言 Google官方在14年Google I/O上推出了全新的设计语言--Material Design.一并推出了一系列实现Material Design效果的控件库--Android Desig ...

  8. 使用TabLayout快速实现一个导航栏

    在没有Material Design的年代,要实现一个类似微信主页面的效果,我们有以下几种解决方案: 1.Fragment + ViewPager  +  RadioGroup自定义固定导航条 2.F ...

  9. 介绍三个Android支持库控件:TabLayout+ViewPager+RecyclerView

    本文主要介绍如下三个Android支持库控件的配合使用: TabLayout:android.support.design.widget.TabLayout ViewPager:android.sup ...

随机推荐

  1. PHP大文件分割上传(分片上传)

    服务端为什么不能直接传大文件?跟php.ini里面的几个配置有关 upload_max_filesize = 2M //PHP最大能接受的文件大小 post_max_size = 8M //PHP能收 ...

  2. 分享一小坑(与swagger有关),以后碰到了可以快速规避

     ---------------------------------------------------------------------------------踩坑过程:①webapi的某acti ...

  3. node.js之第一天

    一.http模块 //require表示引包,引包就是引用自己的一个特殊功能 var http = require("http"); //创建服务器,参数是一个回调函数,表示如果有 ...

  4. 将STM32 iap hex文件与app hex文件合并为一个hex文件

    日前公司产品需要增加远程升级功能,boot loader程序写好后交予生产部门使用时他们反馈每个产品程序需要刷写两次(一个boot loader 一个app程序),生产进度变慢浪费时间,于是乎研究如何 ...

  5. Material使用01 侧边栏MdSidenavModule、工具栏MdTollbarModule

    前提准备: 构建好一个Angular2应用 熟悉CSS的flex布局风格 1 利用flex进行布局 1.1 创建三个组件 app-header app-main app-footer 1.2 在主组件 ...

  6. HDU 2298 Toxophily(公式/三分+二分)

    Toxophily Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  7. 基于 HTML5 Canvas 的 3D 机房创建

    对于 3D 机房来说,监控已经不是什么难事,不同的人有不同的做法,今天试着用 HT 写了一个基于 HTML5 的机房,发现果然 HT 简单好用.本例是将灯光.雾化以及 eye 的最大最小距离等等功能在 ...

  8. Intellij idea 复制粘贴查找快捷键失效

    遇到此问题,竟不能复制, 发现原因,是因为勾选了Vim模式, Tools,Vim Emulator,前面会有一个√,取消即可,如图: 我的是这个原因,复制粘贴快捷键失效,也有可能历史粘贴板的深度不够 ...

  9. reference file contains errors

    一,问题分析 在学习 JavaWeb 的开发,很多时候我们会引用许多 JAR ,以为版本的问题,有时候就会出现这个问题:reference file contains errors (引用文件包含错误 ...

  10. seleniumPO模式

    一.框架目录结构 二.代码 2.1page层代码 package com.mianshui.page; import org.openqa.selenium.WebElement; import or ...