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

/*
 * Copyright (C) 2014 Jason Fang ( ijasonfang@gmail.com )
 *
 * 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 ( ijasonfang@gmail.com )
 *
 * 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());

posted @ 2015-01-28 11:08  小草房Fang  阅读(778)  评论(2编辑  收藏  举报