自定义控件之AndroidSegmentControlView,仿IOS平台UISegmentControlView,继承自View

来源:互联网 发布:学数据库有前途吗 编辑:程序博客网 时间:2024/06/11 09:05

控件简介

UISegmentControl在IOS平台的App中非常常见,其控件如下图所示:

IOS平台的UISegmentControl

      这种控件的主要作用是动态的更改界面的显示内容,一般应用于内容较多的界面,且分屏显示不同种类的内容。

      在Android开发过程中,有时需要实现类似UISegmentControl的效果,这里我将自己的代码开源在github上了,命名为SegmentControlView,下面是实现的效果:


图示1

动态图片可点击如下链接:
https://github.com/Carbs0126/AndroidSegmentControlView

控件说明

SegmentControlView extends View

      这个SegmentControlView是继承自View的,而非组合控件,因此实现起来虽然有点繁琐,但是灵活性反而比组合控件要高很多,并且可以加上过度效果等,且比组合控件更加轻量化。

控件特点

      我实现的这个SegmentControlView具有如下特点:

1.SegmentControlView可设置与ViewPager联动,在segment切换时具有颜色渐变效果,类似微信。2.可以自定义SegmentControlView的四个corner的半径。3.自定义背景颜色与字体颜色、字体大小等等。4.在xml中设置SegmentControlView中的多个titles,自动按照titles生成多个segment。5.设置按下颜色与normal颜色的色值对比度。6.具有AT_MOST的适配功能,即具有wrap_content模式7.可以设置回调响应事件

使用方法

属性文件说明

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="SegmentControlView">        <attr name="scv_BackgroundSelectedColor" format="reference|color" />//选中segment的背景颜色        <attr name="scv_BackgroundNormalColor" format="reference|color" />//未选中segment的背景颜色        <attr name="scv_TextSelectedColor" format="reference|color" />//选中segment的文字颜色        <attr name="scv_TextNormalColor" format="reference|color" />//未选中segment的文字颜色        <attr name="scv_FrameColor" format="reference|color" />//segment边框的颜色        <attr name="scv_FrameWidth" format="reference|dimension" />//segment边框的宽度        <attr name="scv_FrameCornerRadius" format="reference|dimension" />//segment四个圆角的半径大小        <attr name="scv_TextSize" format="reference|dimension" />//文字大小        <attr name="scv_TextArray" format="reference" />//string数组,每一个string都会填充到一个segment中        <attr name="scv_SelectedIndex" format="reference|integer" />//默认选中的segment        <attr name="scv_SegmentPaddingHorizontal" format="reference|dimension" />//每一个segment内部的水平padding        <attr name="scv_SegmentPaddingVertical" format="reference|dimension" />每一个Segment的竖直方向的padding        <attr name="scv_Gradient" format="reference|boolean" />//Segment改变时是否使用颜色渐变效果    </declare-styleable></resources>

布局文件创建SegmentControlView

<cn.carbs.android.segmentcontrolview.library.SegmentControlView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center_horizontal"        android:paddingLeft="10dp"        android:paddingRight="10dp"        app:scv_FrameCornerRadius="6dp"        app:scv_FrameWidth="1dp"        app:scv_Gradient="true"        app:scv_SegmentPaddingVertical="5dp"        app:scv_TextArray="@array/segment_control_arrays_0"/>

使用方法

dependencies {    compile 'cn.carbs.android:SegmentControlView:1.0.0'}
    segmentcontrolview.setOnSegmentChangedListener(new SegmentControlView.OnSegmentChangedListener() {        @Override        public void onSegmentChanged(int newSelectedIndex) {            if(viewpager != null){                //change the second argument to true if you want the gradient effect when viewpager is changing                viewpager.setCurrentItem(newSelectedIndex, false);//viewpager changing without animation            }        }    });    //set viewpager to change segment according to the state of viewpager    segmentcontrolview.setViewPager(viewpager);    //set the selected index of segments initiatively    segmentcontrolview.setSelectedIndex();    //set gradient effect if you want    segmentcontrolview.setGradient(true);

项目地址:

https://github.com/Carbs0126/AndroidSegmentControlView

Git:

git clone https://github.com/Carbs0126/AndroidSegmentControlView.git

源码如下

package cn.carbs.android.segmentcontrolview.library;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.graphics.Rect;import android.graphics.RectF;import android.support.v4.view.ViewPager;import android.text.TextUtils;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import java.lang.reflect.Field;/** * an SegmentControlView inspired by the UISegmentControl on IOS platform. * this view has many interesting such as : *  1. set gradient effect when segment is changing by ViewPager if needed *  2. set the corners' radius *  3. set colors of texts and background *  4. set titles in xml resource file *  5. has pressed effect when finger touches this view, you can set the dark coefficient    *  * Author   Carbs.Wang  * Email    yeah0126#yeah.net */public class SegmentControlView extends View {    /**     * onSegmentChanged function will be triggered if segment changed     */    public interface OnSegmentChangedListener{        void onSegmentChanged(int newSelectedIndex);    }    private static final float TOUCHED_BACKGROUND_DARK_COEFFICIENT = 0.95F;    private static final int COLOR_PRIMARY_NORMAL = 0XFFFFFFFF;    private static final int COLOR_PRIMARY_SELECTED = 0XFF2CA99F;    private static final int DEFAULT_COLOR_BACKGROUND_SELECTED = COLOR_PRIMARY_SELECTED;    private static final int DEFAULT_COLOR_BACKGROUND_NORMAL = COLOR_PRIMARY_NORMAL;    private static final int DEFAULT_COLOR_TEXT_SELECTED = COLOR_PRIMARY_NORMAL;    private static final int DEFAULT_COLOR_TEXT_NORMAL = COLOR_PRIMARY_SELECTED;    private static final int DEFAULT_COLOR_FRAME = COLOR_PRIMARY_SELECTED;    private static final int DEFAULT_TEXT_SIZE_SP = 16;    private static final int DEFAULT_FRAME_WIDTH_PX = 2;    private static final int DEFAULT_FRAME_CORNER_RADIUS_PX = 0;    private static final int DEFAULT_SELECTED_INDEX = 0;    private static final int DEFAULT_SEGMENT_PADDING_HORIZONTAL = 16;    private static final int DEFAULT_SEGMENT_PADDING_VERTICAL = 12;    private static final boolean DEFAULT_IS_GRADIENT = false;    private String[] mTexts = null;    private int mColorBackgroundSelected = DEFAULT_COLOR_BACKGROUND_SELECTED;    private int mColorBackgroundNormal = DEFAULT_COLOR_BACKGROUND_NORMAL;    private int mColorTextSelected = DEFAULT_COLOR_TEXT_SELECTED;    private int mColorTextNormal = DEFAULT_COLOR_TEXT_NORMAL;    private int mColorFrame = DEFAULT_COLOR_FRAME;    private int mFrameWidth = DEFAULT_FRAME_WIDTH_PX;    private int mFrameCornerRadius = DEFAULT_FRAME_CORNER_RADIUS_PX;    private int mTextSize = 0;    private int mSelectedIndex = DEFAULT_SELECTED_INDEX;    //used in wrap_content mode    private int mSegmentPaddingHorizontal = DEFAULT_SEGMENT_PADDING_HORIZONTAL;    private int mSegmentPaddingVertical = DEFAULT_SEGMENT_PADDING_VERTICAL;    private boolean mIsGradient = DEFAULT_IS_GRADIENT;    private OnSegmentChangedListener mOnSegmentChangedListener;    private float unitWidth = 0;    private Paint paintText;        //painter of the text     private Paint paintBackground;  //painter of the background    private Paint paintFrame;       //painter of the frame    private RectF rectF;    private RectF rectFArc;    private Path pathFrame;    private float textCenterYOffset;    private int preTouchedIndex = -1;    private int curTouchedIndex = -1;    private ViewPager viewPager;    public SegmentControlView(Context context) {        super(context);        init();    }    public SegmentControlView(Context context, AttributeSet attrs) {        super(context, attrs);        initAttr(context, attrs);        init();    }    public SegmentControlView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initAttr(context, attrs);        init();    }    private void initAttr(Context context, AttributeSet attrs) {        if (attrs == null) {            return;        }        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SegmentControlView);        int n = a.getIndexCount();        for (int i = 0; i < n; i++) {            int attr = a.getIndex(i);            if(attr == R.styleable.SegmentControlView_scv_BackgroundSelectedColor){                mColorBackgroundSelected = a.getColor(attr, DEFAULT_COLOR_BACKGROUND_SELECTED);            }else if(attr == R.styleable.SegmentControlView_scv_BackgroundNormalColor){                mColorBackgroundNormal = a.getColor(attr, DEFAULT_COLOR_BACKGROUND_NORMAL);            }else if(attr == R.styleable.SegmentControlView_scv_TextSelectedColor){                mColorTextSelected = a.getColor(attr, DEFAULT_COLOR_TEXT_SELECTED);            }else if(attr == R.styleable.SegmentControlView_scv_TextNormalColor){                mColorTextNormal = a.getColor(attr, DEFAULT_COLOR_TEXT_NORMAL);            }else if(attr == R.styleable.SegmentControlView_scv_FrameColor){                mColorFrame = a.getColor(attr, DEFAULT_COLOR_FRAME);            }else if(attr == R.styleable.SegmentControlView_scv_TextSize){                mTextSize = a.getDimensionPixelSize(attr, sp2px(getContext(), DEFAULT_TEXT_SIZE_SP));            }else if(attr == R.styleable.SegmentControlView_scv_TextArray){                mTexts = convertCharSequenceToString(a.getTextArray(attr));            }else if(attr == R.styleable.SegmentControlView_scv_FrameWidth){                mFrameWidth = a.getDimensionPixelSize(attr, DEFAULT_FRAME_WIDTH_PX);            }else if(attr == R.styleable.SegmentControlView_scv_FrameCornerRadius){                mFrameCornerRadius = a.getDimensionPixelSize(attr, DEFAULT_FRAME_CORNER_RADIUS_PX);            }else if(attr == R.styleable.SegmentControlView_scv_SelectedIndex){                mSelectedIndex = a.getInteger(attr, DEFAULT_SELECTED_INDEX);            }else if(attr == R.styleable.SegmentControlView_scv_SegmentPaddingHorizontal){                mSegmentPaddingHorizontal = a.getDimensionPixelSize(attr, DEFAULT_SEGMENT_PADDING_HORIZONTAL);            }else if(attr == R.styleable.SegmentControlView_scv_SegmentPaddingVertical){                mSegmentPaddingVertical = a.getDimensionPixelSize(attr, DEFAULT_SEGMENT_PADDING_VERTICAL);            }else if(attr == R.styleable.SegmentControlView_scv_Gradient){                mIsGradient = a.getBoolean(attr, DEFAULT_IS_GRADIENT);            }        }        a.recycle();    }    private void init(){        rectF = new RectF();        rectFArc = new RectF();        pathFrame = new Path();        if(mTextSize == 0)            mTextSize = sp2px(getContext(), DEFAULT_TEXT_SIZE_SP);        paintText = new Paint();        paintText.setAntiAlias(true);        paintText.setTextAlign(Paint.Align.CENTER);        paintText.setTextSize(mTextSize);        paintBackground = new Paint();        paintBackground.setAntiAlias(true);        paintBackground.setStyle(Paint.Style.FILL);        paintFrame = new Paint();        paintFrame.setAntiAlias(true);        paintFrame.setStyle(Paint.Style.STROKE);        paintFrame.setStrokeWidth(mFrameWidth);        paintFrame.setColor(mColorFrame);        textCenterYOffset = getTextCenterYOffset(paintText.getFontMetrics());        this.setClickable(true);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        setMeasuredDimension(measureWidth(widthMeasureSpec, paintText),                              measureHeight(heightMeasureSpec, paintText));      }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        rectF.left = getPaddingLeft();        rectF.top = getPaddingTop();        rectF.right = w - getPaddingRight();        rectF.bottom = h - getPaddingBottom();        float inset = (float)Math.ceil(mFrameWidth / 2);        rectF.inset(inset, inset);        if(mTexts!= null && mTexts.length > 0){            unitWidth = rectF.width() / mTexts.length;        }        rectFArc.left = 0;        rectFArc.top = 0;        rectFArc.right = 2 * mFrameCornerRadius;        rectFArc.bottom = 2 * mFrameCornerRadius;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if(!isStringArrayEmpty(mTexts)){            drawBackgroundAndFrameAndText(canvas);        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        preTouchedIndex = curTouchedIndex;        switch(event.getAction()){        case MotionEvent.ACTION_DOWN:            curTouchedIndex = getTouchedIndex(event.getX(), event.getY());            if(preTouchedIndex != curTouchedIndex){                invalidate();            }            break;        case MotionEvent.ACTION_MOVE:            curTouchedIndex = getTouchedIndex(event.getX(), event.getY());            if(preTouchedIndex != curTouchedIndex){                invalidate();            }            break;        case MotionEvent.ACTION_UP:            curTouchedIndex = getTouchedIndex(event.getX(), event.getY());            if(curTouchedIndex != -1){                if(mOnSegmentChangedListener != null && mSelectedIndex != curTouchedIndex){                    mOnSegmentChangedListener.onSegmentChanged(curTouchedIndex);                }                mSelectedIndex = curTouchedIndex;            }            curTouchedIndex = -1;            if(mIsGradient && checkViewPagerOnPageChangeListener(this.viewPager)){            }else{                invalidate();            }            break;        case MotionEvent.ACTION_CANCEL:            curTouchedIndex = -1;            invalidate();            break;        }        return super.onTouchEvent(event);    }    public void setTextSize(int textSize){        if(this.mTextSize != textSize){            this.mTextSize = textSize;            paintText.setTextSize(textSize);            textCenterYOffset = getTextCenterYOffset(paintText.getFontMetrics());            requestLayout();            invalidate();        }    }    public int getSelectedIndex(){        return mSelectedIndex;    }    public void setSelectedIndex(int selectedIndex){        if(mSelectedIndex != selectedIndex){            mSelectedIndex = selectedIndex;            if(mOnSegmentChangedListener != null){                mOnSegmentChangedListener.onSegmentChanged(mSelectedIndex);            }//          invalidate();            if(mIsGradient && checkViewPagerOnPageChangeListener(this.viewPager)){            }else{                invalidate();            }        }    }    public void setTextColor(int textColorNormal, int textColorSelected){        this.mColorTextNormal = textColorNormal;        this.mColorTextSelected = textColorSelected;        invalidate();    }    public void setBackgroundColor(int backgroundColorNormal, int backgroundColorSelected){        this.mColorBackgroundNormal = backgroundColorNormal;        this.mColorBackgroundSelected = backgroundColorSelected;        invalidate();    }    public void setFrameColor(int frameColor){        this.mColorFrame = frameColor;        invalidate();    }    public void setFrameWidth(int frameWidth){        this.mFrameWidth = frameWidth;        requestLayout();        invalidate();    }    public void setTexts(String[] texts){        assertTextsValid(texts);        if(texts == null || texts.length < 2){            throw new IllegalArgumentException("SegmentControlView's content text array'length should larger than 1");        }        if(checkIfEqual(this.mTexts, texts)){            return;        }        this.mTexts = texts;        unitWidth = rectF.width() / texts.length;        requestLayout();        invalidate();    }    public int getCount(){        if(mTexts == null) return 0;        return mTexts.length;    }    /**     * setViewPager(viewpager) to response to the change of ViewPager     * @param viewPager the viewPager you want segmentcontrolview to respond with     */    public void setViewPager(ViewPager viewPager) {        this.viewPager = viewPager;        if (viewPager != null) {            viewPager.setOnPageChangeListener(new InternalViewPagerListener());        }    }    /**     * set if this view has the Gradient effect when segment changed     * @param gradient set if you want gradient effect     */    public void setGradient(boolean gradient){        if(mIsGradient != gradient){            mIsGradient = gradient;        }    }    public boolean getGradient(){        return mIsGradient;    }    /**     * when segment changed,      * mOnSegmentChangedListener.onSegmentChanged(newSelectedIndex) will be triggered     * @param listener OnSegmentChangedListener     */    public void setOnSegmentChangedListener(OnSegmentChangedListener listener){        mOnSegmentChangedListener = listener;    }    public void update(){        invalidate();    }    private float getTextCenterYOffset(Paint.FontMetrics fontMetrics){        if(fontMetrics == null) return 0;        return Math.abs(fontMetrics.top + fontMetrics.bottom)/2;    }    private String[] convertCharSequenceToString(CharSequence[] csArray){        if(csArray == null) return null;        String[] sArray = new String[csArray.length];        for(int i = 0; i < csArray.length; i++){            sArray[i] = csArray[i].toString();        }        return sArray;    }    private void assertTextsValid(String[] texts){        if(texts == null || texts.length < 2){            throw new IllegalArgumentException("SegmentControlView's content text array'length should larger than 1");        }    }    private boolean checkViewPagerOnPageChangeListener(ViewPager viewPager){        if(viewPager == null) return false;        Field field = null;        try {            field = ViewPager.class.getDeclaredField("mOnPageChangeListener");            if(field == null) return false;            field.setAccessible(true);            Object o = field.get(viewPager);            if(o != null && o instanceof InternalViewPagerListener){                return true;            }        } catch (Exception e) {            return false;        }        return false;    }    private int getTouchedIndex(float x, float y){        if(!rectF.contains(x, y)){            return -1;        }        for(int i = 0; i < mTexts.length; i++){            if(rectF.left + i * unitWidth <= x && x < rectF.left + (i + 1) * unitWidth){                return i;            }        }        return -1;    }    private boolean checkIfEqual(String[] a, String[] b){        if(a == null && b == null){            return true;        }        if(a != null){            if(b == null){                return false;            }            if(a.length != b.length){                return false;            }            for(int i = 0; i < a.length; i++){                if(a[i] == null && b[i] == null){                    continue;                }                if(a[i] != null && a[i].equals(b[i])){                    continue;                }else{                    return false;                }            }            return true;        }        return false;    }    private int measureWidth(int measureSpec, Paint paint) {          int result = 0;          int specMode = MeasureSpec.getMode(measureSpec);          int specSize = MeasureSpec.getSize(measureSpec);          if (specMode == MeasureSpec.EXACTLY) {              result = specSize;        } else {              int maxWidth = 0;            int maxWidthItem = getMaxWidthOfTextArray(mTexts, paint);            maxWidth = (maxWidthItem + 2 * mSegmentPaddingHorizontal + 2 * mFrameWidth) * mTexts.length;            if(maxWidth < 2 * mFrameCornerRadius){                maxWidth = 2 * mFrameCornerRadius;            }            result = this.getPaddingLeft() + this.getPaddingRight() + maxWidth;//MeasureSpec.UNSPECIFIED            if (specMode == MeasureSpec.AT_MOST) {                result = Math.min(result, specSize);              }        }        return result;      }      private int measureHeight(int measureSpec, Paint paint) {          int result = 0;          int specMode = MeasureSpec.getMode(measureSpec);          int specSize = MeasureSpec.getSize(measureSpec);          if (specMode == MeasureSpec.EXACTLY) {              result = specSize;          } else {              int maxHeight = 0;            int maxHeightItem = getMaxHeightOfTextArray(mTexts, paint);            maxHeight = maxHeightItem + 2 * mSegmentPaddingVertical + 2 * mFrameWidth;            if(maxHeight < 2 * mFrameCornerRadius){                maxHeight = 2 * mFrameCornerRadius;            }            result = this.getPaddingTop() + this.getPaddingBottom() + maxHeight;//MeasureSpec.UNSPECIFIED            if (specMode == MeasureSpec.AT_MOST) {                  result = Math.min(result, specSize);              }          }          return result;    }    private int getMaxWidthOfTextArray(String[] array, Paint paint){        if(array == null){            return 0;        }        int maxWidth = 0;        for(String item : array){            if(item != null){                int itemWidth = getTextWidth(item, paint);                maxWidth = Math.max(itemWidth, maxWidth);            }        }        return maxWidth;    }    private int getMaxHeightOfTextArray(String[] array, Paint paint){        if(array == null){            return 0;        }        int maxHeight = 0;        for(String item : array){            if(item != null){                int itemHeight = getTextHeight(item, paint);                maxHeight = Math.max(itemHeight, maxHeight);            }        }        return maxHeight;    }    private void drawBackgroundAndFrameAndText(Canvas canvas){        int curBackgroundColor = 0;        int curTextColor = 0;        for(int i = 0; i < mTexts.length; i++){            float left = rectF.left + unitWidth * i;            pathFrame.reset();            if(i == 0){                pathFrame.moveTo(rectF.left, rectF.top + mFrameCornerRadius);                rectFArc.offsetTo(rectF.left, rectF.top);                pathFrame.arcTo(rectFArc, 180, 90);                pathFrame.lineTo(rectF.left + unitWidth, rectF.top);                pathFrame.lineTo(rectF.left + unitWidth, rectF.bottom);                pathFrame.lineTo(rectF.left + mFrameCornerRadius, rectF.bottom);                rectFArc.offsetTo(rectF.left, rectF.bottom - 2 * mFrameCornerRadius);                pathFrame.arcTo(rectFArc, 90, 90);            }else if(i == (mTexts.length - 1)){                pathFrame.moveTo(rectF.left + i * unitWidth, rectF.top);                pathFrame.lineTo(rectF.right - mFrameCornerRadius, rectF.top);                rectFArc.offsetTo(rectF.right - 2 * mFrameCornerRadius, rectF.top);                pathFrame.arcTo(rectFArc, 270, 90);                pathFrame.lineTo(rectF.right, rectF.bottom - mFrameCornerRadius);                rectFArc.offsetTo(rectF.right - 2 * mFrameCornerRadius, rectF.bottom - 2 * mFrameCornerRadius);                pathFrame.arcTo(rectFArc, 0, 90);                pathFrame.lineTo(rectF.left + i * unitWidth, rectF.bottom);            }else{                pathFrame.moveTo(left, rectF.top);                pathFrame.lineTo(left + unitWidth, rectF.top);                pathFrame.lineTo(left + unitWidth, rectF.bottom);                pathFrame.lineTo(left, rectF.bottom);            }            pathFrame.close();            if(!mIsGradient){                if(i == mSelectedIndex){                    curBackgroundColor = mColorBackgroundSelected;                    curTextColor = mColorTextSelected;                }else{                    curBackgroundColor = mColorBackgroundNormal;                    curTextColor = mColorTextNormal;                }            }            if(mIsGradient){                if(viewPagerPositionOffset != 0f){                    if(i == viewPagerPosition){                        curBackgroundColor = getEvaluateColor(viewPagerPositionOffset, mColorBackgroundSelected, mColorBackgroundNormal);                        curTextColor = getEvaluateColor(viewPagerPositionOffset, mColorTextSelected, mColorTextNormal);                    }else if(i == viewPagerPosition + 1){                        curBackgroundColor = getEvaluateColor(viewPagerPositionOffset, mColorBackgroundNormal, mColorBackgroundSelected);                        curTextColor = getEvaluateColor(viewPagerPositionOffset, mColorTextNormal, mColorTextSelected);                    }else{                        curBackgroundColor = mColorBackgroundNormal;                        curTextColor = mColorTextNormal;                    }                }else{                    if(i == mSelectedIndex){                        curBackgroundColor = mColorBackgroundSelected;                        curTextColor = mColorTextSelected;                    }else{                        curBackgroundColor = mColorBackgroundNormal;                        curTextColor = mColorTextNormal;                    }                }            }            paintBackground.setColor(curBackgroundColor);            if(curTouchedIndex == i){                paintBackground.setColor(getDarkColor(curBackgroundColor, TOUCHED_BACKGROUND_DARK_COEFFICIENT));            }            canvas.drawPath(pathFrame, paintBackground);            canvas.drawPath(pathFrame, paintFrame);            paintText.setColor(curTextColor);            canvas.drawText(mTexts[i], left + unitWidth / 2,rectF.centerY() + textCenterYOffset, paintText);        }    }    private int viewPagerPosition = -1;    private float viewPagerPositionOffset = 0f;    private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {        @Override        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {            if(mIsGradient){                mSelectedIndex = position;                viewPagerPosition = position;                viewPagerPositionOffset = positionOffset;                invalidate();            }        }        @Override        public void onPageScrollStateChanged(int state) {        }        @Override        public void onPageSelected(int position) {            if(mIsGradient){            }else{                SegmentControlView.this.setSelectedIndex(position);            }        }    }    private int getDarkColor(int color, float darkCoefficient){        int a = (color & 0xff000000) >>> 24;        int r = (color & 0x00ff0000) >>> 16;        int g = (color & 0x0000ff00) >>> 8;        int b = (color & 0x000000ff) >>> 0;        r = (int)(r * darkCoefficient);        g = (int)(g * darkCoefficient);        b = (int)(b * darkCoefficient);        return a << 24 | r << 16 | g << 8 | b;    }    private int getEvaluateColor(float fraction, int startColor, int endColor){        int a, r, g, b;        int sA = (startColor & 0xff000000) >>> 24;        int sR = (startColor & 0x00ff0000) >>> 16;        int sG = (startColor & 0x0000ff00) >>> 8;        int sB = (startColor & 0x000000ff) >>> 0;        int eA = (endColor & 0xff000000) >>> 24;        int eR = (endColor & 0x00ff0000) >>> 16;        int eG = (endColor & 0x0000ff00) >>> 8;        int eB = (endColor & 0x000000ff) >>> 0;        a = (int)(sA + (eA - sA) * fraction);        r = (int)(sR + (eR - sR) * fraction);        g = (int)(sG + (eG - sG) * fraction);        b = (int)(sB + (eB - sB) * fraction);        return a << 24 | r << 16 | g << 8 | b;    }    private boolean isStringArrayEmpty(String[] array){        return (array == null || array.length == 0);    }    private static int sp2px(Context context, float spValue) {          final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;          return (int) (spValue * fontScale + 0.5f);      }     private int getTextWidth(String text, Paint paint){        if(!TextUtils.isEmpty(text)){            return (int)(paint.measureText(text) + 0.5f);        }        return -1;    }    private int getTextHeight(String text, Paint paint){        if(!TextUtils.isEmpty(text)){            Rect textBounds = new Rect();            paint.getTextBounds(text, 0, text.length(), textBounds);            return textBounds.height();        }        return -1;    }}
2 0