天天看點

PageIndicator兩種動畫效果

最近看了一個關于PageIndicator的開源項目,發現效果挺好,遍着手寫了一兩個效果。上代碼

自定義屬性:

<declare-styleable name="PageIndicatorView">

        <attr name="dot_radius" format="dimension" />
        <attr name="dot_margin" format="dimension" />
        <attr name="dot_count" format="integer" />
        <attr name="dot_bg" format="reference" />

    </declare-styleable>
           

//第一種效果

public class CircleSmoothPageIndictor extends View implements ViewPager.OnPageChangeListener {

    private int mDotRadius;
    private int mDotMargin;
    private int mDotCount;
    private int mDotSytle;

    private ViewPager mViewPager;
    private RectF mRectF;
    private boolean mFirstLoad = true;

    private List<Integer> mDotLeftXs = new ArrayList<>(10);

    public CircleSmoothPageIndictor(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PageIndicatorView);
        mDotRadius = typedArray.getDimensionPixelSize(R.styleable.PageIndicatorView_dot_radius, 10);
        mDotMargin = typedArray.getDimensionPixelOffset(R.styleable.PageIndicatorView_dot_margin, 10);
        mDotCount = typedArray.getInteger(R.styleable.PageIndicatorView_dot_count, 0);
        mDotSytle = typedArray.getResourceId(R.styleable.PageIndicatorView_dot_bg,0);
        typedArray.recycle();

        initRectF();

    }

    private void initRectF(){
        mRectF = new RectF();
        mRectF.left = 0;
        mRectF.top = 0;
        mRectF.right = mRectF.left + mDotRadius;
        mRectF.bottom = mDotRadius;
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int width = mDotRadius * mDotCount + (mDotCount-1)* mDotMargin;
        int height = mDotRadius;
        setMeasuredDimension(width,height);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#B48A8A"));
        drawAtOnce(canvas);
    }

    private void drawAtOnce(Canvas canvas){

        Log.d("getMeasuredHeight()",""+getMeasuredHeight());

        Paint paint = new Paint();
        if (mFirstLoad){

            int dotX;
            for (int i =0;i< mDotCount;i++){

                if (i ==0){
                    dotX = mDotRadius/2;
                }else{
                    dotX = mDotRadius/2 + (mDotRadius+ mDotMargin)*i;
                }
                mDotLeftXs.add(dotX-mDotRadius/2);

                paint.setColor(Color.parseColor("#3F48CC"));
                paint.setStyle(Paint.Style.FILL);
                paint.setAntiAlias(true);
                canvas.drawCircle(dotX,mDotRadius/2,mDotRadius/2,paint);
            }
        }

        paint.setColor(Color.parseColor("#000000"));
        canvas.drawRoundRect(mRectF,mDotRadius,mDotRadius,paint);
    }


    public void setViewPager(ViewPager viewPager){
        mViewPager = viewPager;
        mViewPager.setOnPageChangeListener(this);
    }



    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        Log.d("xjbin",positionOffset+"");//0-1

        if (mRectF == null){
            mRectF = new RectF();//rect 的高度最大mRedius的一半,長度最大為mRedius的mMargin
        }

        if (mDotLeftXs != null && mDotLeftXs.size() > 0){
            mRectF.left = mDotLeftXs.get(position) + (mDotRadius+mDotMargin)*positionOffset/1;
            mRectF.top = 0;
            mRectF.right = mRectF.left + mDotRadius;
            mRectF.bottom = mDotRadius;
            invalidate();
        }
    }

    @Override
    public void onPageSelected(int position) {

        if (mRectF != null){
            mRectF.setEmpty();
        }

    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}
           

//第二種效果

public class RectAnimPageIndictor extends View implements ViewPager.OnPageChangeListener {

    private int mDotRadius;
    private int mDotMargin;
    private int mDotCount;
    private int mDotSytle;

    private ViewPager mViewPager;
    private RectF mRectF;
    private boolean mFirstLoad = true;

    private List<Integer> mDotLeftXs = new ArrayList<>(10);

    public RectAnimPageIndictor(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PageIndicatorView);
        mDotRadius = typedArray.getDimensionPixelSize(R.styleable.PageIndicatorView_dot_radius, 10);
        mDotMargin = typedArray.getDimensionPixelOffset(R.styleable.PageIndicatorView_dot_margin, 10);
        mDotCount = typedArray.getInteger(R.styleable.PageIndicatorView_dot_count, 0);
        mDotSytle = typedArray.getResourceId(R.styleable.PageIndicatorView_dot_bg,0);
        typedArray.recycle();

        initRectF();

    }

    private void initRectF(){
        mRectF = new RectF();
        mRectF.left = 0;
        mRectF.top = 0;
        mRectF.right = mRectF.left + mDotRadius;
        mRectF.bottom = mDotRadius;
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int width = mDotRadius * mDotCount + (mDotCount-1)* mDotMargin;
        int height = mDotRadius;
        setMeasuredDimension(width,height);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#B48A8A"));
        drawAtOnce(canvas);
    }

    private void drawAtOnce(Canvas canvas){

        Log.d("getMeasuredHeight()",""+getMeasuredHeight());

        Paint paint = new Paint();
        if (mFirstLoad){

            int dotX;
            for (int i =0;i< mDotCount;i++){

                if (i ==0){
                    dotX = mDotRadius/2;
                }else{
                    dotX = mDotRadius/2 + (mDotRadius+ mDotMargin)*i;
                }
                mDotLeftXs.add(dotX-mDotRadius/2);

                paint.setColor(Color.parseColor("#3F48CC"));
                paint.setStyle(Paint.Style.FILL);
                paint.setAntiAlias(true);
                canvas.drawCircle(dotX,mDotRadius/2,mDotRadius/2,paint);
            }
        }

        paint.setColor(Color.parseColor("#000000"));
        canvas.drawRoundRect(mRectF,mDotRadius,mDotRadius,paint);
    }


    public void setViewPager(ViewPager viewPager){
        mViewPager = viewPager;
        mViewPager.setOnPageChangeListener(this);
    }



    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        Log.d("xjbin",positionOffset+"");//0-1

        if (mRectF == null){
            mRectF = new RectF();//rect 的高度最大mRedius的一半,長度最大為圓點的mMargin
        }

        int maxDotWidth = mDotMargin;

        if (mDotLeftXs != null && mDotLeftXs.size() > 0){

            mRectF.top = 0;
            mRectF.bottom = mDotRadius;

            //0-0.5之間變長
            if (positionOffset < 0.5){

                mRectF.left = mDotLeftXs.get(position) + mDotRadius/2f*positionOffset/0.5f;
                mRectF.right =  mDotLeftXs.get(position) + mDotRadius/2f*positionOffset/0.5f + mDotRadius  + mDotMargin * positionOffset/0.5f;

            }else{
            //0.5-1之間變短到正常長度

                float leftOffset = (mDotRadius/2f + mDotMargin) * (positionOffset-0.5f)/0.5f;
                mRectF.left = (mDotLeftXs.get(position) + mDotRadius/2f) + leftOffset;

                float offset = mDotRadius/2f * (positionOffset/1f);
                mRectF.right = mDotLeftXs.get(position+1)+ mDotRadius/2f + offset;
            }

            invalidate();
        }
    }

    @Override
    public void onPageSelected(int position) {

    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}
           

引用開源https://github.com/XjbJoy/PageIndicatorView.git