Tablayout ViewPage 使用示例
上一篇文章介绍了使用 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 文件可以参考上一篇文章中的布局
或者直接查看源码所在地:
https://github.com/huanshen/Learn-Android/tree/master/TablayoutViewpager
Tablayout ViewPage 使用示例的更多相关文章
- 【Scroller】scrollTo scrollBy startScroll computeScroll 自定义ViewPage 简介 示例
简介 android.widget.Scroller是用于模拟scrolling行为,它是scrolling行为的一个帮助类.我们通常通过它的 startScroll 函数来设置一个 scrollin ...
- 仿9GAG制作过程(一)
有话要说: 准备开始学习Android应用程序的一个完整的设计过程.准备做一个仿9GAG的APP,前端界面设计+后台数据爬虫+后台接口设计,整个流程体验一遍.今天准备先把前端界面的框架给完成了. 成果 ...
- viewpage和tablayout导航栏
引入material库: implementation 'com.google.android.material:material:1.2.1' <?xml version="1.0& ...
- ViewPage 大圣归来 原生示例
VP简介 android-support-v4.jar 是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api.而ViewPage就是其中之一,利用它,我 ...
- TabLayout 简单使用。
先上效果图 在使用TabLayout 之前需要导入design包. 我使用的是android studio 只要在build.gradle中加入 compile 'com.android.suppor ...
- ViewPager导航栏TabLayout
ViewPager中加入TabLayout导航 需要导入依赖包: 'com.android.support:appcompat-v7:xxxxx' compile 'com.android.supp ...
- Android Material Design控件学习(一)——TabLayout的用法
前言 Google官方在14年Google I/O上推出了全新的设计语言--Material Design.一并推出了一系列实现Material Design效果的控件库--Android Desig ...
- 使用TabLayout快速实现一个导航栏
在没有Material Design的年代,要实现一个类似微信主页面的效果,我们有以下几种解决方案: 1.Fragment + ViewPager + RadioGroup自定义固定导航条 2.F ...
- 介绍三个Android支持库控件:TabLayout+ViewPager+RecyclerView
本文主要介绍如下三个Android支持库控件的配合使用: TabLayout:android.support.design.widget.TabLayout ViewPager:android.sup ...
随机推荐
- Angular之指令Directive系列
项目筹备近期开启Angular学习,指令比较难理解所以记录备案,推荐Angualr实战学习视频大漠穷秋 Angular实战 一.指令directive概述 指令可以对元素绑定事件监听或者改变DOM结构 ...
- tomcat8权限分离
安装jdk tar xf jdk-8u121-linux-x64.tar.gz mv jdk-* /usr/local/jdk1.8 vi /etc/profile export JAVA_HOME ...
- iOS开发-自己定义后台显示图片(iOS7-Background Fetch的应用)
之前在用电池医生的时候, 发现它有这样一个功能:当应用进入后台的时候, 会显示另外一张图片覆盖App Switcher显示的界面. 效果例如以下: 变成----> 而这种一个功能, 对于保护用户 ...
- Android官方技术文档翻译——Gradle 插件用户指南(5)
昨晚把第五章未译完的几句话攻克了.只是第六章没怎么译,明后天又是周末,假设周一前第六章翻译完的话,周一再发第六章. 本文译自Android官方技术文档<Gradle Plugin User Gu ...
- C++、Objective-C 混合编程
在XCODE中想使用C++代码,你须要把文件的扩展名从.m改成.mm.这样才会启动g++编译器. 我们来看个測试代码: [java] view plaincopy class TestC { priv ...
- Swift开发教程--使用Storyboard进行界面跳转
使用storyboard结合代码来做确实能够给开发带来非常多的便利. 在实践的过程中,我们常常会遇到界面的跳转问题. 通过控件和界面的建立的"连接"就能够了. 假设是navigat ...
- POJ 2482 Stars in Your Window(线段树)
POJ 2482 Stars in Your Window 题目链接 题意:给定一些星星,每一个星星都有一个亮度.如今要用w * h的矩形去框星星,问最大能框的亮度是多少 思路:转化为扫描线的问题,每 ...
- 深入理解javascript函数进阶系列第四篇——惰性函数
前面的话 惰性函数表示函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了.本文将详细介绍惰性 ...
- 在无人值守程序(服务)中调用Microsoft Graph
作者:陈希章 发表于 2017年5月31日 什么是无人值守程序(服务) 我在此前用了几篇文章分别介绍了在桌面应用程序(控制台),Web应用程序(ASP.NET MVC),以及PowerSehll脚本中 ...
- jQuery里使用setinterval
如果第一个参数是一个已写好的函数而不是匿名代码块,一定不要加引号,直接var ** = setinterval{myFunction ,500},只能这样,加括号会直接只调用一次,自然不行,加引号和括 ...