自定义view|自定义view - 玩转字体变色

1. 思路分析
自定义View步骤:
1>:values__attrs.xml,定义自定义属性;
2>:在第三个构造方法中获取自定义属性;
3>:onMeasure【不是必须的】;
4>:onDraw:绘制代码全都在onDraw中写的;
技术分析:
不能继承TextView,因为系统的TextView只能有一种颜色,需要ColorTraceTextView,继承TextView,而不是继承View,原因是:
1>:继承TextView不用自己手动实现onMeasure、onDraw,系统已经实现了;
2>:textColor、textSize方法TextView已经实现了,不用自己实现;
思路分析:
一个文字两种颜色,用两个画笔来画:
1>:左边用红色画笔,右边用黑色画笔;
2>:能从左到右【左黑右红】,也能从右到左【左红右黑】;
3>:最后整合到ViewPager中;
2. 效果如下
自定义view|自定义view - 玩转字体变色
文章图片
图片.png
【自定义view|自定义view - 玩转字体变色】从左边向右边滑动:黑变红;
从右边向左边滑动:红变黑;
3. 代码如下
1>:attrs


2>:ColorTrackTextView
/** * ================================================ * Email: 2185134304@qq.com * Created by Novate 2018/12/29 10:31 * Version 1.0 * Params: * Description:玩转字体变色 * ================================================ */public class ColorTrackTextView extends TextView {// 绘制不变色的画笔 private Paint mOriginPaint ; // 绘制变色的画笔 private Paint mChangePaint ; // 当前进度 文字左边一半是黑色,右边一半是红色 private float mCurrentProgress = 0.0f; // 不同的朝向 private Direction mDirection = LEFT_TO_RIGHT; public enum Direction{ LEFT_TO_RIGHT , RIGHT_TO_LEFT }public ColorTrackTextView(Context context) { this(context,null); }public ColorTrackTextView(Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); }public ColorTrackTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initPaint(context,attrs) ; }/** * 初始化画笔 */ private void initPaint(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackTextView); // 此处颜色传递默认值,防止你在布局文件中没有指定颜色 int originColor = typedArray.getColor(R.styleable.ColorTrackTextView_originColor,getTextColors().getDefaultColor()); int changeColor = typedArray.getColor(R.styleable.ColorTrackTextView_changeColor,getTextColors().getDefaultColor()); // 不变色的画笔 mOriginPaint = getPaintByColor(originColor); // 变色的画笔 mChangePaint = getPaintByColor(changeColor); }/** * 根据颜色获取画笔 */ private Paint getPaintByColor(int color) { Paint paint = new Paint() ; // 给画笔设置颜色 paint.setColor(color); // 设置抗锯齿 paint.setAntiAlias(true); // 仿抖动 paint.setDither(true); // 设置文字大小 paint.setTextSize(getTextSize()); return paint; }/** * 一个文字两种颜色 *利用 clipRect 的API,裁剪,左边用一个画笔去画,右边用另一个画笔去画,不断地改变中间值 */ @Override protected void onDraw(Canvas canvas) { // 这里必须注释,这个是TextView自身的绘制,因为需要自己去画文字,所以需要注释 // super.onDraw(canvas); // 获取中间位置 int middle = (int) (mCurrentProgress*getWidth()); if (mDirection == Direction.LEFT_TO_RIGHT){ // 左-右:左边是红色 右边是黑色 // 绘制变色文字 0-middle drawText(canvas,mChangePaint,0,middle); // 绘制不变色 middle-getWidth drawText(canvas,mOriginPaint,middle,getWidth()); }else{ // 右-左: drawText(canvas , mChangePaint , getWidth()-middle , getWidth()); drawText(canvas , mOriginPaint , 0 , getWidth()-middle); } }/** * 画文字 */ 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 fontMetricsInt = paint.getFontMetricsInt(); int dy = (fontMetricsInt.bottom-fontMetricsInt.top)/2-fontMetricsInt.bottom; 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 color){ this.mChangePaint.setColor(color); }/** * 设置不改变的颜色 */ public void setOriginColor(int color){ this.mOriginPaint.setColor(color); } }

3>:ViewPagerActivity
public class ViewPagerActivity extends AppCompatActivity {private String[] items = {"直播", "推荐", "视频", "图片", "段子", "精华"}; private LinearLayout mIndicatorContainer; // 变成通用的 private List mIndicators; private ViewPager mViewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_viewpager); mIndicators = new ArrayList<>() ; mIndicatorContainer = (LinearLayout) findViewById(R.id.indicator_view); mViewPager = (ViewPager) findViewById(R.id.view_pager); //初始化指示器 initIndicator() ; //初始化ViewPager initViewPager() ; }/** * 初始化ViewPager */ private void initViewPager() { mViewPager.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) {} }); //ViewPager添加滑动监听器 mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {//position:代表当前页码位置 //第0个item的position为0 ,第1个item的position为1,第2个item的position为2 等等//positionOffset:代表滚动的 0-1的百分比 //0.0-0.009259259-0.031481482-0.05462963-0.08055556-等等 -0.0Log.e("TAG" , "position -> "+position+" positionOffset ->"+positionOffset) ; //1.左边 位置 position ColorTrackTextView left = mIndicators.get(position); left.setDirection(ColorTrackTextView.Direction.RIGHT_TO_LEFT); left.setCurrentProgress(1-positionOffset); try { //2.右边为防止最后一个精华item角标越界,所以添加try catch ColorTrackTextView right = mIndicators.get(position + 1); right.setDirection(ColorTrackTextView.Direction.LEFT_TO_RIGHT); right.setCurrentProgress(positionOffset); } catch (Exception e) { e.printStackTrace(); } }@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容器 mIndicatorContainer.addView(colorTrackTextView); // 加入集合 mIndicators.add(colorTrackTextView); } } }

4>:activity_viewpager

5>:ItemFragment
public class ItemFragment extends Fragment {public static ItemFragment newInstance(String item) { ItemFragment itemFragment = new ItemFragment(); Bundle bundle = new Bundle(); bundle.putString("title", item); itemFragment.setArguments(bundle); return itemFragment; }@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_item, null); TextView tv = (TextView) view.findViewById(R.id.text); Bundle bundle = getArguments(); tv.setText(bundle.getString("title")); return view; } }

6>:fragment_item

    推荐阅读