一、概述

继续学习自定义view,主要还是讲解画笔,实现的功能是用两种颜色的画笔画文字,根据滑动的偏移量,实现颜色过渡,可以用于页面的指示器。 效果图:

​指示器.gif​


二、思路分析

有两种颜色,一种默认颜色,一种选中的颜色(改变的颜色),一个文本两种不同颜色的画笔去画,画的起始点和结束点(也就是文字的绘制矩形区域)根据左滑或者右滑的偏移量而改变。

2.1继承自textView自定义默认画笔和改变颜色画笔的颜色属性
//自定义属性
public ColorTrackTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ColorTrackTextView);
mOrignColor = a.getColor(R.styleable.ColorTrackTextView_originColor,mOrignColor);
mChangeColor = a.getColor(R.styleable.ColorTrackTextView_changeColor,mChangeColor);
a.recycle();
mChangePaint = getPaintByColor(mChangeColor);
mOrignPaint = getPaintByColor(mOrignColor);
}

2.2在ondraw方法里面绘制

// 1. 一个文字两种颜色
// 利用clipRect的API 可以裁剪 左边用一个画笔去画 右边用另一个画笔去画 不断的改变中间值
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
// canvas.clipRect(); 裁剪区域
// 根据进度把中间值算出来
int middle = (int) (mCurrentProgress * getWidth());

// 从左变到右
if(mDirection == Direction.LEFT_TO_RIGHT) { // 左边是红色右边是黑色
// 绘制变色
drawText(canvas, mChangePaint , 0, middle);
drawText(canvas, mOriginPaint, middle, getWidth());
}else{
// 右边是红色左边是黑色
drawText(canvas, mChangePaint, getWidth()-middle, getWidth());
// 绘制变色
drawText(canvas, mOriginPaint, 0, getWidth()-middle);
}
}

其中的枚举常量Direction.LEFT_TO_RIGHT,表示颜色从左往右改变,当mCurrentProgress为1时文字完全变为改变的颜色,另外的一种情况就是相反的,颜色从右往左变化,由改变颜色变为默认颜色。
drawText方法的代码如下:

/**
* 绘制Text
* @param canvas
* @param paint
* @param start
* @param end
*/
private void drawText(Canvas canvas, Paint paint, int start, int end) {
canvas.save();
// 绘制不变色
Rect rect = new Rect(start, 0, end, getHeight());
canvas.clipRect(rect);
String text = getText().toString();
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
// 获取字体的宽度
int x = getWidth() / 2 - bounds.width() / 2;
// 基线baseLine
Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
int dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
int baseLine = getHeight() / 2 + dy;
canvas.drawText(text, x, baseLine, paint);// 这么画其实还是只有一种颜色
canvas.restore();
}

2.3其他方法:

public void setDirection(Direction direction){
this.mDirection = direction;
}

public void setCurrentProgress(float currentProgress){
this.mCurrentProgress = currentProgress;
invalidate();
}

public void setChangeColor(int changeColor) {
this.mChangePaint.setColor(changeColor);
}

public void setOriginColor(int originColor) {
this.mOriginPaint.setColor(originColor);
}

暴露给用户去设置默认颜色,和选中颜色。通过调用setCurrentProgress方法,不断的动态传入 方法中不断调用ondraw方法,实现效果。
看下运行效果图:


​GIF.gif​


2.4集成到viewpager

比较简单,就不做具体分析,只看下关键代码:

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
Log.e("TAG","position -> "+position +" positionOffset -> "+positionOffset);
// position 代表当前的位置
// positionOffset 代表滚动的 0 - 1 百分比

if (positionOffset > 0) {
// 获取左边
ColorTrackTextView left = mIndicators.get(position);
// 设置朝向
left.setDirection(ColorTrackTextView.Direction.DIRECTION_RIGHT);
//positionOffset从0变化到1
left.setCurrentProgress(1 - positionOffset);
try {
// 获取右边
ColorTrackTextView right = mIndicators.get(position + 1);
right.setDirection(ColorTrackTextView.Direction.DIRECTION_LEFT);
right.setCurrentProgress(positionOffset);
} catch (Exception e) {

}
}
}

@Override
public void onPageSelected(int position) {

}

@Override
public void onPageScrollStateChanged(int state) {

}
});
// 默认一进入就选中第一个
ColorTrackTextView left = mIndicators.get(0);
left.setDirection(ColorTrackTextView.Direction.DIRECTION_RIGHT);
left.setCurrentProgress(1);
}

给viewpager添加监听,在页面滑动的时候调用setCurrentProgress方法绘制文字,头部指示器用LinearLayout添加。代码如下:

/**
* 初始化可变色的指示器
*/
private void initIndicator() {
for (int i = 0; i < items.length; i++) {
// 动态添加颜色跟踪的TextView
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.weight = 1;
ColorTrackTextView colorTrackTextView = new ColorTrackTextView(this);
// 设置颜色
colorTrackTextView.setTextSize(20);
colorTrackTextView.setChangeColor(Color.RED);
colorTrackTextView.setText(items[i]);
colorTrackTextView.setLayoutParams(params);
// 把新的加入LinearLayout容器
mIndicatorContainer.addView(colorTrackTextView);
// 加入集合
mIndicators.add(colorTrackTextView);
}
}

分析完毕

三、结语

参考链接:​​打造炫酷通用的ViewPager指示器 - Adapter模式适配所有​​​代码地址:​​http://pan.baidu.com/s/1mhRghnE​

作者:临窗听雨

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。