android中自定义textView自动区分SpannableStringBuilder中的不同样式字体


我在网上搜索了很多有关SpannableStringBuilder以及SpannableString的帖子,发现都是教学怎么使用,或者是api讲解.并不是我所需要的结果.我在论坛中搜索了一下SpannableString,找到的也是类似于教学的问答.

问题描述:需要实现一个类似于TextView的功能.

问题演示:在android中,通过系统的TextView,直接就进行setText所显示的效果是这样的:


 String str1 = "11111111";
    SpannableString spannableString1 = new SpannableString(str1);
    spannableString1.setSpan(new AbsoluteSizeSpan(20, true), 0, str1.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

    String str2 = "22222222";
    SpannableString spannableString2 = new SpannableString(str2);


    spannableString2.setSpan(new AbsoluteSizeSpan(50, true), 0, str2.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

    SpannableStringBuilder ssb = new SpannableStringBuilder();
    ssb.append(spannableString1).append(spannableString2);

    TextView textView = new TextView(this);
    textView.setText(ssb);
    setContentView(textView);

通过系统的TextView,直接就进行setText所显示的效果
需求描述:现在我需要自己重新继承View,自己用Canvas以及paint来绘制文字.也需要实现这样的效果.这个时候,自定义的View就需要实现类似系统TextView的功能,能够自动识别所设置的SpannableString中的字体样式.

查阅过程:我翻阅了google,baidu,stackoverflow,android dev上面大部分文档以及提问帖,还有android TextView的源码.都没有找到相关的资料.

在csdn上又看到过一个,在EditText上实现不同文字显示,但这个是通过选择文字进行对应的样式添加.首先,这样是能够知道是某一段到某一段之间的文字需要变成某一种样式.
而我现在的情况是,不知道某一段到某一段,应该变成一个什么样的预设值的样式(预设值:指之前在生成SpannableString时候添加的字体样式).

所以在这里求教,想要理解一下这个思路或实现方式等.

在帖子上或通过Gmail或QQ都能够联系我.
Gmail:[email protected]
QQ:272119494

谢谢!

Android spannablestring textview 自定义view spananblestringbuilder

kululu 10 years, 3 months ago

..好尴尬,没有人回答..

最后这个我问题,我这样解决的.(我翻看了TextView的源码,可惜看不太懂)
重写了SpannableString,在里面定义了一个tag字段,用来区分这段文字是什么类型.
然后自定义了一个SpannableStringBuilder,里面维护了一个ArrayList,用来区分每一段append进去的文字.


 public class MySpannableString extends SpannableString {

    private String tag;

    public MySpannableString(CharSequence source, String tag) {
        super(source);
        this.tag = tag;

    }

    public String getTag() {
        return tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

}

public class MySpannableStringBuilder {

    private static MySpannableStringBuilder mySpannableStringBuilder;
    private static ArrayList<MySpannableString> spannableStringArrayList;

    private MySpannableStringBuilder() {

    }

    public static synchronized MySpannableStringBuilder getMySpannableStringBuilderInstance() {
        if (mySpannableStringBuilder == null) {
            mySpannableStringBuilder = new MySpannableStringBuilder();
        }

        return mySpannableStringBuilder;
    }

    public static synchronized ArrayList<MySpannableString> getSpannableStringArrayListInstance() {
        if (spannableStringArrayList == null) {
            spannableStringArrayList = new ArrayList<MySpannableString>();
        }

        return spannableStringArrayList;
    }

    public MySpannableStringBuilder append(MySpannableString text) {
        getSpannableStringArrayListInstance().add(text);
        return getMySpannableStringBuilderInstance();
    }

}



//在Activity中
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    myTextView = new MyTextView(this);

    String str1 = "11111111";
    MySpannableString spannableString1 = new MySpannableString(str1, "p");
    spannableString1.setSpan(new AbsoluteSizeSpan(20, true), 0, str1.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

    String str2 = "2222222";
    MySpannableString spannableString2 = new MySpannableString(str2, "h1");
    spannableString2.setSpan(new AbsoluteSizeSpan(50, true), 0, str2.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

    String str3 = "44444444";
    MySpannableString spannableString3 = new MySpannableString(str3, "h2");
    spannableString3.setSpan(new AbsoluteSizeSpan(50, true), 0, str3.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

    String str4 = "555";
    MySpannableString spannableString4 = new MySpannableString(str4, "h3");
    spannableString4.setSpan(new AbsoluteSizeSpan(50, true), 0, str4.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

    String str5 = "666666";
    MySpannableString spannableString5 = new MySpannableString(str5, "h4");
    spannableString5.setSpan(new AbsoluteSizeSpan(50, true), 0, str5.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

    String str6 = "777777";
    MySpannableString spannableString6 = new MySpannableString(str6, "p");
    spannableString6.setSpan(new AbsoluteSizeSpan(50, true), 0, str6.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

    MySpannableStringBuilder ssb = MySpannableStringBuilder.getMySpannableStringBuilderInstance();
    MySpannableStringBuilder mySpannableStringBuilder = ssb.append(spannableString1).
            append(spannableString1).
            append(spannableString1).
            append(spannableString1).
            append(spannableString1).
            append(spannableString2);

    myTextView.setText(mySpannableStringBuilder);
    setContentView(myTextView);

}

如果有大牛觉得这样写不好,或者是有其他方案,欢迎共同讨论交流.

//----------------------------
又发现了一种方法


 String str2 = "2222222";
    MySpannableString spannableString2 = new MySpannableString(str2, "h1");
    spannableString2.setSpan(new AbsoluteSizeSpan(50, true), 0, str2.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

//直接通过 spannableString2.getSpan();

// 三个参数:起始位置,结束位置,Span类型
            AbsoluteSizeSpan[] spans = spannableString2.getSpans(0, spannableString2.length(), AbsoluteSizeSpan.class);
            System.out.println(spans[0].getSize());


 // 如果无法确定里面到底都是用了什么样式可以通过这种方法获取.
            Object[] spans = spannableString.getSpans(0,spannableString.length(), Object.class);
            for (Object object : spans) {
                if (object instanceof AbsoluteSizeSpan) {

                } else if(...){
                            ...
                           }
            }

如果设置了其他的Span,那就通过类似的方法拿出来.

不过如果把多个SpannableString放到SpannableStringBuilder里面去.还是没有办法区分他的起始位置和结束为止,这里就还是需要用到上面自定义的MySpannableStringBuilder来进行存储.

猫井喵太郎 answered 10 years, 3 months ago

Your Answer