美文网首页
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