一、需求
頁面頂部添加Tab條壤圃,類似微博首頁的關(guān)注和熱門兩個(gè)Tab陵霉,如下圖:
二、方案
三個(gè)實(shí)現(xiàn)要點(diǎn):
- TabLayout+FrameLayout
- 兩個(gè)Tab對(duì)應(yīng)兩個(gè)Fragment伍绳,根據(jù)TabLayout.OnTabSelectedListener的回調(diào)切換Fragment
- 不使用ViewPager
三踊挠、問題
兩個(gè)下劃線樣式問題:
- 不支持自定義寬度
- 不支持導(dǎo)圓角
四、解決
有兩種方案墨叛,最終采用了第二種:
- 使用開源庫
MagicIndicator
FlycoTabLayout
NavigationTabStrip
上面三個(gè)開源庫均支持多種形式的Tab條止毕,其中MagicIndicator支持在非ViewPager場(chǎng)景使用模蜡,另兩個(gè)庫目前不支持漠趁。 - 自定義下劃線
思路:給TabLayout的mTabStrip設(shè)置背景實(shí)現(xiàn)自定義下劃線
優(yōu)點(diǎn):可以繪制任意樣式的下劃線,線條忍疾、三角等闯传,只要你想得到
Step1:創(chuàng)建背景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.support.design.widget.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"http://隱藏原下劃線
app:tabMode="fixed"
app:tabPaddingEnd="24dp"
app:tabPaddingStart="24dp"
app:tabTextAppearance="@style/TabTextStyle"http://自定義Tab文本樣式
app:tabTextColor="@color/light_text_color" />
Step3:代碼里使用自定義下劃線卤妒,即給mStripView設(shè)置背景:
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點(diǎn)擊處理
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));//設(shè)置背景 添加自定義下劃線
tabLayout.setVisibility(VISIBLE);
}
五甥绿、遇到的問題
- java.lang.NoSuchFieldException: mIndicatorLeft | mIndicatorRight
問題:通過反射獲取SlidingTabStrip的兩個(gè)私有變量值,debug包正常運(yùn)行则披,release包報(bào)錯(cuò)找不到變量共缕。
解決辦法:在混淆文檔中去掉對(duì)widget包的混淆,即加上
-keep class android.support.design.widget.** { *; }