今天再分享一个TextView内容风格化的类

/*
 * Copyright (C) 2014 Jason Fang ( [email protected] )
 *
 * 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.
 */

package fyc.framework.text;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.ClickableSpan;
import android.text.style.ImageSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.UnderlineSpan;
import android.view.View;
import android.widget.TextView;

/**
 * @author Jason Fang
 * @datetime 2015年1月26日 下午9:24:13
 */
public class SpanBuilder {
    static final boolean DEBUG = true;

    private String mText;
    private SpannableStringBuilder mBuilder;

    public SpanBuilder(String text) {
        if (TextUtils.isEmpty(text)) {
            throw new IllegalArgumentException("text is null or empty!");
        }
        mText = text;
        mBuilder = new SpannableStringBuilder(mText);
    }

    /**
     * @see AbsoluteSizeSpan#AbsoluteSizeSpan(int)
     */
    public SpanBuilder setFontSize(String spanText, int fontSize) {
        return setFontSize(spanText, fontSize, true);
    }

    /**
     * @see AbsoluteSizeSpan#AbsoluteSizeSpan(int, boolean)
     */
    public SpanBuilder setFontSize(String spanText, int fontSize, boolean dp) {
        if (TextUtils.isEmpty(spanText)) return this;

        int start = mText.indexOf(spanText);
        if (start == -1) return this;
        AbsoluteSizeSpan fontSizeSpan = new AbsoluteSizeSpan(fontSize, dp);
        mBuilder.setSpan(fontSizeSpan, start, start + spanText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    /**
     * @see RelativeSizeSpan#RelativeSizeSpan(float)
     */
    public SpanBuilder setFontSizes(String spanText, float proportion) {
        if (TextUtils.isEmpty(spanText)) return this;

        int start = mText.indexOf(spanText);
        if (start == -1) return this;
        RelativeSizeSpan fontSizeSpan = new RelativeSizeSpan(proportion);
        mBuilder.setSpan(fontSizeSpan, start, start + spanText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    /**
     * @see AlphaForegroundColorSpan#AlphaForegroundColorSpan(int)
     */
    public SpanBuilder setTextColor(String spanText, int color) {
        if (TextUtils.isEmpty(spanText)) return this;

        int start = mText.indexOf(spanText);
        if (start == -1) return this;
        AlphaForegroundColorSpan colorSpan = new AlphaForegroundColorSpan(color);
        mBuilder.setSpan(colorSpan, start, start + spanText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    /**
     * @see BackgroundColorSpan#BackgroundColorSpan(int)
     */
    public SpanBuilder setBackgroundColor(String spanText, int color) {
        if (TextUtils.isEmpty(spanText)) return this;

        int start = mText.indexOf(spanText);
        if (start == -1) return this;
        BackgroundColorSpan colorSpan = new BackgroundColorSpan(color);
        mBuilder.setSpan(colorSpan, start, start + spanText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    /**
     * @see UnderlineSpan#UnderlineSpan()
     */
    public SpanBuilder setUnderline(String spanText) {
        if (TextUtils.isEmpty(spanText)) return this;

        int start = mText.indexOf(spanText);
        if (start == -1) return this;
        mBuilder.setSpan(new UnderlineSpan(), start, start + spanText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    /**
     * @see StrikethroughSpan#StrikethroughSpan()
     */
    public SpanBuilder setStrikethrough(String spanText) {
        if (TextUtils.isEmpty(spanText)) return this;

        int start = mText.indexOf(spanText);
        if (start == -1) return this;
        mBuilder.setSpan(new StrikethroughSpan(), start, start + spanText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    /**
     * @see ClickableSpan#ClickableSpan()
     */
    public SpanBuilder setClickable(TextView textView, String spanText, SpanClickListener listener) {
        return setClickable(textView, spanText, listener, -1, true);
    }

    /**
     * @see ClickableSpan#ClickableSpan()
     */
    public SpanBuilder setClickable(TextView textView, String spanText, SpanClickListener listener,
            int hightLightColor) {
        return setClickable(textView, spanText, listener, hightLightColor, true);
    }

    /**
     * @see ClickableSpan#ClickableSpan()
     */
    public SpanBuilder setClickable(TextView textView, String spanText, SpanClickListener listener,
            int hightLightColor, boolean needUnderline) {
        if (textView == null
                || TextUtils.isEmpty(spanText)
                || listener == null)
            return this;

        int start = mText.indexOf(spanText);
        if (start == -1) return this;
        JasonClickableSpan clickableSpan = new JasonClickableSpan(listener, hightLightColor, needUnderline);
        mBuilder.setSpan(clickableSpan, start, start + spanText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        textView.setHighlightColor(Color.TRANSPARENT);
        textView.setMovementMethod(LinkMovementMethod.getInstance());
        return this;
    }

    /**
     * @see ImageSpan#ImageSpan(Bitmap)
     */
    public SpanBuilder setImage(Context context, Bitmap bitmap, String replaceText) {
        return setImage(context, bitmap, ImageSpan.ALIGN_BOTTOM, replaceText);
    }

    /**
     * @see ImageSpan#ImageSpan(Context, Bitmap, int)
     */
    public SpanBuilder setImage(Context context, Bitmap bitmap, int verticalAlignment, String replaceText) {
        if (context == null || bitmap == null) return this;

        Drawable drawable = new BitmapDrawable(context.getResources(), bitmap);
        return setImage(drawable, verticalAlignment, replaceText);
    }

    /**
     * @see ImageSpan#ImageSpan(Drawable)
     */
    public SpanBuilder setImage(Drawable drawable, String replaceText) {
        return setImage(drawable, ImageSpan.ALIGN_BOTTOM, replaceText);
    }

    /**
     * @see ImageSpan#ImageSpan(Drawable, int)
     */
    public SpanBuilder setImage(Drawable drawable, int verticalAlignment, String replaceText) {
        if (drawable == null) return this;

        int start = mText.indexOf(replaceText);
        if (start == -1) return this;
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        ImageSpan imageSpan = new ImageSpan(drawable, verticalAlignment);
        mBuilder.setSpan(imageSpan, start, start + replaceText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    /**
     * @see ImageSpan#ImageSpan(Drawable, String)
     */
    public SpanBuilder setImage(Drawable drawable, String source, String replaceText) {
        return setImage(drawable, source, ImageSpan.ALIGN_BOTTOM, replaceText);
    }

    /**
     * @see ImageSpan#ImageSpan(Drawable, String, int)
     */
    public SpanBuilder setImage(Drawable drawable, String source, int verticalAlignment, String replaceText) {
        if (drawable == null || TextUtils.isEmpty(source) || TextUtils.isEmpty(replaceText)) return this;

        int start = mText.indexOf(replaceText);
        if (start == -1) return this;
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        ImageSpan imageSpan = new ImageSpan(drawable, source, verticalAlignment);
        mBuilder.setSpan(imageSpan, start, start + replaceText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    public SpanBuilder setImage(Context context, Uri uri, String replaceText) {
        return setImage(context, uri, ImageSpan.ALIGN_BOTTOM, replaceText);
    }

    /**
     * @see ImageSpan#ImageSpan(Context, Uri, int)
     */
    public SpanBuilder setImage(Context context, Uri uri, int verticalAlignment, String replaceText) {
        if (context == null || uri == null || TextUtils.isEmpty(replaceText)) return this;

        int start = mText.indexOf(replaceText);
        if (start == -1) return this;
        ImageSpan imageSpan = new ImageSpan(context, uri, verticalAlignment);
        mBuilder.setSpan(imageSpan, start, start + replaceText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    /**
     * @see ImageSpan#ImageSpan(Context, int)
     */
    public SpanBuilder setImage(Context context, int resourceId, String replaceText) {
        return setImage(context, resourceId, ImageSpan.ALIGN_BOTTOM, replaceText);
    }

    /**
     * @see ImageSpan#ImageSpan(Context, int, int)
     */
    public SpanBuilder setImage(Context context, int resourceId, int verticalAlignment, String replaceText) {
        if (context == null || resourceId < 0 || TextUtils.isEmpty(replaceText)) return this;

        int start = mText.indexOf(replaceText);
        if (start == -1) return this;
        ImageSpan imageSpan = new ImageSpan(context, resourceId, verticalAlignment);
        mBuilder.setSpan(imageSpan, start, start + replaceText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    /**
     * @return
     */
    public SpannableStringBuilder create() {
        return mBuilder;
    }

    /**
     * @author Jason Fang
     * @datetime 2015年1月27日 下午3:15:15
     */
    class JasonClickableSpan extends ClickableSpan {

        SpanClickListener mListener;
        int mColor;
        boolean mUnderline;

        public JasonClickableSpan(SpanClickListener listener) {
            this(listener, -1);
        } 

        public JasonClickableSpan(SpanClickListener listener, int color) {
            this(listener, -1, true);
        }

        public JasonClickableSpan(SpanClickListener listener, int color, boolean underline) {
            mListener = listener;
            mColor = color;
            mUnderline = underline;
        }

        @Override
        public void onClick(View widget) {
            if (mListener != null) {
                mListener.onClick(widget);
            }
        }

        @Override
        public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
            ds.setColor(mColor == -1 ? ds.linkColor : mColor);
            ds.setUnderlineText(mUnderline);
        }

    }

    /**
     * @author Jason Fang
     * @datetime 2015年1月27日 下午3:15:08
     */
    public interface SpanClickListener {
        public void onClick(View spanView);
    }
}

AlphaForegroundColorSpan.java

/*
 * Copyright (C) 2014 Jason Fang ( [email protected] )
 *
 * 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.
 */

package fyc.framework.text;

import fyc.framework.util.Flog;
import android.graphics.Color;
import android.os.Parcel;
import android.text.TextPaint;
import android.text.style.ForegroundColorSpan;

/**
 * Alpha ForegroundColorSpan
 * @author Jason Fang
 * @datetime 2014年12月1日 下午9:07:22
 */
public class AlphaForegroundColorSpan extends ForegroundColorSpan {
    static final boolean DEBUG = true;

    private int mAlpha;

    public AlphaForegroundColorSpan(int color) {
        super(color);
        if (DEBUG) Flog.i("alpha:" + Color.alpha(color));
        setAlpha(Color.alpha(color));
    }

    public AlphaForegroundColorSpan(Parcel src) {
        super(src);
        mAlpha = src.readInt();
    }

    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeInt(mAlpha);
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setColor(getAlphaColor());
    }

    public void setAlpha(int alpha) {
        mAlpha = alpha;
    }

    public int getAlpha() {
        return mAlpha;
    }

    private int getAlphaColor() {
        int foregroundColor = getForegroundColor();
        return Color.argb(mAlpha, Color.red(foregroundColor), Color.green(foregroundColor), Color.blue(foregroundColor));
    }
}

DEMO

TextView mTips = (TextView) findViewById(R.id.tips);mTips.setText(new SpanBuilder("我不知道你在说什么!")
                .setFontSize("什么", 24)
                .setTextColor("什么", getColor(R.color.sky_blue))
                .setBackgroundColor("什", Color.BLACK)
                .setClickable(mTips, "知道", new SpanClickListener() {

                    @Override
                    public void onClick(View spanView) {
                        ToastUtils.show(getApplicationContext(), "Hello");
                    }
                }, getColor(R.color.red))
                .setUnderline("在")
                .setStrikethrough("说")
                .setImage(getApplicationContext(), R.drawable.image_1_land, ImageSpan.ALIGN_BASELINE, "!")
                .create());

时间: 2024-10-10 16:27:28

今天再分享一个TextView内容风格化的类的相关文章

分享一个PHP文件上传类

该类用于处理文件上传,可以上传一个文件,也可以上传多个文件. 包括的成员属性有: 1 private $path = "./uploads"; //上传文件保存的路径 2 private $type = array('jpg','gif','png'); //设置限制上传文件的类型 3 private $maxSize = 1000000; //限制文件上传大小(字节) 4 private $isRandName = true; //设置是否随机重命名文件, false不随机 5 pr

分享一个 MySQL 分库分表类(php)

当一个表数据记录过大时就会出现性能瓶颈,而一般对应的解决办法是要么做分区表,要么分表,分区表就不说了,分表又分为垂直分割和水平分割,具体区别请自行搜索.一般而言,分库分表属于水平分割,按照一定的规则将数据插入到不同的表中去.而分库则可以很方便的转移数据库的压力,比如将一个很大库的分别放在不同的服务器上. 下面是我写的一个分库分表的实现: <?php /** * User: guoyu * Date: 14-8-12 * Time: 下午3:16 */ namespace App\Model\Da

分享一个C#读取计算机信息的类

using System; using System.Runtime.InteropServices; using System.Management; namespace Hardware { /// summary /// Hardware_Mac 的摘要说明. /// /summary public class HardwareInfo { //取机器名 public string GetHostName() { return System.Net.Dns.GetHostName(); }

分享一个完整程序的代码(消除类游戏)

AppDelegate.cpp #include "AppDelegate.h" #include"WelcomeScene.h" #include "SimpleAudioEngine.h"//声音管理类 using namespace CocosDenshion;//声音类处于该命名空间中 USING_NS_CC; AppDelegate::AppDelegate() { } AppDelegate::~AppDelegate()  { }

分享一个记录日志的类,可多线程使用。

好久没写博客了,今天分享一个自己用的日志类,非原创,借鉴了前辈的一个想法,然后修改来的. 日志我们是必须的,现在程序都是多线程并发了,记日志就有可能出现问题了,lock?影响性能.log4net太重量级了,本日志是一个轻量级的小工具. 废话不多说,看源码: 1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Text; 5 6 namespace GEDU.CourseOnli

iOS TextView内容为空时设置按钮为不可用

有时做项目会遇到这样一种需求: 当一个TextView内容为空时设置按钮为不可用, 具体实现如下: 1. 按钮初始设置为不可用: self.customButton.enabled = NO; 2. 通过代理或通知监控TextView文本内容变化状态, 通过hasText方法判断TextView内是否有文本内容, 以设置按钮状态: 代理: 遵守协议: @interface CustomViewController () <UITextViewDelegate> 设置代理: self.textV

一个漂亮的php验证码类

一个漂亮的php验证码类(分享) 作者: 字体:[增加 减小] 类型:转载 下面小编就为大家分享一个漂亮的php验证码类.需要的朋友可以过来参考下 直接上代码: 复制代码 代码如下: //验证码类class ValidateCode { private $charset = 'abcdefghkmnprstuvwxyzABCDEFGHKMNPRSTUVWXYZ23456789';//随机因子 private $code;//验证码 private $codelen = 4;//验证码长度 pri

【开源.NET】 分享一个前后端分离的轻量级内容管理框架

开发框架要考虑的面太多了:安全.稳定.性能.效率.扩展.整洁,还要经得起实践的考验,从零开发一个可用的框架,是很耗时费神的工作.网上很多开源的框架,为何还要自己开发?我是基于以下两点: 没找到合适的:安全.稳定.简单.易用.高效.免费: 想成为架构师: 于是就自己动手,参考网上开源的项目和借鉴网友的设计思路(特别是萧秦系列博文),结合自己的实践,开发了一个简单.易用.高效的的框架,虽然不完善,但也能解决现实中的问题.不过随着见识增广,发现没负责过千万级别的项目难以成为架构师,也不可能开发出一个完

浅谈android中仅仅使用一个TextView实现高仿京东,淘宝各种倒计时

今天给大家带来的是仅仅使用一个TextView实现一个高仿京东.淘宝.唯品会等各种电商APP的活动倒计时.最近公司一直加班也没来得及时间去整理,今天难得休息想把这个分享给大家,只求共同学习,以及自己后续的复习.为什么会想到使用一个TextView来实现呢?因为最近公司在做一些优化的工作,其中就有一个倒计时样式,原来开发的这个控件的同事使用了多个TextView拼接在一起的,实现的代码冗余比较大,故此项目经理就说:小宏这个就交给你来优化了,并且还要保证有一定的扩展性,当时就懵逼了.不知道从何处开始