1. 说明
前边我们学习了自定义View入门、自定义TextView、仿QQ运动步数效果,那么今天我们就来实现下这个效果 —— 玩转字体变色,效果图如下:
2. 思路
不能直接使用TextView来实现。因为系统提供的TextView只能够显示一种颜色,所以在这里需要自定义View;
自定义View该继承谁?
extends View:可以实现,但是需要我们手动去复写onMeasure()、onDraw()方法,比较麻烦;
extends TextView:可以实现,onMeasure()方法不需要实现,并且TextView自带有textSize()、textColor(),不需要我们自己去写自定义属性,可以减少一些逻辑,并且也可以减少代码量。
我们需要做的步骤就是:
1>:一个文字两种颜色,两个画笔去画;左边用红色画笔去画,右边用黑色画笔去画,需要切割;
2>:能够从左到右,从右到左;
3>:整合到ViewPager;
3. 代码如下
自定义ColorTrackTextView.java代码如下
/**
* Email: 2185134304@qq.com
* Created by JackChen 2018/3/18 16:18
* Version 1.0
* Params:
* Description: 玩转字体变色
*/
public class ColorTrackTextView extends TextView {
// 1. 实现一个文字两种颜色 - 绘制不变色字体的画笔
private Paint mOriginPaint;
// 1. 实现一个文字两种颜色 - 绘制变色字体的画笔
private Paint mChangePaint;
// 1. 实现一个文字两种颜色 - 当前的进度
private float mCurrentProgress = 0.0f;
// 2.实现不同朝向
private Direction mDirection = Direction.LEFT_TO_RIGHT;
public enum Direction{
LEFT_TO_RIGHT,RIGHT_TO_LEFT
}
public ColorTrackTextView(Context context) {
this(context, null);
}
public ColorTrackTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorTrackTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint(context, attrs);
}
/**
* 1.1 初始化画笔
*/
private void initPaint(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackTextView);
int originColor = array.getColor(R.styleable.ColorTrackTextView_originColor, getTextColors().getDefaultColor());
int changeColor = array.getColor(R.styleable.ColorTrackTextView_changeColor, getTextColors().getDefaultColor());
mOriginPaint = getPaintByColor(originColor);
mChangePaint = getPaintByColor(changeColor);
// 回收
array.recycle();
}
/**
* 1.根据颜色获取画笔
*/
private Paint getPaintByColor(int color) {
Paint paint = new Paint();
// 设置颜色
paint.setColor(color);
// 设置抗锯齿
paint.setAntiAlias(true);
// 防抖动
paint.setDither(true);
// 设置字体的大小 就是TextView的字体大小
paint.setTextSize(getTextSize());
return paint;
}
// 1. 一个文字两种颜色
// 利用clipRect的API 可以裁剪 左边用一个画笔去画 右边用另一个画笔去画 不断的改变中间值
@Override
protected void onDraw(Canvas canvas) {
// 我们不要用系统的onDraw()方法来画,我们自己定义画文字的方法
// super.onDraw(canvas);
// 根据进度把中间值算出来
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);
}
}
/**
* 绘制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;
Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
// dy
int dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
// 基线baseLine
int baseLine = getHeight() / 2 + dy;
canvas.drawText(text, x, baseLine, paint);
canvas.restore();
}
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);
}
}
ViewPagerActivity.java代码如下:
/**
* Email: 2185134304@qq.com
* Created by JackChen 2018/3/18 17:07
* Version 1.0
* Params:
* Description: 左右滑动的变色字体
*/
public class ViewPagerActivity extends AppCompatActivity {
private String[] items = {"直播", "推荐", "视频", "图片", "段子", "精华"};
// private LinearLayout mIndicatorContainer;// 变成通用的
private List<ColorTrackTextView> mIndicators ;
private LinearLayout indicator_view; // 变成通用的
private ViewPager view_pager;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager);
mIndicators = new ArrayList<>() ;
// 顶部文字
indicator_view = (LinearLayout) findViewById(R.id.indicator_view);
view_pager = (ViewPager) findViewById(R.id.view_pager);
// 初始化可变色的指示器
initIndicator() ;
initViewPager() ;
}
private void initViewPager() {
view_pager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return ItemFragment.newInstance(items[position]);
}
@Override
public int getCount() {
return items.length;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
});
view_pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// position: 代表当前位置 0、1、2
// positionOffset: 代表滚动的百分比 值是 0-1、
// 从左到右 滚动
ColorTrackTextView left = mIndicators.get(position);
left.setDirection(ColorTrackTextView.Direction.RIGHT_TO_LEFT);
left.setCurrentProgress(1 - positionOffset);
try {
// 从右到左 滚动
ColorTrackTextView right = mIndicators.get(position + 1);
right.setDirection(ColorTrackTextView.Direction.LEFT_TO_RIGHT);
right.setCurrentProgress(positionOffset);
}catch (Exception e){
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
/**
* 初始化可变色的指示器
*/
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容器
indicator_view.addView(colorTrackTextView);
// 加入集合
mIndicators.add(colorTrackTextView);
}
}
}
activity_View_pager.xml布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:id="@+id/indicator_view"
android:layout_height="wrap_content"/>
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/view_pager"
android:layout_weight="1"
/>
</LinearLayout>
attrs.xml资源文件如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ColorTrackTextView">
<!-- 不变的颜色 -->
<attr name="originColor" format="color"/>
<!-- 改变的颜色 -->
<attr name="changeColor" format="color"/>
</declare-styleable>
</resources>
具体代码已上传至github:
https://github.com/shuai999/View_day04_2.git