比较简单的一个滑动跟随的指示器,本文只是实现了标签的宽度不超过屏幕宽度的情况,根据标签的文字宽度来调节指示器的宽度,效果图如下:
指示器的主要实现是一个自定义的View,代码如下:
public class TabView extends View { private String[] names; private float tabHeight; private List<Float> tabWidths; private Paint tabPaint; private int default_width; private int default_height; private float tabXPadding;//tab x轴上的边距 private float single;//每一个tab的宽度 这里平分计算 private float start;//tab距离左边的边距 private float tabWidth;//tab的宽度 private float tempOffset;//临时变量 用来判断viewPager向左还是向右的判断 public TabView(Context context) { super(context); init(context); } public TabView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public TabView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { tabHeight = Utils.dp2px(context, 3); names = context.getResources().getStringArray(R.array.tabName); tabWidths = new ArrayList<>(); TextPaint textPaint = new TextPaint(); textPaint.setTextSize(Utils.dp2px(context, 18)); float textWidth; for (String name : names) { textWidth = textPaint.measureText(name); tabWidths.add(textWidth); } tabPaint = new Paint(Paint.ANTI_ALIAS_FLAG); tabPaint.setColor(Color.RED); tabPaint.setStyle(Paint.Style.FILL); default_width = Utils.getScreenWidth(context); default_height = (int) tabHeight; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = measureLength(widthMeasureSpec, default_width); int height = measureLength(heightMeasureSpec, default_height); setMeasuredDimension(width, height); start = tabXPadding = ((float) getMeasuredWidth() / names.length - tabWidths.get(0)) / 2; single = getMeasuredWidth() / names.length; } private int measureLength(int measureSpec, int defaultLength) { int length = 0; int mode = MeasureSpec.getMode(measureSpec); int size = MeasureSpec.getSize(measureSpec); switch (mode) { case MeasureSpec.AT_MOST: length = Math.min(size, defaultLength); break; case MeasureSpec.EXACTLY: length = size; break; case MeasureSpec.UNSPECIFIED: length = defaultLength; break; } return length; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawTab(canvas); } private void drawTab(Canvas canvas) { //重点在于计算这个开始start位置的值和 tabWidth这个tab宽度的值 此值在滑动时都可能是变化的 canvas.drawRect(start, 0, start + tabWidth, tabHeight, tabPaint); } public void setScroll(int position, float positionOffset) { boolean isNext = tempOffset < positionOffset && positionOffset != 0 && position != names.length - 1; boolean isPre = tempOffset > positionOffset && positionOffset != 0 && position != names.length - 1; float currentTabWidth = tabWidths.get(position); if (isNext) { float nextWidth = tabWidths.get(position + 1); tabWidth = (nextWidth - currentTabWidth) * positionOffset + currentTabWidth; } else if (isPre) { float preWidth = tabWidths.get(position); currentTabWidth = tabWidths.get(position + 1); tabWidth = (preWidth - currentTabWidth) * (1 - positionOffset) + currentTabWidth; } else { tabWidth = tabWidth == 0 ? currentTabWidth : tabWidth; } tabXPadding = (single - tabWidth) / 2; start = tabXPadding + positionOffset * single + position * single; tempOffset = positionOffset; invalidate(); } }
在Activity里调用的主要代码如下:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { tabView.setScroll(position, positionOffset); } @Override public void onPageSelected(int position) { click(position,false); } @Override public void onPageScrollStateChanged(int state) { } });如果有兴趣查看完整的Demo,请前去http://download.csdn.net/detail/chinaboyliusir/9611839下载,欢迎指正
![微笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/smile.gif)