仿百度手机助手中的ViewPagerIndicator

参照鸿洋大神博客:http://blog.csdn.net/lmj623565791/article/details/42160391

源码地址:https://github.com/zhangcaiqi/CommonDemo

public class ViewPagerIndicatorextends LinearLayoutimplements ViewPager.OnPageChangeListener {

private Contextcontext;

    //屏幕中可见的tab数量

    private int mVisibleCount =4;

    private PaintmPaint;

    //指示器颜色

    private int indicatorColor = Color.BLACK;

    //tab标题文字颜色

    private int textColor = Color.BLACK;

    //tab标题文字大小

    private int textSize =12;

    //tab标题放大比例

    private float textSizeRatio =0.8f;

    //tab宽度

    private int mTabWidth;

    //指示器默认的宽度

    private float minWidthRatio =1.0f/8;

    //指示器可扩展伸长mTabWidth的30%,再进行平移40%,最后缩小到minWidthRatio的尺寸

    private float stretchRatio =0.3f;

    //指示器高度

    private int indicatorHeight =8;

    //指示器和标题之间的间隙

    private int indicatorSpacing =8;

    private ViewPagerviewPager;

    private CanvasmCanvas;

    //viewpager回调中的的position

    private int position;

    //viewpager回调中的offset

    private float positionOffset;

    //指示器默认再tab中央时的偏移量

    private float centerOffset;

    //指示器宽度

    private float mIndicatorWidth;

    //viewpager回调中的position,上述position会随着offset改变,用于计算向左还是向右滑动

    private int selectedPosition;

    public ViewPagerIndicator(Context context) {

this(context,null);

    }

public ViewPagerIndicator(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

        this.context = context;

        if(null != attrs){

TypedArray typedArray = getContext().obtainStyledAttributes(attrs,R.styleable.ViewPagerIndicator);

            indicatorColor = typedArray.getColor(R.styleable.ViewPagerIndicator_indicatorColor,indicatorColor);

            mVisibleCount = typedArray.getInt(R.styleable.ViewPagerIndicator_visibleCount,mVisibleCount);

            textColor = typedArray.getColor(R.styleable.ViewPagerIndicator_textColor,textColor);

            indicatorHeight = typedArray.getDimensionPixelOffset(R.styleable.ViewPagerIndicator_indicatorHeight,indicatorHeight);

            indicatorSpacing = typedArray.getDimensionPixelOffset(R.styleable.ViewPagerIndicator_indicatorSpacing,indicatorSpacing);

            minWidthRatio = typedArray.getFloat(R.styleable.ViewPagerIndicator_minWidthRatio,minWidthRatio);

            textSize = typedArray.getDimensionPixelSize(R.styleable.ViewPagerIndicator_textSize,textSize);

            textSizeRatio = typedArray.getFloat(R.styleable.ViewPagerIndicator_textSizeRatio,textSizeRatio);

            mTabWidth = typedArray.getDimensionPixelOffset(R.styleable.ViewPagerIndicator_tabWidth,mTabWidth);

        }

mPaint =new Paint();

        mPaint.setAntiAlias(true);

        mPaint.setColor(indicatorColor);

        mPaint.setStyle(Paint.Style.FILL);

        mPaint.setStrokeWidth(indicatorHeight);

    }

@Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int mode = MeasureSpec.getMode(heightMeasureSpec);

        int measuredHeight = getMeasuredHeight();

        int newHeight =indicatorHeight +indicatorSpacing + measuredHeight;

        int newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight,mode);

        setMeasuredDimension(widthMeasureSpec,newHeightMeasureSpec);

    }

@Override

    protected void dispatchDraw(Canvas canvas) {

this.mCanvas = canvas;

        drawIndicator();

        scrollAdapt();

        textAdapt();

        super.dispatchDraw(canvas);

    }

@Override

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

        centerOffset = ((1-minWidthRatio)*mTabWidth)/2;

        mIndicatorWidth =minWidthRatio *mTabWidth;

    }

private int getScreenWidth(){

return  ScreenUtil.getScreenWidth(context);

    }

@Override

    protected void onFinishInflate() {

super.onFinishInflate();

        int childrenCount = getChildCount();

        if(childrenCount ==0){

return;

        }

mTabWidth =mTabWidth ==0 ? (getScreenWidth()/mVisibleCount) :mTabWidth;

        for(int i=0; i

TextView view = (TextView) getChildAt(i);

            view.setTextSize(textSize);

            view.setTextColor(textColor);

            LinearLayout.LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();

            layoutParams.width =mTabWidth;

            view.setLayoutParams(layoutParams);

        }

setItemClickEvent();

    }

public void setViewPager(ViewPager viewPager) {

this.viewPager = viewPager;

        viewPager.addOnPageChangeListener(this);

    }

private void setItemClickEvent() {

int count = getChildCount();

        for(int i=0;i

View view = getChildAt(i);

            int finalI = i;

            view.setOnClickListener((v)->{

viewPager.setCurrentItem(finalI);

            });

        }

}

private void drawIndicator(){

//        if(stretchRatio >= 0.5f){

//            throw new RuntimeException("非法stretchRatio");

//        }

        float indicatorOffsetX;

        float startX =0f,endX;

        if(positionOffset ==0){

indicatorOffsetX =centerOffset

                    +position*mTabWidth;

            endX =mIndicatorWidth;

        }else if(positionOffset <=stretchRatio){

//放大

            indicatorOffsetX =centerOffset

                    +position*mTabWidth;

            endX =mIndicatorWidth +positionOffset*mTabWidth;

        }else if(positionOffset >stretchRatio &&positionOffset <= (1-stretchRatio)){

//平移

            float translationPercent =1 -2*stretchRatio;

            indicatorOffsetX =centerOffset

                    + (positionOffset-stretchRatio)*((1-stretchRatio)*mTabWidth)/translationPercent

+position*mTabWidth;

            endX =mIndicatorWidth +stretchRatio*mTabWidth;

        }else {

//缩小

            indicatorOffsetX =2*mTabWidth

                    -centerOffset

                    - (mIndicatorWidth

                    +stretchRatio*mTabWidth)

+position*mTabWidth;;

            endX =mIndicatorWidth +stretchRatio*mTabWidth;

            startX = (positionOffset -1 +stretchRatio)*mTabWidth;

        }

mCanvas.save();

        mCanvas.translate(indicatorOffsetX,0);

        int y =  getMeasuredHeight() -indicatorHeight;

        mCanvas.drawLine(startX,y,endX,y,mPaint);

        mCanvas.restore();

    }

private void scrollAdapt(){

// 容器滚动,当移动到倒数最后一个的时候,开始滚动

        if (positionOffset >0

                &&position >= (mVisibleCount -2)

&& getChildCount() >mVisibleCount){

if (mVisibleCount !=1){

this.scrollTo((position - (mVisibleCount -2)) *mTabWidth + (int) (mTabWidth *positionOffset), 0);

            }else {

this.scrollTo(position *mTabWidth + (int) (mTabWidth *positionOffset), 0);

            }

}

}

private void textAdapt(){

TextView current = (TextView) getChildAt(selectedPosition);

        float changedSize =textSizeRatio*textSize;

        float selectedSize =textSize*(1+textSizeRatio);

        if(positionOffset !=0){

if(position >=selectedPosition){//向左滑动

                TextView next = (TextView) getChildAt(selectedPosition+1);

                float currentTextSize = selectedSize -positionOffset*changedSize;

                current.setTextSize(currentTextSize);

                float nextSize =textSize +positionOffset*changedSize;

                next.setTextSize(nextSize);

                if(positionOffset >0.5){

next.setTypeface(null, Typeface.BOLD);

                    current.setTypeface(null,Typeface.NORMAL);

                }else{

current.setTypeface(null, Typeface.BOLD);

                    next.setTypeface(null,Typeface.NORMAL);

                }

}else{//向右滑动

                TextView previous = (TextView) getChildAt(selectedPosition-1);

                float currentTextSize = selectedSize - (1-positionOffset)*changedSize;

                float previousSize =textSize + (1-positionOffset)*changedSize;

                current.setTextSize(currentTextSize);

                previous.setTextSize(previousSize);

                if(positionOffset <0.5){

previous.setTypeface(null, Typeface.BOLD);

                    current.setTypeface(null,Typeface.NORMAL);

                }else{

current.setTypeface(null, Typeface.BOLD);

                    previous.setTypeface(null,Typeface.NORMAL);

                }

}

}else{

//选中时

            current.setTextSize(selectedSize);

            current.setTypeface(null, Typeface.BOLD);

        }

}

@Override

    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

this.position = position;

        this.positionOffset = positionOffset;

        invalidate();

        if(null !=pageChangeListener){

pageChangeListener.onPageScrolled(position,positionOffset,positionOffsetPixels);

        }

}

@Override

    public void onPageSelected(int position) {

this.position = position;

        this.positionOffset =0f;

        this.selectedPosition = position;

        invalidate();

        if(null !=pageChangeListener){

pageChangeListener.onPageSelected(position);

        }

}

@Override

    public void onPageScrollStateChanged(int state) {

if(null !=pageChangeListener){

pageChangeListener.onPageScrollStateChanged(state);

        }

}

public void setVisibleCount(int visibleCount){

this.mVisibleCount = visibleCount;

    }

public void setTabTitles(List titles){

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

removeAllViews();

            for(String title:titles){

addView(generateTab(title));

            }

setItemClickEvent();

        }

}

private ViewgenerateTab(String title){

mTabWidth =mTabWidth ==0 ? (getScreenWidth()/mVisibleCount) :mTabWidth;

        TextView view =new TextView(context);

        view.setTextSize(textSize);

        view.setTextColor(textColor);

        view.setText(title);

        view.setGravity(Gravity.CENTER);

        LayoutParams layoutParams =new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);

        layoutParams.width =mTabWidth;

        view.setLayoutParams(layoutParams);

        return view;

    }

public interface PageChangeListener{

void onPageScrolled(int position, float positionOffset,  int positionOffsetPixels);

        void onPageSelected(int position);

        void onPageScrollStateChanged(int state);

    }

private PageChangeListenerpageChangeListener;

    public void setPageChangeListener(PageChangeListener pageChangeListener) {

this.pageChangeListener = pageChangeListener;

    }

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。