新手贴 请将就
效果图
没有别的东西 直接上代码
前言
tablayout 的mode 分为 scrollable 和 fixed
根据前辈的博客 https://blog.youkuaiyun.com/u013134391/article/details/70833903
发现使用后 只有mode为scrollable 是 指示器和文字是一样长 而为fill就出现问题 针对这个问题 我在前辈的基础上做了一点点修改,有问题希望大家能给为建议
为了方便大家 贴前辈代码(省的大家另开网页,若需研究原理 就去前辈那里)
public static void reflexScrol(final TabLayout tabLayout){ //了解源码得知 线的宽度是根据 tabView的宽度来设置的 tabLayout.post(new Runnable() { @Override public void run() { try { //拿到tabLayout的mTabStrip属性 LinearLayout mTabStrip = (LinearLayout) tabLayout.getChildAt(0); int dp10 = dip2px(tabLayout.getContext(), 10); for (int i = 0; i < mTabStrip.getChildCount(); i++) { View tabView = mTabStrip.getChildAt(i); //拿到tabView的mTextView属性 tab的字数不固定一定用反射取mTextView Field mTextViewField = tabView.getClass().getDeclaredField("mTextView"); mTextViewField.setAccessible(true); TextView mTextView = (TextView) mTextViewField.get(tabView); tabView.setPadding(0, 0, 0, 0); //因为我想要的效果是 字多宽线就多宽,所以测量mTextView的宽度 int width = 0; width = mTextView.getWidth(); if (width == 0) { mTextView.measure(0, 0); width = mTextView.getMeasuredWidth(); } //设置tab左右间距为10dp 注意这里不能使用Padding 因为源码中线的宽度是根据 tabView的宽度来设置的 LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tabView.getLayoutParams(); params.width = width ; params.leftMargin = dp10; params.rightMargin = dp10; tabView.setLayoutParams(params); tabView.invalidate(); } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }); }
使用过程中发现 上述的问题,个人觉得,是因为Mode为fixed的时候每个TabView的weight都为1,margin设置失效,修改时
可以先拿到TabView的宽度减去TextView宽度除以2,然后在设置margin,代码实现
public static void reflexFixed(final TabLayout tabLayout){ //了解源码得知 线的宽度是根据 tabView的宽度来设置的 tabLayout.post(new Runnable() { @Override public void run() { try { //拿到tabLayout的mTabStrip属性 LinearLayout mTabStrip = (LinearLayout) tabLayout.getChildAt(0); for (int i = 0; i < mTabStrip.getChildCount(); i++) { View tabView = mTabStrip.getChildAt(i); //拿到tabView的mTextView属性 tab的字数不固定一定用反射取mTextView Field mTextViewField = tabView.getClass().getDeclaredField("mTextView"); mTextViewField.setAccessible(true); TextView mTextView = (TextView) mTextViewField.get(tabView); tabView.setPadding(0, 0, 0, 0); //因为我想要的效果是 字多宽线就多宽,所以测量mTextView的宽度 int width = 0; width = mTextView.getWidth(); if (width == 0) { mTextView.measure(0, 0); width = mTextView.getMeasuredWidth(); } int margin = (tabView.getWidth()-width)/2; int dp10 = px2dip(tabLayout.getContext(), margin); Log.e("fhxxMargin","text"+ width + " tab " +tabView.getWidth() + " get" + margin + " 间距"+ dp10); //设置tab左右间距 注意这里不能使用Padding 因为源码中线的宽度是根据 tabView的宽度来设置的 LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tabView.getLayoutParams(); params.width = width ; params.leftMargin = margin; params.rightMargin = margin; tabView.setLayoutParams(params); tabView.invalidate(); } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }); }
修改过后 就可以设置mode为fill的情况了
最后贴上两个dp和px的转换方法
/** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } /** * 根据手机的分辨率从 px(像素) 的单位 转成为 dp */ public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); }
仅供参考 ,大佬留情