众所周知,TabLayout 特别好用,项目里面需要自定义Tab字体和Indicator
image
想到的方案有两个:
一是获取系统默认TabItem的TextView,然后动态设置字体和背景来实现,后来发现textSize属性不生效,app:tabTextAppearance 满足不了需求。
二是自定义View,即Tablayout.Tab.setCustomView()。写了demo,实现了需求。整理一下代码重写TabLayout,即插即用,打算后期丰富API,完善过渡动画等。
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.meishubao.client.R;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: 自定义顶部Tab导航
* @Author: dengbin
* @CreateDate: 2020/3/20 18:02
* @UpdateUser: dengbin
* @UpdateDate: 2020/3/20 18:02
* @UpdateRemark: 更新说明
*/
public class MTabLayout extends TabLayout {
// 所绑定的 ViewPager 的 Adapter
private PagerAdapter pagerAdapter;
// title 集合
private int tmpTitleInitPos;
private List<CharSequence> titleStringList = new ArrayList<>();
// 监听 Adapter 数据变化
private DataSetObserver dataSetObserver = new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
updateTitleText();
}
@Override
public void onInvalidated() {
super.onInvalidated();
updateTitleText();
}
};
private ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() {
int currentPos; // 上一次选中的页面
boolean posChanged; // 页面有所切换
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
Tab tab0 = getTabAt(arg0);
Tab tab1 = getTabAt(arg0 + 1);
animationTab(tab0, arg1);
animationTab(tab1, 1f - arg1);
}
@Override
public void onPageSelected(int i) {
posChanged = i != currentPos;
if (posChanged) {
setTabText(getTabAt(currentPos), false);
setTabText(getTabAt(i), true);
}
currentPos = i;
}
@Override
public void onPageScrollStateChanged(int i) {
if (i != ViewPager.SCROLL_STATE_IDLE || !posChanged)
return;
resetTab(currentPos);
}
};
public MTabLayout(Context context) {
this(context, null);
}
public MTabLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
// 重写该方法,实现 setCustomView
@NonNull
@Override
public Tab newTab() {
Tab tab = super.newTab();
View view = LayoutInflater.from(getContext()).inflate(R.layout.item_gallery_tab, null);
tab.setCustomView(view);
if (titleStringList.size() > 0 && tmpTitleInitPos < titleStringList.size()) {
CharSequence cs = titleStringList.get(tmpTitleInitPos++);
TextView tv = view.findViewById(R.id.tab_tv);
tv.setText(cs);
}
if (tmpTitleInitPos == 1) { // 初始化选中第一个
setTabText(tab, true);
}
if (tmpTitleInitPos >= titleStringList.size()) {
titleStringList.clear();
tmpTitleInitPos = 0;
}
return tab;
}
@Override
public void setupWithViewPager(@Nullable ViewPager viewPager) {
super.setupWithViewPager(viewPager);
if (viewPager == null)
return;
pagerAdapter = viewPager.getAdapter();
if (pagerAdapter == null) {
// 监听 ViewPager 的 Adapter 变化
viewPager.addOnAdapterChangeListener((viewPager1, pagerAdapter, pagerAdapter1) -> {
if (this.pagerAdapter != null)
this.pagerAdapter.unregisterDataSetObserver(dataSetObserver);
this.pagerAdapter = pagerAdapter1;
if (this.pagerAdapter != null)
registerDataSetObserver();
});
} else {
registerDataSetObserver();
}
// 监听 ViewPager 滑动实现过渡效果
viewPager.addOnPageChangeListener(pageChangeListener);
}
// 注册数据监听
private void registerDataSetObserver() {
pagerAdapter.registerDataSetObserver(dataSetObserver);
}
// 更新 title 文本,保存到集合
private void updateTitleText() {
int adapterCount = pagerAdapter.getCount();
int curItem;
for (curItem = 0; curItem < adapterCount; ++curItem) {
CharSequence title = pagerAdapter.getPageTitle(curItem);
titleStringList.add(TextUtils.isEmpty(title) ? "" : title);
}
}
private void animationTab(Tab tab, float per) {
if (tab == null || tab.getCustomView() == null)
return;
RelativeLayout rl = (RelativeLayout) tab.getCustomView();
View view = rl.findViewById(R.id.tab_bg_view);
view.setAlpha(1f - per);
}
private void setTabText(Tab tab, boolean selected) {
animationTab(tab, selected ? 0f : 1f);
if (tab == null || tab.getCustomView() == null)
return;
RelativeLayout rl = (RelativeLayout) tab.getCustomView();
TextView tv = rl.findViewById(R.id.tab_tv);
tv.setTypeface(Typeface.defaultFromStyle(selected ? Typeface.BOLD : Typeface.NORMAL));
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, selected ? 22f : 14f);
tv.setTextColor(tv.getResources().getColor(selected ? R.color.msb_text_black : R.color.msb_text_gray));
}
private void resetTab(int currentPos) {
for (int i = 0; i < getTabCount(); i++)
setTabText(getTabAt(i), i == currentPos);
}
}
网友评论