美文网首页
Tablayout的tab指示器需要自行定制的时候黑人微笑问号哈

Tablayout的tab指示器需要自行定制的时候黑人微笑问号哈

作者: 莫不如哦 | 来源:发表于2017-11-10 16:22 被阅读0次
前两天研究了一个新的玩意 Tablayout 需求上是这样的 要求tablayout带着原生的红线指示器,并且要根据tab内容调整红线的长度,本来这么个问题不算问题,虽然Tablayout本身没有支持设置红线的长度,但是无数前辈们已经写好了工具类,大体都是用反射 修改tab的宽度,因为红线是跟tab的宽度变化而变化的,我成功改好红线跟文字的需求后,要求在红线下面在加一个小三角。。。两个指示器,很烦 先上下成品图 Slidingtablayout.gif

具体思路就是继承了Tablayout 然后动的时候重新绘制一个三角在下边

/**
 * 支持自定义下标,自定义tab宽度
 * <p>
 *
 * @author 郭凯奇
 * @date 2017/10/31 21:18.
 */
public class SlidingTabLayout extends TabLayout {
    /**
     * 自定义指示器
     */
    private Bitmap mSlideIcon;
    /**
     * 滑动过程中指示器偏移量
     */
    private int mTranslationX;
    /**
     * 指示器初始Y偏移量
     */
    private int mInitTranslationY;

    int[] textwidth;
    LinearLayout mTabStrip;
    private boolean ishave = false;

    public boolean ishave() {
        return ishave;
    }

    public void setIshave(boolean ishave) {
        this.ishave = ishave;
    }

    public void setTabWidth(int[] tabWidth, LinearLayout mTabStrip) {
        this.textwidth = tabWidth;
        this.mTabStrip = mTabStrip;
        initTranslationParams(mTabStrip);


    }

    public SlidingTabLayout(Context context) {
        super(context);
    }

    public SlidingTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mSlideIcon = BitmapFactory.decodeResource(getResources(), R.drawable.home_jiaobiao);
    }

    /**
     * 重绘下标
     */
    public void redrawIndicator(int position) {
        mTranslationX = 0;
        if (textwidth == null) {
            invalidate();
            return;
        }
        if (position == 0) {
            mTranslationX = textwidth[position] / 2;
            invalidate();
            return;
        }
        for (int i = 0; i <= position; i++) {
            mTranslationX += textwidth[i];
            if (i == position) {
                mTranslationX = mTranslationX - (textwidth[i] / 2);
            }

        }
        invalidate();
    }

    @Override
    public int getScrollIndicators() {
        return super.getScrollIndicators();
    }

    public Field getmTabStrip() {
        Class<?> tabLayout = TabLayout.class;
        Field tabStrip = null;
        try {
            tabStrip = tabLayout.getDeclaredField("mTabStrip");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return tabStrip;
    }

    /**
     * 绘制指示器
     */
    @Override
    protected void dispatchDraw(Canvas canvas) {
        if (mSlideIcon == null) {
            return;
        }
        if (ishave) {
            canvas.save();
            // 平移到正确的位置,修正tabs的平移量
            Log.e("invaaaaaa", mTranslationX + "");
            canvas.translate(mTranslationX - this.mSlideIcon.getWidth() / 2, 200);
            canvas.drawBitmap(this.mSlideIcon, 0, 0, null);
            canvas.restore();
            super.dispatchDraw(canvas);
            return;

        }
        canvas.save();
        // 平移到正确的位置,修正tabs的平移量
        Log.e("invaaaaaa", mTranslationX + "");
        canvas.translate(mTranslationX - this.mSlideIcon.getWidth() / 2, this.mInitTranslationY);
        canvas.drawBitmap(this.mSlideIcon, 0, 0, null);
        canvas.restore();
        super.dispatchDraw(canvas);
    }

    /**
     * 初始化三角下标的坐标参数
     */
    private void initTranslationParams(LinearLayout llTab) {
        if (mSlideIcon == null) {
            return;
        }
        tabWidth = textwidth[0];
        View firstView = llTab.getChildAt(0);
        if (firstView != null) {
            this.mInitTranslationY = (getBottom() - getTop() - this.mSlideIcon.getHeight());
            this.mTranslationX = textwidth[0] / 2;
            invalidate();
        }
    }

}

然后反射修改长度什么的

public class TabLayoutUtil {

    //Slidingtablayout的专属适配器
    public static void slidingScrol(final Context context, final SlidingTabLayout tabLayout) {
        tabLayout.post(new Runnable() {
            @Override
            public void run() {

                try {
                    //拿到tabLayout的mTabStrip属性
                    Field mTabStripField = tabLayout.getmTabStrip();
                    mTabStripField.setAccessible(true);

                    Log.d("setIndicatorWidth", "mTabStripField:" + mTabStripField);
                    LinearLayout mTabStrip = (LinearLayout) mTabStripField.get(tabLayout);

                    int dp10 = dip2px(context,10);
                    int[] textwidth = new int[mTabStrip.getChildCount()];
                    for (int i = 0; i < mTabStrip.getChildCount(); i++) {
                        View tabView = mTabStrip.getChildAt(i);

                        //拿到tabView的mTextView属性
                        Field mTextViewField = tabView.getClass().getDeclaredField("mTextView");
                        mTextViewField.setAccessible(true);
                        TextView mTextView = (TextView) mTextViewField.get(tabView);
                        //因为我想要的效果是   字多宽线就多宽,所以测量mTextView的宽度
                        int width = 0;
                        width = mTextView.getWidth();
                        if (width == 0) {
                            mTextView.measure(0, 0);
                            width = mTextView.getMeasuredWidth();
                        }
                        Log.d("setIndicatorWidth", "mTextView.width:" + width);
                        //设置tab左右间距为10dp  注意这里不能使用Padding 因为源码中线的宽度是根据 tabView的宽度来设置的
                        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tabView.getLayoutParams();
                        params.width = width;
                        Log.d("setIndicatorWidth", "tabView.width:" + params.width);
                        params.leftMargin = dp10;
                        params.rightMargin = dp10;
                        tabView.setLayoutParams(params);
                        tabView.invalidate();
                        textwidth[i]=width+dp10+dp10;
                        tabView.setPadding(0, dip2px(context,20), 0, 0);
                    }
                    tabLayout.setTabWidth(textwidth,mTabStrip);

                } catch (NoSuchFieldException e) {
                    Log.d("setIndicatorWidth", "NoSuchFieldException:" + e.getMessage());
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    Log.d("setIndicatorWidth", "IllegalAccessException:" + e.getMessage());
                    e.printStackTrace();
                }
            }
        });
    }
    private static int dip2px(Context context, float dipValue)
    {
        Resources r = context.getResources();
        return (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, dipValue, r.getDisplayMetrics());
    }
}

      topTabLayout = (SlidingTabLayout) findViewById(R.id.tablayout);
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        viewPager.setAdapter(new TabFragmentAdapter(fragments, strings, getSupportFragmentManager(), this));
        topTabLayout.setupWithViewPager(viewPager);
        topTabLayout.setTabTextColors(getResources().getColor(R.color.radiobutton), getResources().getColor(R.color.radiobuttonzhong));
        TabLayoutUtil.slidingScrol(this, topTabLayout);
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                topTabLayout.redrawIndicator(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });

贴的这个代码是三角是不能滑动的,只会瞬移到下一个tab的中间
想滑动的滑需要在viewpager的onscroll方法里去做一些操作
留下来是为了防止我忘了
有想看 的联系我 我给demo

相关文章

网友评论

      本文标题:Tablayout的tab指示器需要自行定制的时候黑人微笑问号哈

      本文链接:https://www.haomeiwen.com/subject/dxbbmxtx.html