Android开发-仿今日头条文字变色效果

效果展示

自定义文字变色效果

原理分析

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) {

            }
        });
    }
}

这样,你就成功了,是不是很简单

最后,附上源码:自定义文字变色效果

猜你喜欢

转载自blog.csdn.net/qq_41885673/article/details/114169714