• TabLayout中Indicator的样式修改


    最近写一个项目的时候用到了TabLayout,其中Indicator只是固定的一条横线,样式只能修改Color和Height,没有办法改变形状和宽度等其他信息。

    经过查看TabLayout类的源码,发现了其存在一个私有的内部类SlidingTabStrip,这个类继承自LinearLayout,而Indicator就是在此类中进行绘制的。

    @Override  
    public void draw(Canvas canvas) {  
        super.draw(canvas);  
    
        // Thick colored underline below the current selection  
        if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) {  
            canvas.drawRect(mIndicatorLeft, getHeight() - mSelectedIndicatorHeight,  
                    mIndicatorRight, getHeight(), mSelectedIndicatorPaint);  
        }  
    }
    

    在它的onDraw方法中,可以看到绘制的是一个Rect,并且宽度是根据mIndicatorLeft和mIndicatorRight这两个成员变量来决定的,再往上看会发现这两个变量的值是实时计算出来的。

    rivate void updateIndicatorPosition() {  
        final View selectedTitle = getChildAt(mSelectedPosition);  
        int left, right;  
    
        if (selectedTitle != null && selectedTitle.getWidth() > 0) {  
            left = selectedTitle.getLeft();  
            right = selectedTitle.getRight();  
    
            if (mSelectionOffset > 0f && mSelectedPosition < getChildCount() - 1) {  
                // Draw the selection partway between the tabs  
                View nextTitle = getChildAt(mSelectedPosition + 1);  
                left = (int) (mSelectionOffset * nextTitle.getLeft() +  
                        (1.0f - mSelectionOffset) * left);  
                right = (int) (mSelectionOffset * nextTitle.getRight() +  
                        (1.0f - mSelectionOffset) * right);  
            }  
        } else {  
            left = right = -1;  
        }  
    
        setIndicatorPosition(left, right);  
    }  
    
    private void setIndicatorPosition(int left, int right) {  
        if (left != mIndicatorLeft || right != mIndicatorRight) {  
            // If the indicator's left/right has changed, invalidate  
            mIndicatorLeft = left;  
            mIndicatorRight = right;  
            ViewCompat.postInvalidateOnAnimation(this);  
        }  
    }

    这里大概意思是根据当前选中的SlidingTabStrip的Child的宽度来得出mIndicatorLeft和mIndicatorRight的值,而这个Child我觉得其实就相当于Tab,这样一来如果想简单的修改一下Indicator的宽度,其实可以稍微给Child加点Margin就可以了。这个类和其对象在SlidingTabStrip都是私有的,可以通过反射的方式进行修改。

    我的思路是,首先得到TabLayout的Class对象,然后得到私有成员变量mSlidingTabStrip的Field,通过Field得到值强转为LinearLayout,之后只需要遍历LinearLayout中所有的Child为其增加Margin即可,实现代码如下:

    Class<?> tablayout = tl_main.getClass();  
    Field tabStrip = tablayout.getDeclaredField("mTabStrip");  
    tabStrip.setAccessible(true);  
    LinearLayout ll_tab= (LinearLayout) tabStrip.get(tl_main);  
    for (int i = 0; i < ll_tab.getChildCount(); i++) {  
        View child = ll_tab.getChildAt(i);  
        child.setPadding(0,0,0,0);  
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT,1);  
        params.setMarginStart(DensityUtil.dip2px(20f));  
        params.setMarginEnd(DensityUtil.dip2px(20f));  
        child.setLayoutParams(params);  
        child.invalidate();  
    }

    最后得到效果如图:


     

    至于Indicator的形状,因为在onDraw方法中绘制的是Rect,只靠反射是改动不了的,我觉得可以自定义一个类继承SlidingTabStrip重写其onDraw方法或者直接弃用TabLayout自带的Indicator,自己写一个IndicatorView将其和TabLayout放入FrameLayout,使IndicatorView响应TabLayout的Tab切换事件就好。



  • 相关阅读:
    浙江理工2015.12校赛-F Landlocked
    浙江理工2015.12校赛-G Jug Hard
    浙江理工2015.12校赛-B 七龙珠
    浙江理工2015.12校赛-A
    Smallest Bounding Rectangle
    Just a Hook(HDU1698 线段树的简单应用)
    覆盖的面积(HDU 1255 线段树)
    Prime Query (ZOJ 3911 线段树)
    JuQueen(线段树 lazy)
    2015弱校联盟(2)
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/7339741.html
Copyright © 2020-2023  润新知