首页 > 其他分享 >高效快捷解决一个TextView显示多种字体的控件SpannableTextView

高效快捷解决一个TextView显示多种字体的控件SpannableTextView

时间:2023-04-06 22:43:21浏览次数:47  
标签:控件 SpannableTextView int text Builder 高效快捷 Piece public


这个控件本人强烈推荐,它会使得布局非常的简单且高效;


下面这个布局如果是你,你会用多少层?多少控件生成?



高效快捷解决一个TextView显示多种字体的控件SpannableTextView_List



告诉你吧,一个SpannableTextView控件就搞定了!



它把TextView和Spannable封装在了一起,可以在一个TextView中显示不同的字体颜色,大小,背景色等;


它支持如下样式:



* Babushka Method      Internal Span


*     textSize            AbsoluteSizeSpan


*     textColor           ForegroundColorSpan


*     textSizeRelative    RelativeSizeSpan


*     backgroundColor     BackgroundColorSpan


*     style               StyleSpan


*     underline           UnderlineSpan


*     strike              StrikethroughSpan


*     superscript         SuperscriptSpan


*     subscript           SubscriptSpan



用法也很简单:

/**
     * 为一个TextView设置多种字体(大小,颜色,背景色等)
     * 
     * @param tv
     * @param title
     * @param content
     */
    public void createSpannableTextView(SpannableTextView tv, String title, String content)
    {

        // clear pieces
        tv.reset();
        // Add the first piece
        tv.addPiece(new SpannableTextView.Piece.Builder(title).textColor(App.res.getColor(R.color.text_color_c2))
                .textSize((int) App.res.getDimension(R.dimen.font_xbig)).build());

        // Add the second piece
        tv.addPiece(new SpannableTextView.Piece.Builder(content).textColor(App.res.getColor(R.color.text_color_c8))
                .textSize((int) App.res.getDimension(R.dimen.font_middle)).build());

        // Display the final, styled text
        tv.display();
    }




SpannableTextView tv = null;
                tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView0));
                context.createSpannableTextView(tv, "血糖\n", "记录血糖指数");
                tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView1));
                context.createSpannableTextView(tv, "血压\n", "记录血压指数");
                tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView2));
                context.createSpannableTextView(tv, "体重\n", "记录体重");
                tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView3));
                context.createSpannableTextView(tv, "饮食\n", "记录日常饮食");
                tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView4));
                context.createSpannableTextView(tv, "运动\n", "记录运动时间");




<cn.tangdada.tangbang.widget.SpannableTextView
                android:id="@+id/spannableTextView0"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center_vertical"
                android:background="@drawable/line_bottom"
                android:drawableRight="@drawable/arrow_right"
                android:drawableLeft="@drawable/icon_0"
                android:gravity="center_vertical"
                android:lineSpacingExtra="4dp"
                android:paddingRight="16dp"
                android:singleLine="false" />




源码:


package cn.tangdada.tangbang.widget;

/*
 * Copyright (C) 2014 Henrique Boregio.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author Henrique Boregio ([email protected])
 */

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.UnderlineSpan;
import android.util.AttributeSet;
import android.widget.TextView;

/**
 * usage:
 * 
 * <pre>
 * SpannableTextView tv = (SpannableTextView) findViewById(R.id.spannable_textview);
 * 
 * // Add the first piece "Central Park"
 * tv.addPiece(new SpannableTextView.Piece.Builder("Central Park, NY\n").textColor(Color.parseColor("#414141")).build());
 * 
 * // Add the second piece "1.2 mi"
 * tv.addPiece(new SpannableTextView.Piece.Builder("1.2 mi ").textColor(Color.parseColor("#0081E2")).textSizeRelative(0.9f).build());
 * 
 * // Add the third piece "from here"
 * tv.addPiece(new SpannableTextView.Piece.Builder("from here").textColor(Color.parseColor("#969696")).textSizeRelative(0.9f).build());
 * 
 * // Display the final, styled text
 * tv.display();
 * </pre>
 * 
 * <pre>
 * // grab the Piece at position 1
 * Piece piece = babushka.getPiece(1);
 * 
 * // modify it's text
 * piece.setText("1.9 km ");
 * 
 * // you must always call display after you alter a Piece's text
 * tv.display();
 * </pre>
 * 
 * <pre>
 * Babushka Method      Internal Span
 *     textSize            AbsoluteSizeSpan
 *     textColor           ForegroundColorSpan
 *     textSizeRelative    RelativeSizeSpan
 *     backgroundColor     BackgroundColorSpan
 *     style               StyleSpan
 *     underline           UnderlineSpan
 *     strike              StrikethroughSpan
 *     superscript         SuperscriptSpan
 *     subscript           SubscriptSpan
 * </pre>
 * 
 * BabushkaText is a TextView which lets you customize the styling of parts of your text via Spannables, but without the
 * hassle of having to deal directly with Spannable themselves.
 * 
 * The idea behind a BabushkaText is that it is made up of {@code Piece}s. Each Piece represents a section of the final
 * text displayed by this TextView, and each Piece may be styled independently from the other Pieces. When you put it
 * all together, the final results is still a a single TextView, but with a a very different graphic output.
 * 
 * 
 * https://github.com/quiqueqs/BabushkaText
 */
public class SpannableTextView extends TextView
{

    // some default params
    private static int DEFAULT_ABSOLUTE_TEXT_SIZE;

    private static float DEFAULT_RELATIVE_TEXT_SIZE = 1;

    private List<Piece> mPieces;

    /**
     * Create a new instance of a this class
     * 
     * @param context
     */
    public SpannableTextView(Context context)
    {
        super(context);
        init();
    }

    public SpannableTextView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init();
    }

    public SpannableTextView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init()
    {
        mPieces = new ArrayList<Piece>();
        SpannableTextView.DEFAULT_ABSOLUTE_TEXT_SIZE = (int) getTextSize();
    }

    /**
     * Use this method to add a {@link SpannableTextView.BabushkaText.Piece} to a BabushkaText. Each
     * {@link SpannableTextView.BabushkaText.Piece } is added sequentially, so the order you call this method matters.
     * 
     * @param aPiece the Piece
     */
    public void addPiece(Piece aPiece)
    {
        mPieces.add(aPiece);
    }

    /**
     * Adds a Piece at this specific location. The underlying data structure is a {@link java.util.List}, so expect the
     * same type of behaviour.
     * 
     * @param aPiece the Piece to add.
     * @param location the index at which to add.
     */
    public void addPiece(Piece aPiece, int location)
    {
        mPieces.add(location, aPiece);
    }

    /**
     * Replaces the Piece at the specified location with this new Piece. The underlying data structure is a
     * {@link java.util.List}, so expect the same type of behaviour.
     * 
     * @param newPiece the Piece to insert.
     * @param location the index at which to insert.
     */
    public void replacePieceAt(int location, Piece newPiece)
    {
        mPieces.set(location, newPiece);
    }

    /**
     * Removes the Piece at this specified location. The underlying data structure is a {@link java.util.List}, so
     * expect the same type of behaviour.
     * 
     * @param location the index of the Piece to remove
     */
    public void removePiece(int location)
    {
        mPieces.remove(location);
    }

    /**
     * Clear all the Pieces, same as reset()
     */
    public void clearPiece()
    {
        mPieces.clear();
    }

    /**
     * Get a specific {@link SpannableTextView.BabushkaText.Piece} in position index.
     * 
     * @param location position of Piece (0 based)
     * @return Piece o null if invalid index
     */
    public Piece getPiece(int location)
    {
        if (location >= 0 && location < mPieces.size())
        {
            return mPieces.get(location);
        }

        return null;
    }

    /**
     * Call this method when you're done adding {@link SpannableTextView.BabushkaText.Piece}s and want this TextView to
     * display the final, styled version of it's String contents.
     * 
     * You MUST also call this method whenever you make a modification to the text of a Piece that has already been
     * displayed.
     */
    public void display()
    {

        // generate the final string based on the pieces
        StringBuilder builder = new StringBuilder();
        for (Piece aPiece : mPieces)
        {
            builder.append(aPiece.text);
        }

        // apply spans
        int cursor = 0;
        SpannableString finalString = new SpannableString(builder.toString());
        for (Piece aPiece : mPieces)
        {
            applySpannablesTo(aPiece, finalString, cursor, cursor + aPiece.text.length());
            cursor += aPiece.text.length();
        }

        // set the styled text
        setText(finalString);
    }

    private void applySpannablesTo(Piece aPiece, SpannableString finalString, int start, int end)
    {

        if (aPiece.subscript)
        {
            finalString.setSpan(new SubscriptSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        if (aPiece.superscript)
        {
            finalString.setSpan(new SuperscriptSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        if (aPiece.strike)
        {
            finalString.setSpan(new StrikethroughSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        if (aPiece.underline)
        {
            finalString.setSpan(new UnderlineSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        // style
        finalString.setSpan(new StyleSpan(aPiece.style), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        // absolute text size
        finalString.setSpan(new AbsoluteSizeSpan(aPiece.textSize), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        // relative text size
        finalString.setSpan(new RelativeSizeSpan(aPiece.textSizeRelative), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        // text color
        finalString.setSpan(new ForegroundColorSpan(aPiece.textColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        // background color
        if (aPiece.backgroundColor != -1)
        {
            finalString.setSpan(new BackgroundColorSpan(aPiece.backgroundColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }

    /**
     * Resets the styling of this view and sets it's content to an empty String.
     */
    public void reset()
    {
        mPieces = new ArrayList<Piece>();
        setText("");
    }

    /**
     * Change text color of all pieces of textview.
     */
    public void changeTextColor(int textColor)
    {
        for (Piece mPiece : mPieces)
        {
            mPiece.setTextColor(textColor);
        }
        display();
    }

    /**
     * A Piece represents a part of the text that you want to style. Say for example you want this BabushkaText to
     * display "Hello World" such that "Hello" is displayed in Bold and "World" is displayed in Italics. Since these
     * have different styles, they are both separate Pieces.
     * 
     * You create a Piece by using it's {@link SpannableTextView.BabushkaText.Piece.Builder}
     * 
     */
    public static class Piece
    {

        private String text;

        private int textColor;

        private final int textSize;

        private final int backgroundColor;

        private final float textSizeRelative;

        private final int style;

        private final boolean underline;

        private final boolean superscript;

        private final boolean strike;

        private final boolean subscript;

        public Piece(Builder builder)
        {
            this.text = builder.text;
            this.textSize = builder.textSize;
            this.textColor = builder.textColor;
            this.backgroundColor = builder.backgroundColor;
            this.textSizeRelative = builder.textSizeRelative;
            this.style = builder.style;
            this.underline = builder.underline;
            this.superscript = builder.superscript;
            this.subscript = builder.subscript;
            this.strike = builder.strike;
        }

        /**
         * Sets the text of this Piece. If you're creating a new Piece, you should do so using it's
         * {@link SpannableTextView.BabushkaText.Piece.Builder}.
         * 
         * Use this method if you want to modify the text of an existing Piece that is already displayed. After doing
         * so, you MUST call {@code display()} for the changes to show up.
         * 
         * @param text the text to display
         */
        public void setText(String text)
        {
            this.text = text;
        }

        /**
         * Sets the text color of this Piece. If you're creating a new Piece, you should do so using it's
         * {@link SpannableTextView.BabushkaText.Piece.Builder}.
         * 
         * Use this method if you want to change the text color of an existing Piece that is already displayed. After
         * doing so, you MUST call {@code display()} for the changes to show up.
         * 
         * @param color of text (it is NOT android Color resources ID, use getResources().getColor(R.color.colorId) for
         *            it)
         */
        public void setTextColor(int textColor)
        {
            this.textColor = textColor;
        }

        /**
         * Builder of Pieces
         */
        public static class Builder
        {

            // required
            private final String text;

            // optional
            private int textSize = DEFAULT_ABSOLUTE_TEXT_SIZE;

            private int textColor = Color.BLACK;

            private int backgroundColor = -1;

            private float textSizeRelative = DEFAULT_RELATIVE_TEXT_SIZE;

            private int style = Typeface.NORMAL;

            private boolean underline = false;

            private boolean strike = false;

            private boolean superscript = false;

            private boolean subscript = false;

            /**
             * Creates a new Builder for this Piece.
             * 
             * @param text the text of this Piece
             */
            public Builder(String text)
            {
                this.text = text;
            }

            /**
             * Sets the absolute text size.
             * 
             * @param textSize text size in pixels
             * @return a Builder
             */
            public Builder textSize(int textSize)
            {
                this.textSize = textSize;
                return this;
            }

            /**
             * Sets the text color.
             * 
             * @param textColor the color
             * @return a Builder
             */
            public Builder textColor(int textColor)
            {
                this.textColor = textColor;
                return this;
            }

            /**
             * Sets the background color.
             * 
             * @param backgroundColor the color
             * @return a Builder
             */
            public Builder backgroundColor(int backgroundColor)
            {
                this.backgroundColor = backgroundColor;
                return this;
            }

            /**
             * Sets the relative text size.
             * 
             * @param textSizeRelative relative text size
             * @return a Builder
             */
            public Builder textSizeRelative(float textSizeRelative)
            {
                this.textSizeRelative = textSizeRelative;
                return this;
            }

            /**
             * Sets a style to this Piece.
             * 
             * @param style see {@link android.graphics.Typeface}
             * @return a Builder
             */
            public Builder style(int style)
            {
                this.style = style;
                return this;
            }

            /**
             * Underlines this Piece.
             * 
             * @return a Builder
             */
            public Builder underline()
            {
                this.underline = true;
                return this;
            }

            /**
             * Strikes this Piece.
             * 
             * @return a Builder
             */
            public Builder strike()
            {
                this.strike = true;
                return this;
            }

            /**
             * Sets this Piece as a superscript.
             * 
             * @return a Builder
             */
            public Builder superscript()
            {
                this.superscript = true;
                return this;
            }

            /**
             * Sets this Piece as a subscript.
             * 
             * @return a Builder
             */
            public Builder subscript()
            {
                this.subscript = true;
                return this;
            }

            /**
             * Creates a {@link SpannableTextView.BabushkaText.Piece} with the customized parameters.
             * 
             * @return a Piece
             */
            public Piece build()
            {
                return new Piece(this);
            }
        }
    }

}




试着结合这个类

Phrase.java那就更爽了;


ColorPhrase实现处理带颜色的字符串


https://github.com/THEONE10211024/ColorPhrase



https://github.com/quiqueqs/BabushkaText



Spanny实现字符串样式处理


https://github.com/binaryfork/Spanny

  • 高效快捷解决一个TextView显示多种字体的控件SpannableTextView_java_02

  • 大小: 8.6 KB
  • 查看图片附件

标签:控件,SpannableTextView,int,text,Builder,高效快捷,Piece,public
From: https://blog.51cto.com/u_5454003/6174205

相关文章

  • StepsView显示步骤执行情况的控件
    显示步骤执行情况的控件,在某些情况下,还是非常有用的。<com.anton46.stepsview.StepsViewxmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/stepsView0"android:layout_width="match_parent"......
  • WPF的控件字符串内容使用StringFormat进行字符串转换
    在WPF中TextBlock的Text有时内容只需要改变个别数字,而不需要所以内容都修改,这时候就要使用StringFormat, 如:<TextBlockText="Ihavexxxfriends"/>这里面的xxx是个变量,那在Binding时应该怎样写呢<TextBlockText="{BindingFirendNumber,StringFormat='Ihave{0}firends......
  • LabVIEW调用第三方exe软件或操作操作控制第三方软件界面的控件,如操控烧录软件等
    LabVIEW调用第三方exe软件或操作操作控制第三方软件界面的控件,如操控烧录软件等除了模拟鼠标和键盘来实现之后,还可以考虑另外一种方式,使用窗口句柄来直接操作程序如下面图片实例,操作串口助手,修改串口和波特率,并写入数据和读取数据这种方式可以避免电脑的分辨率变化和位置移动等......
  • winCE 控件篇
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //页面测试伪数据privatevoidbindNumber(){#region页面数......
  • C++ MFC中嵌入web网页控件(WebBrowser、WebView2、CEF3)
    1、简介WebBrowser控件最常见的用途之一是向应用程序添加Internet浏览功能。使用IWebBrowser2接口,可以浏览到本地文件系统、网络或万维网上的任何位置。可以使用IWebBrowser2::Navigate方法告知控件要浏览到哪个位置。第一个参数是包含位置名称的字符串。要浏览到本地文件系......
  • 界面控件开发包DevExpress v22.2.5正式发布|附高速下载
    DevExpress 拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpressDashboardeXpressApp框架、适用于VisualStudio的CodeRush等一系列辅助工具。屡获大奖的软件开发平台DevExpressv22.2已全新发布,该版本拥有众多新产品和数十个具有高影响力的功能,可为桌面......
  • 界面控件DevExtreme v23.1抢先体验,增强的UI/UX自定义功能!
    DevExtreme拥有高性能的HTML5/JavaScript小部件集合,使您可以利用现代Web开发堆栈(包括React,Angular,ASP.NETCore,jQuery,Knockout等)构建交互式的Web应用程序,该套件附带功能齐全的数据网格、交互式图表小部件、数据编辑器等。本文的目的就是为了让开发者预览即将发布的DevExtreme功......
  • jeesite #form中获取控件的值,以绑定的treeselect为例
    绑定部分代码:<divclass="form-group"><#form:formid="searchForm"model="${iotDevice}"action="${ctx}/iot/iotItem/listGroupData"method="post"class="form-inline"......
  • jeesite 给绑定的控件赋值
    如果事件已绑定模型,即设置了path=’XXX‘,则给控件赋值是无效的,<divclass="col-sm-10"><#form:textareapath="remarks"rows="4"maxlength="500"class="form-control"/>......
  • QHBoxLayout清空子控件
    QHBoxLayout清空子控件layout=QHBoxLayout()widget1=QLabel("Widget1")widget2=QLabel("Widget2")widget3=QLabel("Widget3")layout.addWidget(widget1)layout.addWidget(widget2)layout.addWidget(widget3)#removewidget2f......