PagerSlidingTabStrip源码解析
2017-06-27 17:44
357 查看
PagerSlidingTabStrip源码解析
集成使用
导包
在Android Studio中,直接在build.gradle文件中增加如下依赖:dependencies { compile 'com.astuetz:pagerslidingtabstrip:1.0.1' }
XML文件布局
在XML文件中使用时,PagerSlidingTabStrip通常声明在ViewPager的上方.<com.yunos.sprd.appstore.widget.PagerSlidingTabStrip android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="@dimen/title_page_indicator_height" android:background="@color/colorCCFF7E3B" android:textColor="@android:color/white" android:textSize="@dimen/tab_title_textsize" android:focusable="true" app:pstsActivateTextColor="@color/colorFFFFFFFF" app:pstsDeactiveTextColor="@color/color99FFFFFF" app:pstsIndicatorColor="@android:color/white" app:pstsIndicatorHeight="@dimen/psts_indicator_height" app:pstsShouldExpand="true" app:pstsTabSwitch="true" app:pstsTabPaddingLeftRight="0px"/> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" />
Activity或Fragment中初始化
在Activity的onCreate方法中(或者Fragment的onCreateView)中,绑定PagerSlidingTabStrip到ViewPager.// Initialize the ViewPager and set an adapter ViewPager pager = (ViewPager) findViewById(R.id.pager); pager.setAdapter(new TestAdapter(getSupportFragmentManager())); // Bind the tabs to the ViewPager PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs); tabs.setViewPager(pager); // set OnPageChangeListener on PagerSlidingTabStrip instead of ViewPager tabs.setOnPageChangeListener(mPageChangeListener);
源码分析
构造函数
PagerSlidingTabStrip在构造函数中主要是对变量进行初始化:public PagerSlidingTabStrip(Context context) { this(context, null); } public PagerSlidingTabStrip(Context context, AttributeSet attrs) { this(context, attrs, 0); } public PagerSlidingTabStrip(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 允许组件中的控件去充满自己 setFillViewport(true); setWillNotDraw(false); // 定义一个横向的LinearLayout tabsContainer = new LinearLayout(context); tabsContainer.setOrientation(LinearLayout.HORIZONTAL); tabsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); addView(tabsContainer); DisplayMetrics dm = getResources().getDisplayMetrics(); // 获取预设的属性值 scrollOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, scrollOffset, dm); indicatorHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, indicatorHeight, dm); underlineHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, underlineHeight, dm); dividerPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerPadding, dm); tabPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tabPadding, dm); dividerWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerWidth, dm); tabTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm); // get system attrs (android:textSize and android:textColor) TypedArray a = context.obtainStyledAttributes(attrs, ATTRS); tabTextSize = a.getDimensionPixelSize(0, tabTextSize); tabTextColor = a.getColor(1, tabTextColor); a.recycle(); // 获取自定义属性值 a = context.obtainStyledAttributes(attrs, R.styleable.PagerSlidingTabStrip); indicatorColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsIndicatorColor, indicatorColor); underlineColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsUnderlineColor, underlineColor); dividerColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsDividerColor, dividerColor); indicatorHeight = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsIndicatorHeight, indicatorHeight); underlineHeight = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsUnderlineHeight, underlineHeight); dividerPadding = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsDividerPadding, dividerPadding); tabPadding = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsTabPaddingLeftRight, tabPadding); tabBackgroundResId = a.getResourceId(R.styleable.PagerSlidingTabStrip_pstsTabBackground, tabBackgroundResId); shouldExpand = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsShouldExpand, shouldExpand); scrollOffset = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsScrollOffset, scrollOffset); textAllCaps = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsTextAllCaps, textAllCaps); tabSwitch = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsTabSwitch, tabSwitch); tabActiveTextColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsActivateTextColor, tabActiveTextColor); tabDeactiveTextColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsDeactiveTextColor, tabDeactiveTextColor); a.recycle(); // Tab的滑动指示器画笔 rectPaint = new Paint(); rectPaint.setAntiAlias(true); rectPaint.setStyle(Style.FILL); // 垂直分隔线的画笔 dividerPaint = new Paint(); dividerPaint.setAntiAlias(true); dividerPaint.setStrokeWidth(dividerWidth); // 设置默认的Tab属性 defaultTabLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); // 设置均分的tab属性 expandedTabLayoutParams = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f); if (locale == null) { locale = getResources().getConfiguration().locale; } }
onDraw方法实现
中文注释的onDraw函数源码如下:@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (isInEditMode() || tabCount == 0) { return; } final int height = getHeight(); // 设置滑动指示器画笔的颜色 rectPaint.setColor(indicatorColor); // 获取当前的Tab,确定Tab的左右坐标,在当前Tab的下面绘制指示器 View currentTab = tabsContainer.getChildAt(currentPosition); float lineLeft = currentTab.getLeft(); float lineRight = currentTab.getRight(); // 如果ViewPager存在滑动偏移量,则需要根据偏移量来更新Tab的左右坐标 // currentPositionOffset为float,介于0~1,代表相对于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); } // 绘制当前tab下面的指示器 canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height, rectPaint); // 绘制整个导航栏 rectPaint.setColor(underlineColor); canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint); // 绘制垂直分隔线 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); } }
联动实现
接下来,我们进入绘制的关键代码。PagerSlidingTabStrip是如何与ViewPager实现滑动联动的.PagerSlidingTabStrip之所以能实现和ViewPager的联动,是因为它引用了ViewPager的OnPageChangeListener.关键代码:
public void setViewPager(ViewPager pager) { this.pager = pager; if (pager.getAdapter() == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } pager.addOnPageChangeListener(pageListener); notifyDataSetChanged(); }
从代码中,我们可以分析出:PagerSlidingTabStrip保持了ViewPager的句柄,同时为ViewPager设置了一个OnPageChangeListener接口.
这个接口的中文注释源码如下:
/** * delegatePageListener是用户设置的OnPageChangeListener,因为不响应滑动实现,我将其代码删除了. */ private class PageListener implements OnPageChangeListener { /** * 这个方法在屏幕滚动时不断被调用 * @param position 当前页面. * @param positionOffset 当前页面的偏移比例.如果页面向右翻动,这个值不断变大,最后在趋近于1的情况下突变为0.如果页面向左翻动,这个值不断变小,最后Wie0. * @param positionOffsetPixels 当前页面因为滑动偏移了多少像素. */ @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { currentPosition = position; currentPositionOffset = positionOffset; // 根据View的位置和偏移量,来同步LinearLayout容器中tab的位置和偏移量 scrollToChild(position, (int) (positionOffset * tabsContainer.getChildAt(position).getWidth())); invalidate(); } @Override public void onPageScrollStateChanged(int state) { if (state == ViewPager.SCROLL_STATE_IDLE) { scrollToChild(pager.getCurrentItem(), 0); } } @Override public void onPageSelected(int position) { if (tabSwitch) { updateActivateTab(position); } } }
相关文章推荐
- Android 开源项目源码解析 -->PagerSlidingTabStrip 源码解析(十八)
- PagerSlidingTabStrip 源码解析
- PagerSlidingTabStrip 源码解析
- PagerSlidingTabStrip源码解析
- XlistView,Xml解析,PagerSlidingTabStrip
- PagerSlidingTabStrip源码分析
- PagerSlidingTabStrip源码分析及扩展
- 【Android开源项目分析】TAB导航栏PagerSlidingTabStrip的使用和源码分析
- 足球控(1) PagerSlidingTabStrip用法及解析
- PagerSlidingTabStrip,酷炫的ViewPager的滑动导航,使用及解析
- 使用最广泛的Android爬虫指示器PagerSlidingTabStrip遇到的相关问题的解决,并源码修改
- android带有下划线的viewpager标题PagerSlidingTabStrip
- 【Android界面实现】使用PagerSlidingTabStrip实现滑动标签同步的ViewPager效果
- PagerSlidingTabStrip使用问题大合集
- PagerSlidingTabStrip的使用
- ActionBar + ViewPager(PagerSlidingTabStrip)
- PagerSlidingTabStrip介绍及使用,让ViewPager更绚丽
- 今天又发现个很炫的UI框架 PagerSlidingTabStrip
- PagerSlidingTabStrip实现横划
- pagerslidingtabstrip的用法