Android development-imitating the color effect of today's headline text

Show results

Custom text color effect

Principle analysis

1. At a glance, I use: LinearLayout for the indicator above + ViewPager for the layout below. Other methods are certainly possible, and you can try it yourself if time permits.

2. Load multiple "custom TextView" dynamically in LinearLayout layout

3. Monitor the scroll event of ViewPager to realize the linkage with the above indicator

Source code analysis

Step 1: Customize  ColorTrackTextView to  inherit TextView

Here, you may have a doubt, why inherit TextView, View is not good?

My answer is this: View is indeed possible, but TextView is better. The reason is that TextView has already implemented the onMeasure method for us, so we don’t need to write it ourselves. Secondly, we can make full use of some of the properties of TextView, such as TextSize, TextColor, etc., so , We choose TextView.

Some people say that inheriting View has good performance. I just want to ask: Do you have any good ways to measure performance?

Step 2: Write a custom properties file

There are mainly two attributes here, the original color and the changed color

<?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>

The third step: use in the layout file, here we use dynamic loading, that is: dynamically add indicators in the code according to the data, so the following is linear layout + 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>

Step 4: Obtain custom attributes and write related codes

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;
    }
}

Step 5: Call

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

            }
        });
    }
}

In this way, you are successful, isn't it simple

Finally, attach the source code: custom text color effect

Guess you like

Origin blog.csdn.net/qq_41885673/article/details/114169714