android仿今日头条之字体颜色随ViewPager的滑动步伐而改变

事先说好这个是转载的人家鸿洋大神的, Android 自定义控件玩转字体变色 打造炫酷ViewPager指示器


主要用到它写的一个自定义View,名字叫ColorTrackView  


接下来是自定义控件的代码:


自定义属性如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="is_rtl">false</bool>

    <attr name="text" format="string" />
    <attr name="text_size" format="dimension" />
    <attr name="text_origin_color" format="color|reference" />
    <attr name="text_change_color" format="color|reference" />
    <attr name="progress" format="float" />
    <attr name="direction">
        <enum name="left" value="0" />
        <enum name="right" value="1" />
        <enum name="top" value="2" />
        <enum name="bottom" value="3" />
    </attr>

    <declare-styleable name="ColorTrackView">
        <attr name="text" />
        <attr name="text_size" />
        <attr name="text_origin_color" />
        <attr name="text_change_color" />
        <attr name="progress" />
        <attr name="direction" />
    </declare-styleable>
</resources>

自定义代码如下:

public class ColorTrackView extends View{
    private int mTextStartX;
    private int mTextStartY;

    public enum Direction {
        LEFT, RIGHT, TOP, BOTTOM;
    }

    private int mDirection = DIRECTION_LEFT;

    private static final int DIRECTION_LEFT = 0;
    private static final int DIRECTION_RIGHT = 1;
    private static final int DIRECTION_TOP = 2;
    private static final int DIRECTION_BOTTOM = 3;

    public void setDirection(int direction) {
        mDirection = direction;
    }

    private String mText = "张鸿洋";
    private Paint mPaint;
    private int mTextSize = sp2px(30);

    private int mTextOriginColor = 0xff333000;
    private int mTextChangeColor = 0xffd84040;

    private Rect mTextBound = new Rect();
    private int mTextWidth;
    private int mTextHeight;

    private float mProgress;

    public ColorTrackView(Context context) {
        super(context, null);
    }

    public ColorTrackView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        TypedArray ta = context.obtainStyledAttributes(attrs,
                R.styleable.ColorTrackView);
        mText = ta.getString(R.styleable.ColorTrackView_text);
        mTextSize = ta.getDimensionPixelSize(
                R.styleable.ColorTrackView_text_size, mTextSize);
        mTextOriginColor = ta.getColor(
                R.styleable.ColorTrackView_text_origin_color, mTextOriginColor);
        mTextChangeColor = ta.getColor(
                R.styleable.ColorTrackView_text_change_color, mTextChangeColor);
        mProgress = ta.getFloat(R.styleable.ColorTrackView_progress, 0);

        mDirection = ta
                .getInt(R.styleable.ColorTrackView_direction, mDirection);

        ta.recycle();

        mPaint.setTextSize(mTextSize);

    }

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

        measureText();

        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);

        mTextStartX = getMeasuredWidth() / 2 - mTextWidth / 2;
        mTextStartY = getMeasuredHeight() / 2 - mTextHeight / 2;
    }

    private int measureHeight(int measureSpec) {
        int mode = MeasureSpec.getMode(measureSpec);
        int val = MeasureSpec.getSize(measureSpec);
        int result = 0;
        switch (mode) {
            case MeasureSpec.EXACTLY:
                result = val;
                break;
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED:
                result = mTextBound.height();
                result += getPaddingTop() + getPaddingBottom();
                break;
        }
        result = mode == MeasureSpec.AT_MOST ? Math.min(result, val) : result;
        return result;
    }

    private int measureWidth(int measureSpec) {
        int mode = MeasureSpec.getMode(measureSpec);
        int val = MeasureSpec.getSize(measureSpec);
        int result = 0;
        switch (mode) {
            case MeasureSpec.EXACTLY:
                result = val;
                break;
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED:
                // result = mTextBound.width();
                result = mTextWidth;
                result += getPaddingLeft() + getPaddingRight();
                break;
        }
        result = mode == MeasureSpec.AT_MOST ? Math.min(result, val) : result;
        return result;
    }

    private void measureText() {
        mTextWidth = (int) mPaint.measureText(mText);
        Paint.FontMetrics fm = mPaint.getFontMetrics();
        mTextHeight = (int) Math.ceil(fm.descent - fm.top);

        mPaint.getTextBounds(mText, 0, mText.length(), mTextBound);
        mTextHeight = mTextBound.height();
    }

    public void reverseColor() {
        int tmp = mTextOriginColor;
        mTextOriginColor = mTextChangeColor;
        mTextChangeColor = tmp;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int r = (int) (mProgress * mTextWidth + mTextStartX);
        int t = (int) (mProgress * mTextHeight + mTextStartY);

        if (mDirection == DIRECTION_LEFT) {
            drawChangeLeft(canvas, r);
            drawOriginLeft(canvas, r);
        } else if (mDirection == DIRECTION_RIGHT) {
            drawOriginRight(canvas, r);
            drawChangeRight(canvas, r);
        } else if (mDirection == DIRECTION_TOP) {
            drawOriginTop(canvas, t);
            drawChangeTop(canvas, t);
        } else {
            drawOriginBottom(canvas, t);
            drawChangeBottom(canvas, t);
        }

    }

    private boolean debug = false;

    private void drawText_h(Canvas canvas, int color, int startX, int endX) {
        mPaint.setColor(color);
        if (debug) {
            mPaint.setStyle(Paint.Style.STROKE);
            canvas.drawRect(startX, 0, endX, getMeasuredHeight(), mPaint);
        }
        canvas.save(Canvas.CLIP_SAVE_FLAG);
        canvas.clipRect(startX, 0, endX, getMeasuredHeight());// left, top,
        // right, bottom
        canvas.drawText(mText, mTextStartX,
                getMeasuredHeight() / 2
                        - ((mPaint.descent() + mPaint.ascent()) / 2), mPaint);
        canvas.restore();
    }

    private void drawText_v(Canvas canvas, int color, int startY, int endY) {
        mPaint.setColor(color);
        if (debug) {
            mPaint.setStyle(Paint.Style.STROKE);
            canvas.drawRect(0, startY, getMeasuredWidth(), endY, mPaint);
        }

        canvas.save(Canvas.CLIP_SAVE_FLAG);
        canvas.clipRect(0, startY, getMeasuredWidth(), endY);// left, top,
        canvas.drawText(mText, mTextStartX,
                getMeasuredHeight() / 2
                        - ((mPaint.descent() + mPaint.ascent()) / 2), mPaint);
        canvas.restore();
    }

    private void drawChangeLeft(Canvas canvas, int r) {
        drawText_h(canvas, mTextChangeColor, mTextStartX,
                (int) (mTextStartX + mProgress * mTextWidth));
    }

    private void drawOriginLeft(Canvas canvas, int r) {
        drawText_h(canvas, mTextOriginColor, (int) (mTextStartX + mProgress
                * mTextWidth), mTextStartX + mTextWidth);
    }

    private void drawChangeRight(Canvas canvas, int r) {
        drawText_h(canvas, mTextChangeColor,
                (int) (mTextStartX + (1 - mProgress) * mTextWidth), mTextStartX
                        + mTextWidth);
    }

    private void drawOriginRight(Canvas canvas, int r) {
        drawText_h(canvas, mTextOriginColor, mTextStartX,
                (int) (mTextStartX + (1 - mProgress) * mTextWidth));
    }

    private void drawChangeTop(Canvas canvas, int r) {
        drawText_v(canvas, mTextChangeColor, mTextStartY,
                (int) (mTextStartY + mProgress * mTextHeight));
    }

    private void drawOriginTop(Canvas canvas, int r) {
        drawText_v(canvas, mTextOriginColor, (int) (mTextStartY + mProgress
                * mTextHeight), mTextStartY + mTextHeight);
    }

    private void drawChangeBottom(Canvas canvas, int t) {
        drawText_v(canvas, mTextChangeColor,
                (int) (mTextStartY + (1 - mProgress) * mTextHeight),
                mTextStartY + mTextHeight);
    }

    private void drawOriginBottom(Canvas canvas, int t) {
        drawText_v(canvas, mTextOriginColor, mTextStartY,
                (int) (mTextStartY + (1 - mProgress) * mTextHeight));
    }

    public float getProgress() {
        return mProgress;
    }

    public void setProgress(float progress) {
        this.mProgress = progress;
        invalidate();
    }

    public int getTextSize() {
        return mTextSize;
    }

    public void setTextSize(int mTextSize) {
        this.mTextSize = mTextSize;
        mPaint.setTextSize(mTextSize);
        requestLayout();
        invalidate();
    }

    public void setText(String text) {
        this.mText = text;
        requestLayout();
        invalidate();
    }

    public int getTextOriginColor() {
        return mTextOriginColor;
    }

    public void setTextOriginColor(int mTextOriginColor) {
        this.mTextOriginColor = mTextOriginColor;
        invalidate();
    }

    public int getTextChangeColor() {
        return mTextChangeColor;
    }

    public void setTextChangeColor(int mTextChangeColor) {
        this.mTextChangeColor = mTextChangeColor;
        invalidate();
    }

    private int dp2px(float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, getResources().getDisplayMetrics());
    }

    private int sp2px(float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                dpVal, getResources().getDisplayMetrics());
    }

    private static final String KEY_STATE_PROGRESS = "key_progress";
    private static final String KEY_DEFAULT_STATE = "key_default_state";

    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putFloat(KEY_STATE_PROGRESS, mProgress);
        bundle.putParcelable(KEY_DEFAULT_STATE, super.onSaveInstanceState());
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {

        if (state instanceof Bundle) {
            Bundle bundle = (Bundle) state;
            mProgress = bundle.getFloat(KEY_STATE_PROGRESS);
            super.onRestoreInstanceState(bundle
                    .getParcelable(KEY_DEFAULT_STATE));
            return;
        }
        super.onRestoreInstanceState(state);
    }
}

接下来是使用:

<com.landi.zsg.customerview.ColorTrackView
    android:id="@+id/tv_already_completed_orders"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:gravity="center"
    zgy:progress="0"
    zgy:text_size="@dimen/item_area_text_size"
    zgy:text_change_color="@color/tv_color_prefecture_red"
    zgy:text_origin_color="@color/tv_color_black"
    zgy:text="已完成订单" />
上面代码中的text_change_color是自定义改变后的颜色,text_origin_color是定义改变前的颜色,progress可以理解为改变的状态,当这个属性的值为0代表没有改变,如果等于1代表已经改变了,也就是颜色改变了


别忘了添加xml头部:

xmlns:zgy="http://schemas.android.com/apk/res-auto"

使用的代码:

/**
 * 初始化滑动布局
 */
private void initViewPagerFragment(){
    fragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

        @Override
        public int getCount() {
            return fragmentList.size();
        }
    };
    my_orders_viewpager.setAdapter(fragmentPagerAdapter);
    my_orders_viewpager.setCurrentItem(0);

    my_orders_viewpager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if (positionOffset > 0) {
                ColorTrackView left = mTabs.get(position);
                ColorTrackView right = mTabs.get(position + 1);
                left.setDirection(1);
                right.setDirection(0);
                left.setProgress(1 - positionOffset);
                right.setProgress(positionOffset);
            }
            LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) view_tab_line.getLayoutParams();
            lp.leftMargin = (int) ((position + positionOffset) * mTabLineWidth + (mTabLineWidth * 0.25));
            view_tab_line.setLayoutParams(lp);
        }

        @Override
        public void onPageSelected(int position) {
            endPosition = position;
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            if(state == 0){
                tv_already_completed_orders.setProgress(0);
                tv_already_apply_for_sales_return.setProgress(0);
                if(endPosition == 0){
                    tv_already_completed_orders.setProgress(1);
                }else if(endPosition == 1){
                    tv_already_apply_for_sales_return.setProgress(1);
                }
            }
        }
    });
}

这个东西存在一个小小的问题,就是会颜色改变乱掉,可以按以下方法处理,定义一个整型我代码中的endPosition,在onPageSelected中将position的值赋给endPosition,也就是当前是第几项endPosition就是几,然后再在onPageScrolllStateChanged先将目前所有项的progress的值变为0,也就是给所有的项清除颜色,然后再判断,当state == 0的时候,判断当前的endPosition是哪个就给哪个设置progress为1即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值