Android——自定义ViewPager指示器

来源:互联网 发布:问道登陆器源码 编辑:程序博客网 时间:2024/05/17 03:40

很多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);