一、需求

页面顶部添加Tab条,类似微博首页的关注和热门两个Tab,如下图:

20d206267e20?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

Screenshot_2017-11-02-21-47-09-751_com.sina.weibo.png

二、方案

三个实现要点:

TabLayout+FrameLayout

两个Tab对应两个Fragment,根据TabLayout.OnTabSelectedListener的回调切换Fragment

不使用ViewPager

三、问题

两个下划线样式问题:

不支持自定义宽度

不支持导圆角

四、解决

有两种方案,最终采用了第二种:

使用开源库

MagicIndicator

FlycoTabLayout

NavigationTabStrip

上面三个开源库均支持多种形式的Tab条,其中MagicIndicator支持在非ViewPager场景使用,另两个库目前不支持。

自定义下划线

思路:给TabLayout的mTabStrip设置背景实现自定义下划线

优点:可以绘制任意样式的下划线,线条、三角等,只要你想得到

Step1:创建背景Drawable,在onDraw方法中完成自定义的下划线绘制:

public class IndicatorDrawable extends Drawable {

private static final int INDICATOR_MARGIN = ScreenUtils.dp2px(24);

private static final int INDICATOR_HEIGHT = ScreenUtils.dp2px(3);

private static final int INDICATOR_RADIUS = ScreenUtils.dp2px(1.5f);

private View view;

private Paint paint;

public IndicatorDrawable(View view) {

this.view = view;

this.paint = new Paint();

paint.setColor(view.getContext().getResources().getColor(R.color.main_color));

}

@Override

public void draw(@NonNull Canvas canvas) {

int mIndicatorLeft = getIntValue("mIndicatorLeft");

int mIndicatorRight = getIntValue("mIndicatorRight");

int radius = INDICATOR_RADIUS;

if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) {

canvas.drawRoundRect(new RectF(mIndicatorLeft + INDICATOR_MARGIN, view.getHeight() - INDICATOR_HEIGHT, mIndicatorRight - INDICATOR_MARGIN, view.getHeight()), radius, radius, paint);

}

}

private int getIntValue(String name) {

try {

Field f = view.getClass().getDeclaredField(name);

f.setAccessible(true);

Object obj = f.get(view);

return (Integer) obj;

} catch (Exception e) {

e.printStackTrace();

}

return 0;

}

@Override

public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {

}

@Override

public void setColorFilter(@Nullable ColorFilter colorFilter) {

}

@Override

public int getOpacity() {

return PixelFormat.UNKNOWN;

}

}

Step2:xml中隐藏掉TabLayout原有的下划线:

android:id="@+id/tab_layout"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_centerHorizontal="true"

android:layout_gravity="center_horizontal"

android:gravity="center"

android:visibility="gone"

app:tabBackground="@null"

app:tabGravity="center"

app:tabIndicatorColor="@color/main_color"

app:tabIndicatorHeight="0dp"//隐藏原下划线

app:tabMode="fixed"

app:tabPaddingEnd="24dp"

app:tabPaddingStart="24dp"

app:tabTextAppearance="@style/TabTextStyle"//自定义Tab文本样式

app:tabTextColor="@color/light_text_color" />

Step3:代码里使用自定义下划线,即给mStripView设置背景:

private void initTabLayout(FeedHotVideoConfig config) {

tabLayout.removeAllTabs();

tabLayout.clearOnTabSelectedListeners();

View view = LayoutInflater.from(getContext()).inflate(R.layout.feed_tab, null);

tvFollow = (TextView) view.findViewById(R.id.tv_tab);

noticeFollow = view.findViewById(R.id.view_notice);

tabLayout.addTab(tabLayout.newTab().setCustomView(view).setTag(TAG_FOLLOW));//自定义Tab样式

tabLayout.addTab(tabLayout.newTab().setText(config.info.name).setTag(TAG_VIDEO));

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {

@Override

public void onTabSelected(TabLayout.Tab tab) {

//Tab点击处理

int tag = (int) tab.getTag();

if (listener != null) {

listener.onTabSelected(tag);

}

refreshTab(tag);

}

@Override

public void onTabUnselected(TabLayout.Tab tab) {

}

@Override

public void onTabReselected(TabLayout.Tab tab) {

}

});

View tabStripView = tabLayout.getChildAt(0);

tabStripView.setBackground(new IndicatorDrawable(tabStripView));//设置背景 添加自定义下划线

tabLayout.setVisibility(VISIBLE);

}

五、遇到的问题

java.lang.NoSuchFieldException: mIndicatorLeft | mIndicatorRight

问题:通过反射获取SlidingTabStrip的两个私有变量值,debug包正常运行,release包报错找不到变量。

解决办法:在混淆文档中去掉对widget包的混淆,即加上

-keep class android.support.design.widget.** { *; }

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐