当前位置: 代码迷 >> Android >> Android开发:史上最容易方便的viewpager加indicator的方法
  详细解决方案

Android开发:史上最容易方便的viewpager加indicator的方法

热度:47   发布时间:2016-04-28 02:36:07.0
Android开发:史上最简单方便的viewpager加indicator的方法

开发Android应用的时候,每次给viewpager加indicator的时候,是不是感觉到很无力呢,看看JakeWharton大神的github,要么要应用library,要么把code加到自己的项目中,还要加attrs,加各种value,比如colors,strings,其实超过90%以上的时候,我们的需要其实很简单,只是在底部的中间加上指示圆点,而且JakeWharton大神的默认的是空心圆圈,还要在onDraw中改成实心的圆形,是不是厌烦啦,每次都要这么麻烦,好了,终极简单的解决方法出来了,想看效果:


当然,这个效果照搬别人的图,不过实现这个效果,我用了超级简单的方法,一劳永逸:


只要三个步骤,复制粘贴,再复制粘贴,然后在activity中写几行代码即可。


  • 第一步,复制,粘贴
新建一个类,叫做CircleIndicatorHelper,然后复制如下的代码进去:
public class CircleIndicatorHelper {	private CirclePageIndicator mCircleIndicator;	private Context mContext;		public CircleIndicatorHelper(Context context) {		mCircleIndicator = new CirclePageIndicator(context);		mContext = context;	}		public void setViewpager(ViewPager viewPager) {		ViewGroup parentView = (ViewGroup) viewPager.getParent();		LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM);		lp.setMargins(0, 0, 0, dpToPx(8));		mCircleIndicator.setLayoutParams(lp);		parentView.addView(mCircleIndicator);		mCircleIndicator.setViewPager(viewPager);	}		public void setFillColor(String colorString) {		int color = Color.parseColor(colorString);		mCircleIndicator.setFillColor(color);	}		public void setDefaultColor(String colorString) {		int color = Color.parseColor(colorString);		mCircleIndicator.setDefaultColor(color);	}		public void setRadius(int radius) {		mCircleIndicator.setRadius(dpToPx(radius));	}		private int dpToPx(int dp) {		DisplayMetrics resourec = mContext.getResources().getDisplayMetrics();		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resourec);	}}

  • 第二部,再新建一个类,名字叫复制,粘贴
public class CirclePageIndicator extends View{    private static final int INVALID_POINTER = -1;    private float mRadius;//    private final Paint mPaintPageFill = new Paint(ANTI_ALIAS_FLAG);    private final Paint mPaintStroke = new Paint(ANTI_ALIAS_FLAG);    private final Paint mPaintFill = new Paint(ANTI_ALIAS_FLAG);    private ViewPager mViewPager;    private ViewPager.OnPageChangeListener mListener;    private int mCurrentPage;    private int mSnapPage;    private float mPageOffset;    private int mScrollState;    private int mOrientation;    private boolean mCentered;    private boolean mSnap;        private float cicleSpace;    public CirclePageIndicator(Context context) {        this(context, null);    }    public CirclePageIndicator(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public CirclePageIndicator(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        if (isInEditMode()) return;        final Resources res = getResources();        final int defaultFillColor = Color.parseColor("#7F7F7F");        final int defaultStrokeColor = Color.parseColor("#D0D0D0");        final float defaultRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, res.getDisplayMetrics());        mCentered = true;        mPaintStroke.setStyle(Style.FILL);        mPaintStroke.setColor(defaultStrokeColor);        mPaintFill.setStyle(Style.FILL);        mPaintFill.setColor(defaultFillColor);        mRadius = defaultRadius;                cicleSpace = mRadius*3;    }    public void setCentered(boolean centered) {        mCentered = centered;        invalidate();    }    public boolean isCentered() {        return mCentered;    }    public void setDefaultColor(int strokeColor) {        mPaintStroke.setColor(strokeColor);        invalidate();    }        public void setFillColor(int fillColor) {    	mPaintFill.setColor(fillColor);    	invalidate();    }    public void setRadius(float radius) {        mRadius = radius;        cicleSpace = radius*3;        invalidate();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (mViewPager == null) {            return;        }        final int count = mViewPager.getAdapter().getCount();        if (count == 0) {            return;        }        if (mCurrentPage >= count) {            setCurrentItem(count - 1);            return;        }        int longSize;        int longPaddingBefore;        int longPaddingAfter;        int shortPaddingBefore;        if (mOrientation == HORIZONTAL) {            longSize = getWidth();            longPaddingBefore = getPaddingLeft();            longPaddingAfter = getPaddingRight();            shortPaddingBefore = getPaddingTop();        } else {            longSize = getHeight();            longPaddingBefore = getPaddingTop();            longPaddingAfter = getPaddingBottom();            shortPaddingBefore = getPaddingLeft();        }        final float shortOffset = shortPaddingBefore + mRadius;        float longOffset = longPaddingBefore + mRadius;        if (mCentered) {            longOffset += ((longSize - longPaddingBefore - longPaddingAfter) / 2.0f) - ((count * cicleSpace) / 2.0f);        }        float dX;        float dY;        float pageFillRadius = mRadius;        //Draw stroked circles        for (int iLoop = 0; iLoop < count; iLoop++) {            float drawLong = longOffset + (iLoop * cicleSpace);            if (mOrientation == HORIZONTAL) {                dX = drawLong;                dY = shortOffset;            } else {                dX = shortOffset;                dY = drawLong;            }            // Only paint fill if not completely transparent                canvas.drawCircle(dX, dY, mRadius, mPaintStroke);        }        //Draw the filled circle according to the current scroll        float cx = (mSnap ? mSnapPage : mCurrentPage) * cicleSpace;        if (!mSnap) {            cx += mPageOffset * cicleSpace;        }        if (mOrientation == HORIZONTAL) {            dX = longOffset + cx;            dY = shortOffset;        } else {            dX = shortOffset;            dY = longOffset + cx;        }        canvas.drawCircle(dX, dY, mRadius, mPaintFill);    }    public void setViewPager(ViewPager view) {        if (mViewPager == view) {            return;        }        if (mViewPager != null) {            mViewPager.setOnPageChangeListener(null);        }        if (view.getAdapter() == null) {            throw new IllegalStateException("ViewPager does not have adapter instance.");        }        mViewPager = view;        mViewPager.setOnPageChangeListener(new OnPageChangeListener() {						@Override			public void onPageSelected(int position) {		        if (mSnap || mScrollState == ViewPager.SCROLL_STATE_IDLE) {		            mCurrentPage = position;		            mSnapPage = position;		            invalidate();		        }		        if (mListener != null) {		            mListener.onPageSelected(position);		        }		    }						@Override			public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {				mCurrentPage = position;		        mPageOffset = positionOffset;		        invalidate();		        if (mListener != null) {		            mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);		        }			}						@Override			public void onPageScrollStateChanged(int state) {				 mScrollState = state;			        if (mListener != null) {			            mListener.onPageScrollStateChanged(state);			        }			}		});        invalidate();    }    public void setViewPager(ViewPager view, int initialPosition) {        setViewPager(view);        setCurrentItem(initialPosition);    }    public void setCurrentItem(int item) {        if (mViewPager == null) {            throw new IllegalStateException("ViewPager has not been bound.");        }        mViewPager.setCurrentItem(item);        mCurrentPage = item;        invalidate();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        if (mOrientation == HORIZONTAL) {            setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec));        } else {            setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec));        }    }    /**     * Determines the width of this view     *     * @param measureSpec     *            A measureSpec packed into an int     * @return The width of the view, honoring constraints from measureSpec     */    private int measureLong(int measureSpec) {        int result;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) {            //We were told how big to be            result = specSize;        } else {            //Calculate the width according the views count            final int count = mViewPager.getAdapter().getCount();            result = (int)(getPaddingLeft() + getPaddingRight()                    + (count * 2 * mRadius) + (count - 1) * mRadius + 1);            //Respect AT_MOST value if that was what is called for by measureSpec            if (specMode == MeasureSpec.AT_MOST) {                result = Math.min(result, specSize);            }        }        return result;    }    /**     * Determines the height of this view     *     * @param measureSpec     *            A measureSpec packed into an int     * @return The height of the view, honoring constraints from measureSpec     */    private int measureShort(int measureSpec) {        int result;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if (specMode == MeasureSpec.EXACTLY) {            //We were told how big to be            result = specSize;        } else {            //Measure the height            result = (int)(2 * mRadius + getPaddingTop() + getPaddingBottom() + 1);            //Respect AT_MOST value if that was what is called for by measureSpec            if (specMode == MeasureSpec.AT_MOST) {                result = Math.min(result, specSize);            }        }        return result;    }    @Override    public void onRestoreInstanceState(Parcelable state) {        SavedState savedState = (SavedState)state;        super.onRestoreInstanceState(savedState.getSuperState());        mCurrentPage = savedState.currentPage;        mSnapPage = savedState.currentPage;        requestLayout();    }    @Override    public Parcelable onSaveInstanceState() {        Parcelable superState = super.onSaveInstanceState();        SavedState savedState = new SavedState(superState);        savedState.currentPage = mCurrentPage;        return savedState;    }    static class SavedState extends BaseSavedState {        int currentPage;        public SavedState(Parcelable superState) {            super(superState);        }        private SavedState(Parcel in) {            super(in);            currentPage = in.readInt();        }        @Override        public void writeToParcel(Parcel dest, int flags) {            super.writeToParcel(dest, flags);            dest.writeInt(currentPage);        }        @SuppressWarnings("UnusedDeclaration")        public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {            @Override            public SavedState createFromParcel(Parcel in) {                return new SavedState(in);            }            @Override            public SavedState[] newArray(int size) {                return new SavedState[size];            }        };    }    }

代码有点长啊,不过只是复制粘贴,应该没什么问题吧
  • 第三部,在含有viewpager的activity,引用如下几句代码,即可加上viewpagerindicator了
private CircleIndicatorHelper mIndicatorHelper = new CircleIndicatorHelper(this);		mIndicatorHelper.setViewpager(mViewPager);

好了,就是这么的简单,这么的任性,从此再也不用担心加小圆圈了,不过问题来了,怎么自定义呢,我要的圆圈的颜色,大小,间距,OK,这些都是一句代码搞定;

mIndicatorHelper.setFillColor("#651717");		mIndicatorHelper.setDefaultColor("#00A2E8");		mIndicatorHelper.setRadius(8);

设置填充颜色,设置默认颜色,设置大小,简单便捷
好了,最后,别忘了,把viewpager的parent View设置成FrameLayout噢


  相关解决方案