zoukankan      html  css  js  c++  java
  • 自定义控件之SegmentControlView

    SegmentControlView配合PageView使用

    效果图

    核心代码

    package com.example.segmentcontrolview;
    
    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;
    
    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;
        }
    }
    SegmentControlView

    自定义属性之attrs_segment_control_view.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="SegmentControlView">
            <attr name="scv_BackgroundSelectedColor" format="reference|color" />
            <attr name="scv_BackgroundNormalColor" format="reference|color" />
            <attr name="scv_TextSelectedColor" format="reference|color" />
            <attr name="scv_TextNormalColor" format="reference|color" />
            <attr name="scv_FrameColor" format="reference|color" />
            <attr name="scv_FrameWidth" format="reference|dimension" />
            <attr name="scv_FrameCornerRadius" format="reference|dimension" />
            <attr name="scv_TextSize" format="reference|dimension" />
            <attr name="scv_TextArray" format="reference" />
            <attr name="scv_SelectedIndex" format="reference|integer" />
            <attr name="scv_SegmentPaddingHorizontal" format="reference|dimension" />
            <attr name="scv_SegmentPaddingVertical" format="reference|dimension" />
            <attr name="scv_Gradient" format="reference|boolean" />
        </declare-styleable>
    </resources>
    attrs_segment_control_view.xml

    使用Demo

    package com.example.segmentcontrolview;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.support.v4.view.ViewPager;
    public class MainActivity extends Activity {
    
        public static MainActivity mainActivity;
        private SegmentControlView segmentcontrolview;
        private ViewPager viewpager;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
          
            mainActivity=this;
            segmentcontrolview = (SegmentControlView) this.findViewById(R.id.scv);
            segmentcontrolview.setOnSegmentChangedListener(new SegmentControlView.OnSegmentChangedListener() {
                @Override
                public void onSegmentChanged(int newSelectedIndex) {
                    if(viewpager != null){
                        viewpager.setCurrentItem(newSelectedIndex, false);
                    }
                }
            });
            viewpager = (ViewPager)this.findViewById(R.id.vp);
            viewpager.setAdapter(new OptionPagerAdapter());
            segmentcontrolview.setViewPager(viewpager);
        }
    }
    MainActivity.java
    package com.example.segmentcontrolview;
    
    import java.util.ArrayList;
    
    import android.support.v4.view.PagerAdapter;
    import android.support.v4.view.ViewPager;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.Toast;
    
    public class OptionPagerAdapter extends PagerAdapter implements OnClickListener {
    
        private ArrayList<View> pages = new ArrayList<View>();
        
        public OptionPagerAdapter() {
            LayoutInflater mLi = LayoutInflater.from(MainActivity.mainActivity);
            View view1 = mLi.inflate(R.layout.view_option1, null);
            View view2 = mLi.inflate(R.layout.view_option2, null);
            View view3 = mLi.inflate(R.layout.view_option3, null);
            view3.findViewById(R.id.option3_btn_start).setOnClickListener(this);
            pages.add(view1);
            pages.add(view2);
            pages.add(view3);
        }
    
        @Override
        public int getCount() {
            return pages.size();
        }
    
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }
    
    
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View page = pages.get(position);
            if (page != null) {
                container.addView(page);
            }
            return page;
            
        }
    
        @Override
        public void destroyItem(View container, int position, Object object) {
            ((ViewPager) container).removeView((View) object);
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return "";
        }
    
        @Override
        public int getItemPosition(Object object) {
            return super.getItemPosition(object);
        }
    
        @Override
        public void onClick(View v) {
            int id =v.getId();
            if(id==R.id.option3_btn_start){
                Toast.makeText(MainActivity.mainActivity,  "生活的极致,必是素与简", Toast.LENGTH_SHORT).show();
            }
        }
    }
    OptionPagerAdapter

    布局文件activity_main.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:app="http://schemas.android.com/apk/res-auto"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:background="#ffffffff"
                  android:orientation="vertical"
                  android:paddingBottom="@dimen/activity_vertical_margin"
                  android:paddingLeft="@dimen/activity_horizontal_margin"
                  android:paddingRight="@dimen/activity_horizontal_margin"
                  android:paddingTop="@dimen/activity_vertical_margin">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="包夜类型"
            android:textColor="#bb2CA99F"
            android:textSize="14sp"/>
    
        <View
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:layout_marginBottom="8dp"
            android:background="#33555555"/>
    
        <com.example.segmentcontrolview.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"/>
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="填充类型"
            android:textColor="#bb2CA99F"
            android:textSize="14sp"/>
    
        <View
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:layout_marginBottom="8dp"
            android:background="#33555555"/>
    
        <com.example.segmentcontrolview.SegmentControlView
            android:id="@+id/scv"
            android:layout_width="match_parent"
            android:layout_height="36dp"
            android:layout_marginTop="5dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            app:scv_FrameCornerRadius="3dp"
            app:scv_FrameWidth="1dp"
            app:scv_Gradient="true"
            app:scv_SegmentPaddingVertical="5dp"
            app:scv_TextArray="@array/segment_control_arrays_1"/>
    
        <android.support.v4.view.ViewPager
            android:id="@+id/vp"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginTop="5dp"
            android:layout_weight="1"/>
    </LinearLayout>
    <?xml version="1.0" encoding="UTF-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#ffffffff" >
    
        <TextView
            android:id="@+id/lbl_start_word"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_marginTop="100dp"
            android:padding="20sp"
            android:text="@string/option1"
            android:textColor="@color/colorPrimaryDark"
            android:textSize="36sp" />
    
    </RelativeLayout>
  • 相关阅读:
    Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException
    idea 设置svn忽略 .idea内的文件
    使用JDBC连接MySql时出现:The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration
    问题:SpringBoot访问不到Controller
    JAVA 并发编程-多个线程之间共享数据
    Data时间格式化
    wow.js中各种特效对应的类名(滚动效果)
    [从零开始搭网站七]CentOS上安装Mysql
    [从零开始搭网站六]为域名申请免费SSL证书(https),并为Tomcat配置https域名所用的多SSL证书
    [从零开始搭网站五]http网站Tomcat配置web.xml和server.xml
  • 原文地址:https://www.cnblogs.com/huangzhen22/p/6514974.html
Copyright © 2011-2022 走看看