很多ViewPager和下面的图形绑定一块来滚动,也就是指示器,指示器可以是很多,正
方形,长方形,三角形,圆形等。
这里举一个三角形例子:
效果图:未滑动
滑动中:
这里滑动只要超过倒数第二个就自动向后滑动。
上代码:
自定义view:
public class ViewPagerIndicator extends LinearLayout {
private Paint paint;
private Path path;
private int triangleWidth;
private int triangleHeight;
private static final float RADIO_TRIANGLE_WIDTH = 1 / 6f;
private static final int HIGHCOLOR = 0xffffffff;
private static final int LOWERCOLOR = 0x88ffffff;
private int initTranslationX;
private int moveTranslationX;
private int TabVisibleCount;
private static final int COUNT_DEFAULT_TAB = 4;
private List<String> titles = new ArrayList<String>();
public ViewPagerIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
// 获取可见Tab的数量
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewPagerIndicator);
TabVisibleCount = ta.getInt(R.styleable.ViewPagerIndicator_visible_tab_count, COUNT_DEFAULT_TAB);
if (TabVisibleCount < 0) {
TabVisibleCount = COUNT_DEFAULT_TAB;
}
ta.recycle();
// 初始化画笔
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
paint.setStyle(Style.FILL);
paint.setPathEffect(new CornerPathEffect(5));
}
public ViewPagerIndicator(Context context) {
super(context, null);
// TODO Auto-generated constructor stub
}
/**
* 绘制三角形
*/
/**
* 没有背景时直接调用的是dispatchDraw()方法,draw()方法里包含了dispatchDraw()方法的调用。
* 因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法
*/
@Override
protected void dispatchDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.dispatchDraw(canvas);
/*
* 如果有save()和restore(), 那么平移、缩放、旋转等操作只对save()和restore()作用域之间的代码有效。
* 当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,
* 那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,
* 当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响
*/
canvas.save();
canvas.translate(initTranslationX + moveTranslationX, getHeight());
canvas.drawPath(path, paint);
canvas.restore();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
triangleWidth = (int) (w / TabVisibleCount * RADIO_TRIANGLE_WIDTH);
initTranslationX = w / TabVisibleCount / 2 - triangleWidth / 2;
initTrangle();
}
/**
* 在xml加载完成以后调用此方法
*/
@Override
protected void onFinishInflate() {
// TODO Auto-generated method stub
super.onFinishInflate();
int count = getChildCount();
if (count == 0)
return;
for (int i = 0; i < count; i++) {
View view = getChildAt(i);
LinearLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams();
// 如果之前设有weight 都设置为0
lp.weight = 0;
lp.width = getScreenWidth() / TabVisibleCount;
view.setLayoutParams(lp);
}
setItemClickEvent();
}
private int getScreenWidth() {
// TODO Auto-generated method stub
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
/**
* 初始化三角形
*/
private void initTrangle() {
// TODO Auto-generated method stub
path = new Path();
triangleHeight = (int) (triangleWidth / 2 / 1.7);
path.moveTo(0, 0);
path.lineTo(triangleWidth, 0);
path.lineTo(triangleWidth / 2, -triangleHeight);
path.close();
}
/**
* 指示器跟随手指移动
*
* @param position
* 当前页
* @param offset(0~1)
* 偏移量
*/
public void scoll(int position, float offset) {
// TODO Auto-generated method stub
int tabWidth = getWidth() / TabVisibleCount;
moveTranslationX = (int) (tabWidth * (position + offset));
// 容器移动,当tab处于移动至最后一个时
if (position >= (TabVisibleCount - 2) && offset > 0 && getChildCount() > TabVisibleCount) {
if (TabVisibleCount != 1) {
scrollTo((position - (TabVisibleCount - 2)) * tabWidth + (int) (tabWidth * offset), 0);
} else {
scrollTo(position * tabWidth + (int) (tabWidth * offset), 0);
}
}
// 请求重绘三角形
invalidate();
}
// 该方法需要在setTabitemTitles方法之前调用有效,因为用到了TabVisibleCount
public void setVisibleTab(int count) {
this.TabVisibleCount = count;
}
/**
* 根据title动态创建TextView
*
* @param title
* @return
*/
public void setTabitemTitles(List<String> titles) {
if (titles != null && titles.size() > 0) {
this.titles = titles;
}
for (String title : titles) {
addView(getTextView(title));
}
setItemClickEvent();
}
private View getTextView(String title) {
// TODO Auto-generated method stub
TextView tv = new TextView(getContext());
LinearLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lp.width = getScreenWidth() / TabVisibleCount;
tv.setText(title);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
tv.setGravity(Gravity.CENTER);
tv.setLayoutParams(lp);
tv.setTextColor(LOWERCOLOR);
return tv;
}
/**
* 用户的setOnPageChangeListener回调方法供外部使用
*
* @author lpl
*
*/
public interface PageChangeListener {
public void onPageScrollStateChanged(int arg0);
public void onPageScrolled(int arg0, float arg1, int arg2);
public void onPageSelected(int arg0);
}
private PageChangeListener listener;
public void setOnPageChangeListener(PageChangeListener listener) {
this.listener = listener;
}
/**
* 关联ViewPager
*
* @param pager
* @param pos
* 默认选中页
*/
private ViewPager pager;
public void setViewPager(final ViewPager pager, int pos) {
this.pager = pager;
pager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// 总偏移量:arg0(position)*tabWidth+arg1(positionoffset)*tabWidth
if (listener != null) {
listener.onPageScrolled(arg0, arg1, arg2);
}
scoll(arg0, arg1);
}
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
if (listener != null) {
listener.onPageSelected(arg0);
}
HighTextView(arg0);
}
});
pager.setCurrentItem(pos);
HighTextView(pos);
}
public void resetColorTextView() {
for (int i = 0; i < getChildCount(); i++) {
TextView tv = (TextView) getChildAt(i);
tv.setTextColor(LOWERCOLOR);
}
}
/**
* 设置高亮的TextView
*
* @param position
*/
public void HighTextView(int position) {
resetColorTextView();
TextView tv = (TextView) getChildAt(position);
tv.setTextColor(HIGHCOLOR);
}
/**
* 设置tab的点击事件
*/
public void setItemClickEvent() {
for (int i = 0; i < getChildCount(); i++) {
final int j = i;
TextView tv = (TextView) getChildAt(i);
tv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
pager.setCurrentItem(j);
}
});
}
}
}
在Activity中onCreate调用此控件:
// setVisibleTab该方法需要在setTabitemTitles方法之前调用有效,
//因为用到了TabVisibleCount
// indicator.setVisibleTab(3);设置可见的title个数
//titles是List容器存放TextView
indicator.setTabitemTitles(titles);
//默认0是第一个title为高亮选中
indicator.setViewPager(viewpager, 0);
viewpager.setAdapter(adapter);