我們先來看看效果圖

從效果圖中可以看出V2.0和V1.0的區(qū)別
V2.0的Tab UI是可以實(shí)現(xiàn)高度定制的,上面的效果圖中Tab UI共有三種樣式。
V1.0的Tab UI是定死的
實(shí)現(xiàn)
項(xiàng)目的整體架構(gòu)基本沒變,不了解項(xiàng)目架構(gòu)的可以先看看V1.0的文章(http://www.itdecent.cn/p/7cccb5c054da#)
V2.0相對(duì)于V1.0來說就是刪除了Tab類,新增了一個(gè)抽象類AbsTab,同時(shí)修改了BaseAdapter類的邏輯,下面我們先來看看AbsTab類
public abstract class AbsTab {
protected Context mContext;
/**
* Tab在TabHost中的位置,屬于第mIndex個(gè)
*/
private int mIndex;
/**
* Tab類的資源View布局
*/
private View mRootView;
/**
* 當(dāng)前Tab是否選中
*/
protected boolean mIsSelected;
/**
* Tab選中監(jiān)聽
*/
private OnTabSelectedListener onTabSelectedListener;
public AbsTab(Context context, int index) {
mContext = context;
mIndex = index;
}
/**
* 初始化View資源,得到RootView,并添加響應(yīng)事件
* @param tab
* @param layoutResId
* @return
*/
protected void inflaterView(final AbsTab tab, @LayoutRes int layoutResId) {
mRootView = LayoutInflater.from(mContext).inflate(layoutResId, null);
LinearLayout.LayoutParams rootViewLp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rootViewLp.weight = 1;
mRootView.setLayoutParams(rootViewLp);
initView(mRootView);
mRootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onTabSelectedListener != null) {
onTabSelectedListener.onTabSelected(tab);
}
}
});
}
/**
* 設(shè)置選中監(jiān)聽
* @param onTabSelectedListener
*/
public void setOnTabSelectedListener(OnTabSelectedListener onTabSelectedListener) {
this.onTabSelectedListener = onTabSelectedListener;
}
/**
* 得到Tab 的RootView
* @return View
*/
public View getTabRootView() {
return mRootView;
}
/**
* 得到Tab Index
* @return int
*/
public int getTabIndex() {
return mIndex;
}
/**
* 顯示消息提示
* @param show 是否顯示
* @param count 顯示數(shù)量
*/
public void showMessageTip(boolean show, int count) {};
/**
* 是否選中該Tab
* @param isSelected
*/
protected abstract void tabSelected(boolean isSelected);
/**
* 初始化RootView里的布局
* @param rootView
*/
protected abstract void initView(View rootView);
}
AbsTab類中的屬性和方法上都有明確的注釋,無需過多的解釋,下面再來看看BaseAdapter類做了什么修改
public abstract class BaseAdapter {
private Fragment[] mFragmentArray;
private FragmentManager mFragmentManager;
protected Context mContext;
public BaseAdapter(Context context, Fragment[] fragments, FragmentManager fragmentManager) {
mContext = context;
mFragmentArray = fragments;
mFragmentManager = fragmentManager;
}
/**
* tab數(shù)量
*/
public int getCount() {
return mFragmentArray != null ? mFragmentArray.length : 0;
}
/**
* fragment 數(shù)組
*/
public Fragment[] getFragmentArray() {
return mFragmentArray;
}
public FragmentManager getFragmentManager() {
return mFragmentManager;
}
/**
* 得到tab
* @return
*/
public abstract AbsTab getTab(int index);
BaseAdapter類刪除了getTextArray,getIconImageArray,getSelectedIconImageArray三個(gè)方法,新增加了getTab抽象方法。
使用
首先創(chuàng)建一個(gè)繼承自AbsTab類的Tab類(項(xiàng)目中我默認(rèn)實(shí)現(xiàn)了一個(gè)DefaultTab),然后創(chuàng)建一個(gè)繼承自BaseAdapter類的適配器類(項(xiàng)目中我默認(rèn)實(shí)現(xiàn)了一個(gè)DefaultAdapter)
TabContainerView tabContainerView = (TabContainerView) findViewById(R.id.tab_containerview_main);
tabContainerView.setAdapter(new DefaultAdapter(this, fragments, getSupportFragmentManager(), getResources().getStringArray(R.array.titleArray),
getResources().getColor(R.color.colorPrimary), iconImageArray, selectedIconImageArray));
在使用上和V1.0是一致的,最大的不同的是適配器,我們來看看DefaultAdapter適配器
public class DefaultAdapter extends BaseAdapter {
private String[] mTextArray;
private int mTextColor = Color.BLACK, mSelectedTextColor;
private int[] mIconImageArray;
private int[] mSelectedIconImageArray;
public DefaultAdapter(Context context, Fragment[] fragmentArray, FragmentManager fragmentManager, String[] textArray, int selectTextColor,
int[] iconImageArray, int[] selectedIconImageArray) {
super(context, fragmentArray, fragmentManager);
mTextArray = textArray;
mSelectedTextColor = selectTextColor;
mIconImageArray = iconImageArray;
mSelectedIconImageArray = selectedIconImageArray;
}
@Override
public AbsTab getTab(int index) {
DefaultTab defaultTab = new DefaultTab(mContext, index);
defaultTab.setText(mTextArray[index]);
defaultTab.setTextColor(mTextColor, mSelectedTextColor);
defaultTab.setIconImage(mIconImageArray[index], mSelectedIconImageArray[index]);
return defaultTab;
}
}
重點(diǎn)來看看getTab方法,方法中創(chuàng)建了一個(gè)DefaultTab類,DefaultTab是什么呢?我們進(jìn)來看看他的具體實(shí)現(xiàn)
public class DefaultTab extends AbsTab {
/**
* tab布局信息
*/
private ImageView mIvIcon;
private TextView mTvText;
private MessageCircle mMessageCircleTip;
/**
* tab 文本顏色和圖片切換資源
*/
private int mTextColor;
private int mSelectedTextColor;
private int mIconImage;
private int mSelectedIconImage;
public DefaultTab(Context context, int index) {
super(context, index);
inflaterView(this, R.layout.tab_default);
}
@Override
public void tabSelected(boolean isSelected) {
if (this.mIsSelected == isSelected) return;
mIvIcon.setImageResource(isSelected ? mSelectedIconImage : mIconImage);
mTvText.setTextColor(isSelected ? mSelectedTextColor : mTextColor);
this.mIsSelected = isSelected;
}
@Override
public void showMessageTip(boolean show, int count) {
mMessageCircleTip.setVisibility(show ? View.VISIBLE : View.GONE);
if (count == -1) {
mMessageCircleTip.setText("");
} else {
mMessageCircleTip.setText(count >= 1000 ? "999+" : count + "");
}
}
@Override
protected void initView(View rootView) {
mIvIcon = (ImageView) rootView.findViewById(R.id.iv_icon);
mTvText = (TextView) rootView.findViewById(R.id.tv_title);
mMessageCircleTip = (MessageCircle) rootView.findViewById(R.id.mc_circle);
}
public void setTextColor(int textColor, int selectedTextColor) {
mTextColor = textColor;
mSelectedTextColor = selectedTextColor;
mTvText.setTextColor(mTextColor);
}
public void setText(String text) {
mTvText.setText(text);
}
public void setIconImage(int iconImage, int selectedIconImage) {
mSelectedIconImage = selectedIconImage;
mIconImage = iconImage;
mIvIcon.setImageResource(iconImage);
}
}
它繼承了AbsTab類,重寫AbsTab中的抽象方法,getTab方法就是返回一個(gè)AbsTab的子類,這個(gè)子類需要開發(fā)者去創(chuàng)建
還有setAdapter方法邏輯也做了修改,修改最大的地方就是TabHost中的addTabs方法,V1.0版本中添加Tab是創(chuàng)建一個(gè)Tab類,而現(xiàn)在是通過適配器的getTab方法獲得AbsTab類,然后添加AbsTab到TabHost當(dāng)中。
總結(jié)
到此V2.0中修改的類和業(yè)務(wù)邏輯就都講完了;開發(fā)中如果需要定制Tab UI, 首先新建一個(gè)繼承自AbsTab的Tab類(項(xiàng)目中我默認(rèn)實(shí)現(xiàn)了一個(gè)DefaultTab), 在新建的Tab類中創(chuàng)建UI布局, 給布局添加數(shù)據(jù), 設(shè)置布局選中和不選中的UI樣式, 然后新建一個(gè)繼承自BaseAdapter 的適配器類, 重寫getTab方法返回一個(gè)AbsTab類,就是剛創(chuàng)建的繼承自AbsTab的Tab類,然后調(diào)用setAdapter的方法即可。
完整代碼:https://github.com/chenpengfei88/TabContainerView/tree/v2.0
歡迎大家Star,F(xiàn)ollow,謝謝。