写在开头
最近有点忙,好久没写文章了。最近公司App有个仿虾米音乐高大上tablayout的需求,网上百度了些没啥好的轮子,于是自己撸了一发。效果已实现,发出来,欢迎大家批评指正。
效果如下:
不太清楚,如何您正好有这个需求,欢迎下载提问题。
github.com/loveAndroid…
实现思路
首先这个效果系统的tablayout是无法实现的,至少我没发现合适的方式,所以就想着自定义一个tablayout来实现此方式。我们可以看源码的tablayout实现方式,他其实就是一个自定义HorizontalScrollView,所以我们也来根据我们的业务需求实现一个自定义HorizontalScrollView。
主要就是以下几方面:
初始化自定义属性及一些初始化操作。
设置数据源。
关联viewpager及更新界面,添加方法设置当前显示tab。
重要: PageChangeListener实现各种渐变效果
初始化自定义属性及一些初始化操作
public XiaMiTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initStyle(context, attrs);
setFillViewport(true);
setHorizontalScrollBarEnabled(false);
mTabContainer = new LinearLayout(context);
addView(mTabContainer, 0, new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
mDataList = new ArrayList<>();
}
private void initStyle(Context context, AttributeSet attrs) {
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.XiaMiTabLayout, 0, 0);
mNormalTextSize = typedArray.getDimensionPixelSize(R.styleable.XiaMiTabLayout_tab_normal_textSize, DEFAULT_NORMAL_TEXT_SIZE_SP);
mSelectTextSize = typedArray.getDimensionPixelSize(R.styleable.XiaMiTabLayout_tab_select_textSize, DEFAULT_SELECT_TEXT_SIZE_SP);
typedArray.recycle();
}
设置数据源。
/**
* 设置数据源
*/
public void setDataList(List<String> dataList) {
this.mDataList.clear();
this.mDataList.addAll(dataList);
}
关联viewpager及更新界面,添加方法设置当前显示tab。
/**
* 关联viewpager
*/
public void setupWithViewPager(ViewPager viewPager) {
this.mViewPager = viewPager;
if (viewPager == null) {
throw new IllegalArgumentException("viewpager not is null");
}
PagerAdapter pagerAdapter = viewPager.getAdapter();
if (pagerAdapter == null) {
throw new IllegalArgumentException("pagerAdapter not is null");
}
this.mViewPager.addOnPageChangeListener(new TabPagerChanger());
mTabCount = pagerAdapter.getCount();
mCurrentTabPosition = viewPager.getCurrentItem();
notifyDataSetChanged();
}
/**
* 更新界面
*/
public void notifyDataSetChanged() {
mTabContainer.removeAllViews();
for (int i = 0; i < mTabCount; i++) {
final int currentPosition = i;
TextView tabTextView = createTextView();
tabTextView.setText(mDataList.get(i));
tabTextView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mViewPager.setCurrentItem(currentPosition);
}
});
mTabContainer.addView(tabTextView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
}
setSelectedTabView(mCurrentTabPosition);
}
/**
* 第一次设置选中tab效果
*
* @param position
*/
protected void setSelectedTabView(int position) {
this.mCurrentTabPosition = position;
for (int i = 0; i < mTabCount; i++) {
View view = mTabContainer.getChildAt(i);
if (view instanceof TextView) {
TextView textView = (TextView) view;
textView.setSelected(position == i);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, position == i ? mSelectTextSize : mNormalTextSize);
textView.setTypeface(position == i ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
textView.setTextColor(position == i ? DEFAULT_SELECT_TEXT_COLOR : DEFAULT_NORMAL_TEXT_COLOR);
if (mCurrentTabPosition == i) {
textView.setPadding(ScreenUtils.dipToPx(getContext(), 5), 0, ScreenUtils.dipToPx(getContext(), 5), ScreenUtils.dipToPx(getContext(), 6));
} else {
textView.setPadding(ScreenUtils.dipToPx(getContext(), 5), 0, ScreenUtils.dipToPx(getContext(), 5), ScreenUtils.dipToPx(getContext(), 10));
}
}
}
}
PageChangeListener实现各种渐变效果
//利用估值器实现渐变
private ArgbEvaluator argbEvaluator = new ArgbEvaluator();
private IntEvaluator intEvaluator = new IntEvaluator();
/**
* pager监听
*/
private class TabPagerChanger implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
final TextView selectedChild = (TextView) mTabContainer.getChildAt(position);
final TextView nextChild = position + 1 < mTabContainer.getChildCount()
? (TextView) mTabContainer.getChildAt(position + 1)
: null;
if (selectedChild != null) {
selectedChild.setTextSize(TypedValue.COMPLEX_UNIT_PX, mSelectTextSize - (mSelectTextSize - mNormalTextSize) * positionOffset);
//初始颜色值
int bgColor = DEFAULT_SELECT_TEXT_COLOR;
if (positionOffset == 0) {
//显示初始透明颜色
bgColor = DEFAULT_SELECT_TEXT_COLOR;
} else if (positionOffset > 1) {
//滚动到一个定值后,颜色最深,而且不再加深
bgColor = DEFAULT_NORMAL_TEXT_COLOR;
} else {
//滚动过程中渐变的颜色
bgColor = (int) argbEvaluator.evaluate(positionOffset, DEFAULT_SELECT_TEXT_COLOR, DEFAULT_NORMAL_TEXT_COLOR);
}
selectedChild.setTextColor(bgColor);
int pad = 6;
if (positionOffset == 0) {
//显示初始透明颜色
pad = 6;
} else if (positionOffset > 1) {
//滚动到一个定值后,颜色最深,而且不再加深
pad = 10;
} else {
//滚动过程中渐变的padding
pad = intEvaluator.evaluate(positionOffset, 6, 10);
}
selectedChild.setPadding(ScreenUtils.dipToPx(getContext(), 5), 0, ScreenUtils.dipToPx(getContext(), 5), ScreenUtils.dipToPx(getContext(), pad));
if (positionOffset > 0.5) {
selectedChild.setTypeface(Typeface.DEFAULT);
} else {
selectedChild.setTypeface(Typeface.DEFAULT_BOLD);
}
}
if (nextChild != null) {
nextChild.setTextSize(TypedValue.COMPLEX_UNIT_PX, mNormalTextSize + (mSelectTextSize - mNormalTextSize) * positionOffset);
//初始颜色值
int bgColor = DEFAULT_NORMAL_TEXT_COLOR;
if (positionOffset == 0) {
//显示初始透明颜色
bgColor = DEFAULT_NORMAL_TEXT_COLOR;
} else if (positionOffset > 1) {
//滚动到一个定值后,颜色最深,而且不再加深
bgColor = DEFAULT_SELECT_TEXT_COLOR;
} else {
//滚动过程中渐变的颜色
bgColor = (int) argbEvaluator.evaluate(positionOffset, DEFAULT_NORMAL_TEXT_COLOR, DEFAULT_SELECT_TEXT_COLOR);
}
nextChild.setTextColor(bgColor);
int pad = 10;
if (positionOffset == 0) {
pad = 10;
} else if (positionOffset > 1) {
pad = 6;
} else {
//滚动过程中渐变的padding
pad = intEvaluator.evaluate(positionOffset, 10, 6);
}
nextChild.setPadding(ScreenUtils.dipToPx(getContext(), 5), 0, ScreenUtils.dipToPx(getContext(), 5), ScreenUtils.dipToPx(getContext(), pad));
if (Math.abs(positionOffset) > 0.5) {
nextChild.setTypeface(Typeface.DEFAULT_BOLD);
} else {
nextChild.setTypeface(Typeface.DEFAULT);
}
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
写在末尾
欢迎下载Demo批评指正,如您对指示器也有要求但无思路,也可私信联系,共同探讨(已实现)。