事先说好这个是转载的人家鸿洋大神的, 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即可