自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ColorTraceTextView">
<attr name="origin_color" format="color" />
<attr name="change_color" format="color" />
</declare-styleable>
</resources>
自定义变色字体类
public class ColorTraceTextView extends AppCompatTextView {
// 字体默认颜色
private int originColor = 0xFF000000;
// 字体选中颜色
private int changeColor = 0xAAFF0000;
// 划动的位移
private float progress = 0f;
// 划动的方向
private Direction direction = Direction.LEFT_TO_RIGHT;
private Paint originPaint;
private Paint changePaint;
private Rect bounds;
public ColorTraceTextView(Context context) {
this(context, null);
}
public ColorTraceTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorTraceTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
obtainStyleAttrs(context, attrs);
}
private void obtainStyleAttrs(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ColorTraceTextView);
originColor = ta.getColor(R.styleable.ColorTraceTextView_origin_color, originColor);
changeColor = ta.getColor(R.styleable.ColorTraceTextView_change_color, changeColor);
originPaint = getPaint(originColor);
changePaint = getPaint(changeColor);
bounds = new Rect();
ta.recycle();
}
@Override
protected synchronized void onDraw(Canvas canvas) {
int middle = (int) (progress * getWidth());
if (direction == Direction.LEFT_TO_RIGHT) {
drawColorText(canvas, changePaint, 0, middle);
drawColorText(canvas, originPaint, middle, getWidth());
} else {
drawColorText(canvas, changePaint, getWidth() - middle, getWidth());
drawColorText(canvas, originPaint, 0, getWidth() - middle);
}
}
private void drawColorText(Canvas canvas, Paint paint, int start, int end) {
canvas.save();
// 截取变色的文本区域
canvas.clipRect(start, 0, end, getHeight());
// 获取文本内容
String text = getText().toString();
paint.getTextBounds(text, 0, text.length(), bounds);
int x = getWidth() / 2 - bounds.width() / 2;
// 基线
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();
}
private Paint getPaint(@ColorInt int color) {
Paint paint = new Paint();
// 设置画笔颜色
paint.setColor(color);
// 防止抖动
paint.setDither(true);
// 抗锯齿
paint.setAntiAlias(true);
// 设置字体大小
paint.setTextSize(getTextSize());
return paint;
}
public void setOriginColor(@ColorInt int color) {
this.originPaint.setColor(color);
}
public void setChangeColor(@ColorInt int color) {
this.changePaint.setColor(color);
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public void setProgress(float progress) {
this.progress = progress;
invalidate();
}
public enum Direction {
LEFT_TO_RIGHT, RIGHT_TO_LEFT
}
public int dp2px(int value) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value,
getResources().getDisplayMetrics());
}
}
在Activity中使用
public class MainActivity extends AppCompatActivity {
private String[] titles = {"推荐", "体育", "经济", "农业", "政治"};
private List<ColorTraceTextView> list;
private LinearLayout layout;
private ViewPager viewPager;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = new ArrayList<>();
layout = findViewById(R.id.ll_title);
viewPager = findViewById(R.id.view_page);
initLayout();
initViewPage();
}
private void initLayout() {
for (int i=0; i<titles.length; i++) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.weight = 1;
ColorTraceTextView traceTextView = new ColorTraceTextView(this);
traceTextView.setText(titles[i]);
traceTextView.setTextSize(20);
traceTextView.setPadding(0, traceTextView.dp2px(10), 0, traceTextView.dp2px(10));
traceTextView.setLayoutParams(params);
layout.addView(traceTextView);
list.add(traceTextView);
}
}
private void initViewPage() {
viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return PageFragment.instance(titles[position]);
}
@Override
public int getCount() {
return titles.length;
}
});
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
ColorTraceTextView left = list.get(position);
left.setDirection(ColorTraceTextView.Direction.RIGHT_TO_LEFT);
left.setProgress(1 - positionOffset);
if ((position + 1) < titles.length) {
ColorTraceTextView right = list.get(position + 1);
right.setDirection(ColorTraceTextView.Direction.LEFT_TO_RIGHT);
right.setProgress(positionOffset);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#FFD2D2D2" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_page"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>