将spanned转换为大写

时间:2014-08-12 13:03:49

标签: android

我有一个由Spanned返回的Html.fromHtml()实例,我想将文本转换为大写。与String不同,其他Android CharSequence实施没有toUpperCase()方法。显然,调用toString()会导致所有链接和其他格式丢失。

5 个答案:

答案 0 :(得分:4)

您可以从原始CharSequence创建一个新字符串,然后重新应用所有原始跨度。这对我有用:

public static Spanned csToUpperCase(@NonNull Spanned s) {
    Object[] spans = s.getSpans(0,
            s.length(), Object.class);
    SpannableString spannableString = new SpannableString(s.toString().toUpperCase());

    // reapply the spans to the now uppercase string
    for (Object span : spans) {
        spannableString.setSpan(span,
                s.getSpanStart(span),
                s.getSpanEnd(span),
                0);
    }

    return spannableString;
}

答案 1 :(得分:2)

仅使用.toUpperCase()并重新应用跨度是不够的。如果您有类似ß这样的字符,则跨度长度将是错误的。 ß大写时变成SS

可能有些语言将大写的几个字符变成一个字符,但是我不知道一个例子。总之,我们可以完全避免这种情况。

这是一个简单的解决方案,可以处理大多数边缘情况:

private fun toUpperCase(locale: Locale, source: CharSequence, copySpans: Boolean): CharSequence{
    if(!copySpans) return source.toString().toUpperCase(locale)
    val upcased: List<String> = source.map { c ->
       c.toString().toUpperCase(locale)
    }
    val spanned = source as Spanned
    val spans: Array<Any> = source.getSpans(0, source.length, Any::class.java)
    val sb = SpannableStringBuilder(upcased.joinToString(""))
    for(span in spans){
        val spanStart = spanned.getSpanStart(span)
        val spanEnd = spanned.getSpanEnd(span)
        val upcasedEndLength: Int = upcased.slice(spanStart until spanEnd).fold(0){ a,b -> a+b.length}
        val upcasedStartLength: Int = if(spanStart == 0) 0 else upcased.slice(0 until spanStart).fold(0){ a,b -> a+b.length}
        val destStart = upcasedStartLength
        val destEnd = destStart + upcasedEndLength

        val flags = spanned.getSpanFlags(span)
        sb.setSpan(span,destStart,destEnd,flags)
    }
    return sb
}

这在SDK29 btw中不是必需的,因为那里的AllCapsTransformationMethod可以完美地处理跨度。 您可以导入com.ibm.icu:icu4j:67.1并从那里使用所需的方法,它与SDK29中的方法相同,但会大大增加应用程序的大小。

答案 2 :(得分:0)

万一外面有人还在寻找这个。我找到了一个不错的解决方案... 您有一个名为Span的{​​{1}},其中有一种方法可以为您提供所需的CharSequence

ReplacementSpan

继承该类,然后将您的abstract void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) 设置为该类。您将完全控制字符串的处理方式。这是一个示例:

Span

答案 3 :(得分:-1)

CharSequence有一个名为SpannableStringBuilder的可变实现,使用它可以创建CharSequence的可变副本,保留跨度。然后可以将SpannableStringBuilder中的所有字符替换为大写的等价物。

public static Spanned csToUpperCase(CharSequence s) {
    SpannableStringBuilder sb = new SpannableStringBuilder(s);
    sb.replace(0, s.length(), s.toString().toUpperCase(Locale.US));
    return sb;
}

答案 4 :(得分:-1)

在Html.fromHtml()方法中,您将发送字符串,因此您可以将该字符串转换为大写字母,并从Html.fromHtml获取范围


 Html.fromHtml(lSampleString..toUpperCase();