Android 指定TextView某个 字/段 颜色,可批量设置

简介: Android 指定TextView某个 字/段 颜色,可批量设置

如果我们要改变 TextView 中某一个字 ,或者某一段字的颜色,那样会非常麻烦,虽然可以使用别的方法改变颜色。但是如何你的 TextView 只是需要展示一下,不需要绑定控件等,使用那种方法就会非常麻烦,下面我们自定义一个CustomTextView来实现这种效果。


1,修改单个字的颜色

2,修改多个字的颜色

3,可是设置多种颜色

4,可指定某个字的颜色

5,批量设置,每个字对应一种颜色


1,指定需要的属性


在 res/values 下创建 attrs.xml 文件


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 自定义View的名字 -->
    <declare-styleable name="CustomTextView">
         <declare-styleable name="CustomTextView">
        <!-- 文字-string -->
        <attr name="text" format="string" />
        <!-- 文字大小-dimension -->
        <attr name="textSize" format="dimension" />
        <!-- 文字颜色-color-->
        <attr name="textColor" format="color" />
        <!--指定位置的颜色-->
        <attr name="tvColor" format="color" />
        <!--要改变颜色的文字-->
        <attr name="tv" format="string" />
        <!--指定位置-->
        <attr name="startPosInteger" format="integer" />
        <attr name="endPosInteger" format="integer" />
    </declare-styleable>
</resources>


2,自定义View


public class CustomTextView extends AppCompatTextView {
    /**
     * 要显示文字
     */
    private String mText;
    /**
     * 要改变颜色的文字
     */
    private String mTv = null;
    /**
     * 文字默认大小 15sp
     */
    private int mTextSize = 15;
    /**
     * 文字默认颜色
     */
    private int mTextColor = Color.BLACK;
    /**
     * 需要改变的颜色
     */
    private int mTvColor = Color.RED;
    /**
     * 画笔
     */
    private TextPaint mPaint;
    private Rect wRect;
    private Rect hRect;
    private int startPos = -1;
    private int endPos = -1;
    private String[] mTvs = null;
    private Integer[] mColors = null;
    /**
     * 这种调用第1个构造方法
     * TextView tv = new TextView(this):
     */
    public CustomTextView(Context context) {
        this(context, null);
    }
    /**
     * 这种调用第2个构造方法
     * <com.novate.test.customview.MyTextView
     * ......>
     */
    public CustomTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public CustomTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 获取自定义属性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView);
        // 获取文字
        mText = typedArray.getString(R.styleable.CustomTextView_text);
        //获取设置颜色的文字
        mTv = typedArray.getString(R.styleable.CustomTextView_tv);
        // 获取文字大小
        mTextSize = typedArray.getDimensionPixelSize(R.styleable.CustomTextView_textSize, sp2px(mTextSize));
        // 获取文字颜色
        typedArray.getColor(R.styleable.CustomTextView_textColor, mTextColor);
        startPos = typedArray.getInt(R.styleable.CustomTextView_startPosInteger, -1);
        endPos = typedArray.getInt(R.styleable.CustomTextView_endPosInteger, -1);
        mTvColor = typedArray.getInt(R.styleable.CustomTextView_tvColor, Color.RED);
        // 释放资源
        typedArray.recycle();
        // 创建画笔
        mPaint = new TextPaint();
        // 设置抗锯齿,让文字比较清晰,同时文字也会变得圆滑
        mPaint.setAntiAlias(true);
        // 设置文字大小
        mPaint.setTextSize(mTextSize);
        // 设置画笔颜色
        mPaint.setColor(mTextColor);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 如果在布局文件中设置的宽高都是固定值[比如100dp、200dp等],就用下边方式直接获取宽高
        int width = View.MeasureSpec.getSize(widthMeasureSpec);
        int height = View.MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = View.MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);
        // 如果在布局中设置宽高都是wrap_content[对应AT_MOST],必须用mode计算
        if (widthMode != MeasureSpec.EXACTLY) {
            // 文字宽度 与字体大小和长度有关
            if (wRect == null) {
                wRect = new Rect();
            }
            // 获取文本区域 param1__测量的文字 param2__从位置0开始 param3__到文字长度
            mPaint.getTextBounds(mText, 0, mText.length(), wRect);
            // 文字宽度 getPaddingLeft宽度 getPaddingRight高度 写这两个原因是为了在布局文件中设置padding属性起作用
            width = wRect.width() + getPaddingLeft() + getPaddingRight();
        }
        if (hRect == null) {
            hRect = new Rect();
        }
        if (heightMode != MeasureSpec.EXACTLY) {
            mPaint.getTextBounds(mText, 0, mText.length(), hRect);
            height = hRect.height() + getPaddingTop() + getPaddingBottom();
        }
        // 给文字设置宽高
        setMeasuredDimension(width, height);
    }
    /**
     * 绘制文字
     */
    @Override
    protected void onDraw(Canvas canvas) {
        if (mTv != null && !mTv.isEmpty()) {
            int start = mText.indexOf(mTv);
            int end = start + mTv.length();
            startToEnd(canvas, start, end, mTvColor);
        } else if (mTvs != null) {
            if (mColors != null && mColors.length == mTvs.length) {
                sort();
                drawTvs(Arrays.asList(mTvs), Arrays.asList(mColors), canvas);
            } else {
                drawTvs(Arrays.asList(mTvs), canvas);
            }
        } else if (startPos > -1 && endPos > -1) {
            startToEnd(canvas, startPos, endPos, mTvColor);
        } else if (startPos > -1) {
            startToEnd(canvas, startPos, startPos + 1, mTvColor);
        } else {
            int baseLine = getBaseLine();
            mPaint.setColor(mTextColor);
            canvas.drawText(mText, getPaddingLeft(), baseLine, mPaint);
        }
    }
    /**
     * 指定位置的文字变为指定的颜色
     *
     * @param canvas   画布
     * @param startPos 开始的位置
     * @param endPos   结束的位置
     * @param colorPos 指定的颜色
     */
    private void startToEnd(Canvas canvas, int startPos, int endPos, int colorPos) {
        if (startPos <= -1 && endPos <= -1) {
            throw new IndexOutOfBoundsException("索引异常,检查需要修改的文字是否设置正确");
        }
        int baseLine = getBaseLine();
        int paddingLeft = getPaddingLeft();
        String start = mText.substring(0, startPos);
        String red = mText.substring(startPos, endPos);
        String end = mText.substring(endPos, mText.length());
        canvas.drawText(start, paddingLeft, baseLine, mPaint);
        mPaint.setColor(colorPos);
        float redLength = Layout.getDesiredWidth(start, mPaint) + paddingLeft;
        canvas.drawText(red, redLength, baseLine, mPaint);
        mPaint.setColor(mTextColor);
        float endLength = Layout.getDesiredWidth(red, mPaint) + Layout.getDesiredWidth(start, mPaint) + paddingLeft;
        canvas.drawText(end, endLength, baseLine, mPaint);
    }
    private void drawTvs(List<String> tvs, Canvas canvas) {
        mColors = new Integer[mTvs.length];
        for (int i = 0; i < mColors.length; i++) {
            mColors[i] = mTvColor;
        }
        drawTvs(tvs, Arrays.asList(mColors), canvas);
    }
    private void drawTvs(List<String> tvs, List<Integer> colors, Canvas canvas) {
        int baseLine = getBaseLine();
        int paddingLeft = getPaddingLeft();
        for (int i = 0; i < tvs.size(); i++) {
            int start = mText.indexOf(tvs.get(i));
            int end = start + tvs.get(i).length();
            String startPos = mText.substring(0, start);
            String redPos = mText.substring(start, end);
            String endPos;
            if (tvs.size() > i + 1) {
                endPos = mText.substring(end, mText.indexOf(tvs.get(i + 1)));
            } else {
                endPos = mText.substring(end, mText.length());
            }
            if (i == 0) {
                canvas.drawText(startPos, paddingLeft, baseLine, mPaint);
            }
            if (mColors != null && colors.size() > i) {
                mPaint.setColor(colors.get(i));
            } else {
                mPaint.setColor(mTvColor);
            }
            float redLength = Layout.getDesiredWidth(startPos, mPaint) + paddingLeft;
            canvas.drawText(redPos, redLength, baseLine, mPaint);
            mPaint.setColor(mTextColor);
            float endLength = Layout.getDesiredWidth(redPos, mPaint) + Layout.getDesiredWidth(startPos, mPaint) + paddingLeft;
            canvas.drawText(endPos, endLength, baseLine, mPaint);
        }
    }
    /**
     * 开始的位置,可单独使用
     *
     * @param startPos 开始的位置,未设置结束位置则结束位置为 startPos + 1
     */
    public void startPos(int startPos) {
        this.startPos = startPos;
    }
    /**
     * 结束位置
     *
     * @param endPos 结束位置,必须大于开始位置
     */
    public void endPos(int endPos) {
        this.endPos = endPos;
    }
    /**
     * 设置要改变颜色的文字,和设置 位置 选择其一即可
     *
     * @param colorText 改变颜色的文字
     */
    public void setColorTv(String colorText) {
        this.mTv = colorText;
    }
    /**
     * 多个地方的颜色需要修改可以使用此方法
     *
     * @param tvs 需要修改的文字数组
     */
    public void setTvs(String[] tvs) {
        this.mTvs = tvs;
    }
    public void setTvs(String[] tvs, Integer[] colors) {
        this.mTvs = tvs;
        this.mColors = colors;
    }
    /**
     * 设置普通文字的颜色
     *
     * @param color 颜色
     */
    public void setTextColor(@ColorInt int color) {
        this.mTextColor = color;
    }
    /**
     * 设置要文字需要改变的颜色
     *
     * @param color
     */
    public void setTvColor(@ColorInt int color) {
        this.mTvColor = color;
    }
    /**
     * 设置 text
     *
     * @param mText text
     */
    public void setText(String mText) {
        this.mText = mText;
    }
    public void setTv(String changeTxt) {
        this.mTv = changeTxt;
    }
    /**
     * 设置默认文本颜色
     *
     * @param mTextSize size
     */
    public void setTestSize(int mTextSize) {
        this.mTextSize = mTextSize;
    }
    public void notifyTv() {
        invalidate();
    }
    /**
     * 获取基线
     */
    private int getBaseLine() {
        Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();
        int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
        return getHeight() / 2 + dy;
    }
    /**
     * sp转为px
     */
    private int sp2px(int sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                getResources().getDisplayMetrics());
    }
    private void sort() {
        for (int i = 0; i < mTvs.length; i++) {
            for (int j = i + 1; j < mTvs.length; j++) {
                if (mText.indexOf(mTvs[i]) > mText.indexOf(mTvs[j])) {
                    String text = mTvs[i];
                    mTvs[i] = mTvs[j];
                    mTvs[j] = text;
                    int color = mColors[i];
                    mColors[i] = mColors[j];
                    mColors[j] = color;
                }
            }
        }
    }
}


注释都写在上面 了,下面看一下使用


3,使用


先看一下最普通的使用:


<com.business.tools.views.CustomTextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dp"
            app:text="姓名*:张三"
            app:textColor="#000000"
            app:textSize="25sp" />


0a2653c851af460fa595bd959398a8f1.png


设置指定文字的颜色


<com.business.tools.views.CustomTextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dp"
            app:text="姓名*:张三"
            app:textColor="#000000"
            app:textSize="25sp"
            app:tv="*"
            app:tvColor="#ff0000"


使用

2d65d23f6d4748949b924e4057485923.png

tv 来指定 修改的文字,tvColor 指定修改文字的颜色。默认是红色


设置某一段文字的颜色


<com.business.tools.views.CustomTextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dp"
            app:endPosInteger="6"
            app:startPosInteger="4"
            app:text="姓名*:张三"
            app:textColor="#000000"
            app:textSize="25sp" />

0a2653c851af460fa595bd959398a8f1.png


设置指定文字的颜色


<com.business.tools.views.CustomTextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dp"
            app:endPosInteger="6"
            app:startPosInteger="4"
            app:text="姓名*:张三"
            app:textColor="#000000"
            app:textSize="25sp" 
            app:tvColor="#FF110BC9"/>

0a2653c851af460fa595bd959398a8f1.png


指定多个字的颜色


<com.business.tools.views.CustomTextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dp" />
        CustomTextView textView = findViewById(R.id.tv);
        textView.setText("Android-EasyTools" +
                "一个通用的业务代码解决方案");
        textView.setTvs(new String[]{"Android-EasyTools",
                        "通用", "解决方案"},
                new Integer[]{Color.BLUE,
                        Color.GREEN,
                        Color.CYAN});
        textView.notifyTv();


注意:最后要使用 notifyTv 刷新,

注意:不支持换行


在 xml 中可以定义的属性在代码中也可以同样定义

0a2653c851af460fa595bd959398a8f1.png

以上就是具体的使用了,如果需要什么功能,直接在 CustomTextView 中添加就行了。如有错误,还请指出


相关文章
|
24天前
|
XML API Android开发
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
本文介绍了如何使用androidx.preference库快速创建具有一级和二级菜单的Android设置界面的步骤和示例代码。
48 1
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
|
17天前
|
Android开发
Android经典实战之Textview文字设置不同颜色、下划线、加粗、超链接等效果
本文介绍了 `SpannableString` 在 Android 开发中的强大功能,包括如何在单个字符串中应用多种样式,如颜色、字体大小、风格等,并提供了详细代码示例,展示如何设置文本颜色、添加点击事件等,助你实现丰富文本效果。
55 3
|
1月前
|
Java 网络安全 开发工具
UNITY与安卓⭐一、Android Studio初始设置
UNITY与安卓⭐一、Android Studio初始设置
|
20天前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
80 0
|
2月前
|
XML Android开发 数据格式
Android 中如何设置activity的启动动画,让它像dialog一样从底部往上出来
在 Android 中实现 Activity 的对话框式过渡动画:从底部滑入与从顶部滑出。需定义两个 XML 动画文件 `activity_slide_in.xml` 和 `activity_slide_out.xml`,分别控制 Activity 的进入与退出动画。使用 `overridePendingTransition` 方法在启动 (`startActivity`) 或结束 (`finish`) Activity 时应用这些动画。为了使前 Activity 保持静止,可定义 `no_animation.xml` 并在启动新 Activity 时仅设置新 Activity 的进入动画。
54 12
|
30天前
|
开发工具 Android开发
Android项目架构设计问题之外部客户方便地设置回调如何解决
Android项目架构设计问题之外部客户方便地设置回调如何解决
17 0
|
30天前
|
数据可视化 Java 数据挖掘
Android项目架构设计问题之设置RecyclerView的LayoutManager如何解决
Android项目架构设计问题之设置RecyclerView的LayoutManager如何解决
24 0
|
2月前
|
Java Android开发
android 设置系统时间的流程
android 设置系统时间的方法
227 2
|
XML Android开发 数据格式
Android 中使用SpannableString实现TextView文本超链接跳转功能
Android 中使用SpannableString实现TextView文本超链接跳转功能
202 0