PagerSlidingTabStrip 源码解析
来源:互联网 发布:mysql root权限 编辑:程序博客网 时间:2024/06/06 05:57
PagerSlidingTabStrip 源码解析
本文为 Android 开源项目源码解析 中 ${PagerSlidingTabStrip} 部分
项目地址:[
分析者:ayyb1988,分析状态:已完成
校对者:,校对状态:未开始
Demo效果展示如下
上面tab为textviewtab。下面tab为icontab。
1. 总体设计
pagerSlidingTabStrip实现联动效果的原理是,它引用了ViewPager的OnPageChangeListener。
但是viewpager注册的listener不是自身的OnPageChangeListener,而是pagerSlidingTabStrip内部类PageListener。
通过PageListener实现对对viewpager和tab的封装。从而实现滑动联动效果。
可以设置tab的类型为textview还是icon。对于textview可设置字库属性。
通过提供方法如滑动指示器 下划线 tab风格线 tab权重等达到自定义的效果。
2. 流程图
3. 功能介绍
3.1 特性介绍
- 兼容Android支持库中的ViewPager 的一个滑动分页指示器的控件。
- 滑动时实现TextView颜色状态的联动
- 支持文字导航指示,可指定选中的pager导航字体属性
- 支持图片导航指示,可高亮选中pager页导航背景
- 很好的扩展性
3.2 集成及使用指南
3.2.1
在 gradle 中dependencies { compile 'com.astuetz:pagerslidingtabstrip:1.0.1'}
3.2.2 在layout布局文件中引入PagerSlidingTabStrip,通常布局在viewpager上面。如下:
<com.astuetz.PagerSlidingTabStrip android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="48dip" />
3.2.3 在oncreate方法中(或Fragment的onCreateView)中,绑定PagerSlidingTabStrip到Viewpager
// 初始化ViewPager和Adapter ViewPager pager = (ViewPager) findViewById(R.id.pager); pager.setAdapter(new TestAdapter(getSupportFragmentManager())); // 绑定PagerSlidingTabStrip到ViewPager上 PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs); tabs.setViewPager(pager);
3.2.4 如果你的view pager使用到OnPageChangeListener。你应该通过这个PagerSlidingTabStrip控件设置而不是Viewpager。如下:
// continued from above tabs.setOnPageChangeListener(mPageChangeListener);
3.3 用户定制
根据你的需要修改下面的值
- pstsIndicatorColor 滑动指示器的颜色
- pstsUnderlineColor 整个view【PagerSlidingTabStrip】下划线的颜色
- pstsDividerColor tabs之间分割线的颜色
- pstsIndicatorHeight 滑动指示器的高度
- pstsUnderlineHeight 整个View【PagerSlidingTabStrip】下滑线的高度
- pstsDivviderPadding 分割线上部、下部的内间距
- pstsTabPaddingLeftRight 每个tab左右内间距
- pstsScrollOffset 选中tab的滑动的距离
- pstsTabBackground 每个tab的背景图片,使用StateListDrawable
- pstsShouldExpand 如果设置为true,每个tab的宽度拥有相同的权重
- pstsTextAllCaps 如果设置为true,所有的tab字体转为大写
4. 详细设计
4.1 类详细介绍
4.2 核心方法及功能介绍
pagerSlidingTabStrip实现联动效果的原理是,它引用了ViewPager的 OnPageChangeListener。但是viewpager注册的listener不是自身的OnPageChangeListener,而是pagerSlidingTabStrip内部类PageListener。通过PageListener实现对对viewpager和tab的封装。从而实现滑动联动效果。下面结合代码详细说明
private class PageListener implements OnPageChangeListener { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { //当前view的位置也即tab的位置 currentPosition = position; //当前view滑动的距离 。其中currentPositionOffset 为float,介于0~1 代表相对于tab宽偏移的比例 currentPositionOffset = positionOffset; //根据上面得到的view的位置和偏移位置,来同步tab的位置和偏移距离。 scrollToChild(position, (int) (positionOffset * tabsContainer.getChildAt(position).getWidth())); //重绘view,实现tab滑动的效果。 invalidate(); //下面的delegatePageListener就是我们设置的viewpager.setOnPageChangeListener.而现在把它封装在整个pagerSlidingTabStrip中,实现viewpager滑动的效果。 if (delegatePageListener != null) { delegatePageListener.onPageScrolled(position, positionOffset, positionOffsetPixels); } } @Override public void onPageScrollStateChanged(int state) { //滑动结束。positionOffset归零 if (state == ViewPager.SCROLL_STATE_IDLE) { scrollToChild(pager.getCurrentItem(), 0); } //调用viewpager.setOnPageChangeListener if (delegatePageListener != null) { delegatePageListener.onPageScrollStateChanged(state); } } @Override public void onPageSelected(int position) { //调用viewpager.setOnPageChangeListener if (delegatePageListener != null) { delegatePageListener.onPageSelected(position); } } }
scrollToChild,tab的滑动位置 实现如下:
private void scrollToChild(int position, int offset) { if (tabCount == 0) { return; } int newScrollX = tabsContainer.getChildAt(position).getLeft() + offset; if (position > 0 || offset > 0) { newScrollX -= scrollOffset; } //滑动到的位置。 if (newScrollX != lastScrollX) { lastScrollX = newScrollX; scrollTo(newScrollX, 0); } }
接下来说下 addTextTab 和 addIconTab。即tab是text还是icon。如果是icon的话,通过viewpager的adapter实现接口IconTabProvider。来确定icontab。
for (int i = 0; i < tabCount; i++) { if (pager.getAdapter() instanceof IconTabProvider) { addIconTab(i, ((IconTabProvider) pager.getAdapter()).getPageIconResId(i)); } else { addTextTab(i, pager.getAdapter().getPageTitle(i).toString()); } }
4.3 View绘制机制
请参考公共技术点viewdrawflow部分
在pagerSlidingTabStrip中重写了onDraw函数
绘画滑动指示器; 绘画整个tabs下划线; 绘画tab之间间隔线。代码如下
// draw indicator line rectPaint.setColor(indicatorColor); // default: line below current tab View currentTab = tabsContainer.getChildAt(currentPosition); float lineLeft = currentTab.getLeft(); float lineRight = currentTab.getRight(); // if there is an offset, start interpolating left and right coordinates between current and next tab if (currentPositionOffset > 0f && currentPosition < tabCount - 1) { View nextTab = tabsContainer.getChildAt(currentPosition + 1); final float nextTabLeft = nextTab.getLeft(); final float nextTabRight = nextTab.getRight(); lineLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset) * lineLeft); lineRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset) * lineRight); } canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height, rectPaint); // draw underline rectPaint.setColor(underlineColor); canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint); // draw divider dividerPaint.setColor(dividerColor); for (int i = 0; i < tabCount - 1; i++) { View tab = tabsContainer.getChildAt(i); canvas.drawLine(tab.getRight(), dividerPadding, tab.getRight(), height - dividerPadding, dividerPaint); }
5. 杂谈
该库有很好的自定义性和扩展性。比如修改滑动指示器为一张图片【目前为设定颜色值和高度来决定】
参考文献
ViewPagerindicator 源码解析
View的绘制:
- How Android Draws Views
- View 绘制流程
- Android View绘制流程
- Android中View绘制流程以及invalidate()等相关方法分析
- Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(下)
TOUCH事件处理
- View 事件传递
- Andriod 从源码的角度详解View,ViewGroup的Touch事件的分发机制
- Android 中Touch(触屏)事件传递机制
Demo 下载
- PagerSlidingTabStrip 源码解析
- PagerSlidingTabStrip源码解析
- PagerSlidingTabStrip 源码解析
- PagerSlidingTabStrip源码解析
- Android 开源项目源码解析 -->PagerSlidingTabStrip 源码解析(十八)
- PagerSlidingTabStrip源码分析
- PagerSlidingTabStrip源码分析
- XlistView,Xml解析,PagerSlidingTabStrip
- Android源码解析-仿今日头条PagerSlidingTabStrip滑动页面导航效果
- PagerSlidingTabStrip源码分析及扩展
- PagerSlidingTabStrip
- PagerSlidingTabStrip
- 足球控(1) PagerSlidingTabStrip用法及解析
- Android仿网易新闻导航栏PagerSlidingTabStrip源码分析
- PagerSlidingTabStrip+ViewPager
- PagerSlidingTabStrip应用
- PagerSlidingTabStrip + ViewPager
- ym——Android仿网易新闻导航栏PagerSlidingTabStrip源码分析
- iOS开发系列--让你的应用“动”起来,iOS动画
- 2015Java面试指南(一)
- android 5.0 支持的z轴实现机制
- (15.1.3)三道值得思考的产品问题!
- C++构造与析构(9) - 默认构造函数
- PagerSlidingTabStrip 源码解析
- 第12周项目3—日期时间类
- 开机启动服务
- FPGA上的小逻辑算法总结
- 网络状态变化
- 电量变化
- 嵌入式软件开发培训笔记——u-boot-2011.09的移植
- (15.1.4)什么叫大数据?什么叫O2O?什么叫蓝海?什么叫红海?什么叫互联网思维?什么叫众筹?
- CKFinder 2.4.1清除主界面中的版权信息