效果展示
原理分析
1、一眼望去,我采用 :上面指示器利用 LinearLayout + 下面布局利用 ViewPager,采用其他方式肯定也是可以的,时间允许的话大家可以自行尝试
2、LinearLayout 布局中动态加载 多个"自定义 TextView"
3、监听 ViewPager 的滚动事件,实现 与 上面指示器的联动
源码分析
第一步:自定义 ColorTrackTextView 继承 TextView
在这里,大家可能有一个疑惑,凭什么继承 TextView , View不香吗?
我的答案是这样的:View的确可以,可是 TextView 更好,原因是 TextView 已经帮我们实现了 onMeasure 方法,不用我们自己写,其次 TextView 具有的一些属性我们可以充分使用,如TextSize,TextColor等,所以,我们选择TextView。
有人说继承View性能好,我就想问:性能这东西你有什么好方法测量吗?
第二步:编写自定义属性文件
这里主要有两个属性,原始颜色和改变后的颜色
扫描二维码关注公众号,回复:
12558610 查看本文章
<?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>
第三步:在布局文件中的使用,这里 我们采用的是动态加载,即:在代码里根据数据动态添加指示器,故下面是 线性布局+ViewPager
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll_indicator_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/vp_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
第四步:获取自定义属性,并编写相关代码
package com.example.view_day04;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.TextView;
import android.annotation.SuppressLint;
@SuppressLint("AppCompatCustomView")
public class ColorTrackTextView extends TextView {
private int mOriginColor = Color.BLACK;
private int mChangeColor = Color.RED;
//1、实现一个文字两种颜色 --- 绘制不变色字体的画笔
private Paint mOriginPaint;
//1、实现一个文字两种颜色 --- 绘制变色字体的画笔
private Paint mChangePaint;
//1、实现一个文字两种颜色 --- 当前进度
private float mCurrentProgress = 0.0f;
//2、实现不同朝向
public Direction mDirection = Direction.LEFT_TO_RIGHT;
public enum Direction{
LEFT_TO_RIGHT,RIGHT_TOLEFT
}
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初始化画笔
*@Author yiqi
*@created 2021/2/26 15:35
*@param
*@return
*/
private void initPaint(Context context, AttributeSet attrs){
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackTextView);
int originColor = typedArray.getColor(R.styleable.ColorTrackTextView_originColor,mOriginColor);
int changeColor = typedArray.getColor(R.styleable.ColorTrackTextView_changeColor,mChangeColor);
mOriginPaint = getPaintByColor(originColor);
mChangePaint = getPaintByColor(changeColor);
typedArray.recycle();
}
/**
*1、根据颜色获取画笔
*@Author yiqi
*@created 2021/2/26 15:48
*@param
*@return
*/
private Paint getPaintByColor(int color) {
Paint paint = new Paint();
//设置抗锯齿
paint.setAntiAlias(true);
//设置防抖动
paint.setDither(true);
//设置颜色
paint.setColor(color);
//设置字体大小 就是TextView的字体大小
paint.setTextSize(getTextSize());
return paint;
}
//1、一个文字两种颜色
//利用canvas.clipRect(rect); 可以裁剪 左边用一个画笔去画 右边用另一个画笔去画 不断的改变中间值
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas); //不能执行这个,要不然会执行 TextView 的 onDraw() 方法,用他的方式把文字画出来
//canvas.clipRect(); 裁剪区域
//根据进度把中间值算出来
int middle = (int) (mCurrentProgress*getWidth());
if (mDirection == Direction.LEFT_TO_RIGHT){
//绘制不变色的
drawText(canvas,mOriginPaint,middle,getWidth());
//绘制变色的
drawText(canvas,mChangePaint,0,middle);
}else {
// System.out.println("middle=" +middle + "__getwidth()-middle=" + (getWidth()-middle));
//绘制不变色的
drawText(canvas,mOriginPaint,0,getWidth() - middle);
//绘制变色的
drawText(canvas,mChangePaint,getWidth() - middle,getWidth());
}
}
/**
*绘制 Text
*@Author yiqi
*@created 2021/2/26 17:40
*@param
*@return
*/
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();
//获取字体基线
Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
int dy = (fontMetricsInt.bottom - fontMetricsInt.top)/2 - fontMetricsInt.bottom;
int baseLine = getHeight()/2 + dy;
//获取字体的宽度
Rect bounds = new Rect();
paint.getTextBounds(text,0,text.length(),bounds);
int x = getWidth()/2 - bounds.width()/2;
canvas.drawText(text,x,baseLine,paint); //这么画,其实还是只有一种颜色
canvas.restore();
}
public void setDirection(Direction direction){
this.mDirection = direction;
}
public void setCurrentProgress(float currentProgress){
this.mCurrentProgress = currentProgress;
System.out.println("invalidate()被调用了");
invalidate();
}
public void setChangeColor(int changeColor){
this.mChangeColor = changeColor;
}
public void setOriginColor(int originColor){
this.mOriginColor = originColor;
}
}
第五步:调用
package com.example.view_day04;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import java.util.ArrayList;
import java.util.List;
public class ViewPagerActivity extends Activity {
private String[] items = {"直播","推荐","视频","图片","段子","精华"};
private List<ColorTrackTextView> mIndicators;
private LinearLayout ll_indicator_view;
private ViewPager vp_view_pager;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewpager);
initView();
initData();
}
private void initView() {
ll_indicator_view = findViewById(R.id.ll_indicator_view);
vp_view_pager = findViewById(R.id.vp_view_pager);
}
private void initData() {
mIndicators = new ArrayList<>();
//初始化可变色指示器
for (int i = 0; i < items.length; i++) {
ColorTrackTextView colorTrackTextView = new ColorTrackTextView(this);
//设置位置参数
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.weight = 1;
colorTrackTextView.setLayoutParams(params);
//设置文字的基本信息
colorTrackTextView.setText(items[i]);
colorTrackTextView.setTextSize(20);
colorTrackTextView.setChangeColor(Color.RED);
//加入到LinearLayout容器中
ll_indicator_view.addView(colorTrackTextView);
//加入到集合
mIndicators.add(colorTrackTextView);
}
//初始化ViewPager
vp_view_pager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return items.length;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
TextView textView =new TextView(getApplicationContext());
textView.setText(items[position]);
container.addView(textView);
return textView;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
});
//监听ViewPager的事件
vp_view_pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
System.out.println("position=" + position + "positionOffset+" + positionOffset + "mIndicators.get(position)=" + mIndicators.get(position));
//1、左边
ColorTrackTextView left = mIndicators.get(position);
left.setDirection(ColorTrackTextView.Direction.RIGHT_TOLEFT);
left.setCurrentProgress(1-positionOffset);
//右边
//1、左边
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) {
}
});
}
}
这样,你就成功了,是不是很简单
最后,附上源码:自定义文字变色效果