针对PagerSlidingTabStrip 1.3的功能改善(滑动条长度根据标题长度动态变化)

一般入门android以后,想提高自己的android水平,个人认为最好的方式就是大量阅读优秀的开源App,例如开源中国的App,我android入门后就有人推荐我去看,真是收益非浅,想起刚开始写代码的风格,命名方式就是毫无章法,如果换个人来看你的代码估计分分钟想打写代码的人,换个脾气好的,不打你,就生闷气,最后闷出精神疾病也说不好 哈哈 所以严谨代码风格非常重要(说实话,在真正开发中,我没有贯彻得很好,说什么进度赶的都是屁话,就是一个字懒)

好了,废话不多说~ 这章是讲PagerSlidingTabStrip这个控件,但是我前面非扯开源中国是为何呢?不是别的,就是因为我第一次看到这个控件的地方就是在开源中国看到它用的~

也许有人没看过控件,它其实就是配合viewpage,然后给在当前viewpage的上方显示一个标题,然后标题下方有个滑动块,如果不清楚,看下下图的效果图(未改善之前)



发现这个滑动条并不能跟标题栏对齐,但是UI效果是要滑动块和标题对齐,切滑动的时候,根据下一个滑动目标的标题长度动态得改变其长度,效果如下(改善之后)


是不是很多市面上的app都采用了这种风格的控件?最明显的app就是一些新闻类的app,例如网易新闻,今日头条都是这种效果,不过他们做得更绚丽,但究其本质都是一样的,都是监听viewpage的偏移量然后达到一些动态效果

currentPositionOffset 这个就是viewPage的偏移量,然后监听viewpage的滑动即可得到,代码如下

  /**
     * 设置ViewPager
     *
     * @param viewPager ViewPager
     */
    public void setViewPager(ViewPager viewPager) {
        if (disableViewPager)
            return;
        this.viewPager = viewPager;
        this.viewPager.addOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                selectedTab(position);
                if (onPageChangeListener != null) {
                    onPageChangeListener.onPageSelected(position);
                }
                if (listener != null)
                    listener.onChanged(position);
            }

            @Override
            public void onPageScrolled(int nextPagePosition,
                                       float positionOffset, int positionOffsetPixels) {
                ViewGroup tabsLayout = getTabsLayout();
                if (nextPagePosition < tabsLayout.getChildCount()) {
                    View view = tabsLayout.getChildAt(nextPagePosition);
                    if (view != null) {
                        currentPosition = nextPagePosition;
                        currentPositionOffset = positionOffset;
                        scrollToChild(nextPagePosition,
                                (int) (positionOffset * view.getWidth()));
                        isAllowDraw = true;
                        invalidate();
                    }
                }
                if (onPageChangeListener != null) {
                    onPageChangeListener.onPageScrolled(nextPagePosition,
                            positionOffset, positionOffsetPixels);
                }
            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
                if (onPageChangeListener != null) {
                    onPageChangeListener.onPageScrollStateChanged(arg0);
                }
            }
        });
        requestLayout();
    }
得到当前滑动的偏移量,然后就进行绘制

在view进行动态绘制,关绘制滑块键代码如下:

 protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (disableViewPager)
            return;
        /* 绘制滑块 */
        if (isAllowDraw) {
            ViewGroup tabsLayout = getTabsLayout();
            if (tabsLayout != null && tabsLayout.getChildCount() > 0
                    && slidingBlockDrawable != null) {
                View currentTab = tabsLayout.getChildAt(currentPosition);
                View nextTab = tabsLayout.getChildAt(currentPosition + 1);
                float tabStrinpleft;
                float nextTabStrinpleft;
                float slidingBlockLeft;
                float slidingBlockRight;
                float nextTabLeft = 0;
                float nextTabRight = 0;
                if (currentTab != null) {
                    if (allowAlignmentl) {
                        tabStrinpleft = ((RelativeLayout) currentTab).getChildAt(0).getLeft();
                        slidingBlockLeft = currentTab.getLeft() + tabStrinpleft;
                        slidingBlockRight = currentTab.getRight() - tabStrinpleft;
                        if (currentPositionOffset > 0f
                                && currentPosition < tabsLayout.getChildCount() - 1) {
                            if (nextTab != null) {
                                nextTabStrinpleft = ((RelativeLayout) nextTab).getChildAt(0).getLeft();
                                nextTabLeft = nextTab.getLeft() + nextTabStrinpleft;
                                nextTabRight = nextTab.getRight() - nextTabStrinpleft;
                            }
                            slidingBlockLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset)
                                    * slidingBlockLeft);
                            slidingBlockRight = (currentPositionOffset
                                    * nextTabRight + (1f - currentPositionOffset)
                                    * slidingBlockRight);
                        } else {

                        }
                    } else {
                        slidingBlockLeft = currentTab.getLeft();
                        slidingBlockRight = currentTab.getRight();
                        if (currentPositionOffset > 0f
                                && currentPosition < tabsLayout.getChildCount() - 1) {
                            nextTab = tabsLayout.getChildAt(currentPosition + 1);
                            if (nextTab != null) {
                                nextTabLeft = nextTab.getLeft();
                                nextTabRight = nextTab.getRight();
                                slidingBlockLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset)
                                        * slidingBlockLeft);
                                slidingBlockRight = (currentPositionOffset
                                        * nextTabRight + (1f - currentPositionOffset)
                                        * slidingBlockRight);
                            }
                        }
                    }
                    slidingBlockDrawable.setBounds((int) slidingBlockLeft, 0,
                            (int) slidingBlockRight, getHeight());
                    slidingBlockDrawable.draw(canvas);
                }
            }
        }
    }

现在讲讲,关于如何通过偏移量,然后动态得计算出该绘制的坐标

首先获取滑块控件,即slidingBlockDrawable,获取之后,我们算出该绘制的点,然后调用setBounds(int left, int top, int right, int bottom) 即可

绘制的时候,只需要知道left,right的坐标点就行,即slidingBlockLeft 和slidingBlockRight就行

接下来就是很重要的步骤,就是通过偏移量来计算出当前的slidingBlockLeft和slidingBlockRight

在滑动时,先得到当前的slidingBlockLeft和slidingBlockRight,然后计算需要滑向下一个的left和right,即nextTabLeft和nextTabRight,然后根据偏移量 通过公式

slidingBlockLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset)
        * slidingBlockLeft);
slidingBlockRight = (currentPositionOffset
        * nextTabRight + (1f - currentPositionOffset)
        * slidingBlockRight);

计算出slidingBlockLeft和slidingBlockRight,最后

slidingBlockDrawable.setBounds((int) slidingBlockLeft, 0,
        (int) slidingBlockRight, getHeight());
slidingBlockDrawable.draw(canvas);
即可


这个控件使用起来没问题,但是使用的时候需要注意一点,在每次view重新绘制的时候一定要记得强制重绘滑块,不然滑块会没有,在demo有写使用注意


后来在github看到了关于这个控件的改善,是滑动时 对标题字进行渐变 ,点击打开链接,如果喜欢它的风格可以去他那里下


好了,给这个控件的下载地址点击打开链接 (Gradle构建方式,所以最好用as打开)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值