2012-05-02 7 views
7

Chciałbym użyć Canvas.drawText(), aby wyświetlić tekst wielobarwny. Dokładniej, chcę podkreślić podciąg tekstu przekazanego do metody drawText().Czy można wyświetlić tekst wielobarwny za jednym wywołaniem funkcji Canvas.drawText()?

Tekst ma postać SpannableString z 0 lub więcej obiektami ForegroundColorSpan.

Patrząc na kod Canvas, wydaje się, że wywołanie .toString() na podanym poziomie CharSequence oznacza, że ​​nie jest to możliwe.

Czy istnieje alternatywny sposób?

EDYCJA: Tekst może się czasami zmienić (zmiany całkowite, nie przyrostowe). Ponadto w widoku niestandardowym znajduje się potencjalnie wiele tekstów umieszczonych w różnych niezwiązanych ze sobą lokalizacjach.

+0

Użyj Shader do wielokolorowego tekstu –

+0

Dzięki, ale nie widzę, jak to osiągnąć. Która klasa Shadera w szczególności? –

Odpowiedz

25

Jest to możliwe poprzez zastosowanie jednej z następujących Layout klas. Są to klasy pomocnicze do rysowania tekstu na płótnie i obsługują Spannables. Jeśli twój tekst się nie zmienia użyj StaticLayout.

Przykład

Dodaj to do niestandardowej klasy widoku

private StaticLayout layout; 

umieścić ten kod do onLayout lub onSizeChanged

Spannable wordtoSpan = new SpannableString("I know just how to whisper, And I know just how to cry,I know just where to find the answers"); 

wordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 

TextPaint paint = new TextPaint(); 
paint.setTextSize(20f); 
paint.setColor(Color.RED); 
layout = new StaticLayout(wordtoSpan, paint, getWidth(), Alignment.ALIGN_NORMAL, 1, 0, false); 

Następnie w sposobie rysowania wystarczy zadzwonić

layout.draw(canvas); 

Jeśli Twój tekst często się zmienia, możesz użyć numeru DynamicLayout.

Editable.Factory fac = Editable.Factory.getInstance(); 
Editable edit = fac.newEditable(wordtoSpan); 
DynamicLayout layout = new DynamicLayout(edit,paint,getWidth(),Alignment.ALIGN_CENTER,1,0,false); 

zmiana tekstu przy użyciu obiektu edycji

edit.append("hello"); 
+0

Doskonale, dzięki. Wygląda to bardzo obiecująco. W moim przypadku tekst się zmienia. Czy w takim przypadku można użyć jakiegoś wywołania invalid(), aby osiągnąć to, czego chcę? –

+0

W takim przypadku wystarczy użyć opcji [DynamicLayout] (http://developer.android.com/reference/android/text/DynamicLayout.html) lub utworzyć nowy układ przy każdej zmianie tekstu. – Renard

+0

ok, zajrzę do tego. W rzeczywistości wyświetlam wiele ciągów, więc przypuszczam jeden DynamicLayout dla każdego ciągu? Ponadto, gdy tekst się zmienia, cały tekst zmienia się (tj. NIE jest jak tekst edytowany w EditText). Czy wpływa to na pożądane rozwiązanie? –

0

Spróbuj coś takiego, jeśli używasz TextView

String multiColorText = "<font color=0xff0000>Multi</font><font color=0x000000>Color</font><font color=0xccffff>Text</font>"; 

textView.setText(Html.fromHtml(multiColorText)); 

Edit: Dla SpannableString sprawdzić, czy poniżej pomaga

Spannable WordtoSpan = new SpannableString("partial colored text"); 

WordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 2, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 
+0

Niestety, nie używam TextView. –

+0

Odpowiedź edytowana .. Mam nadzieję, że pomaga –

0

Kiedy piszesz, że tekst do tego widoku można ustawić thatView.setBackgroundResource (R.drawable.multicolor); i

W multicolor.xml zapisu

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
android:shape="rectangle"> 
    <gradient 
      android:startColor="@color/tabBgStart" 
      android:endColor="@color/tabBgEnd" 
      android:angle="270"/> 
</shape> 

nadzieję, że to działa zdecydowanie

Aby zmienić kolor tekstu można użyć yourView.setTextColor (R.drawable.multicolor);

1

Nie używany w płótnie. zobacz poniżej kod, jak go użyłem w tekście.

public TextView getTextClipArt1(){ 
    TextView textView = new TextView(context); 
    Typeface tf = new MyTypeface(context, 0).getTypeface(); 

    Shader textShader=new LinearGradient(0, 0, 0, 30, 
      new int[]{Color.GREEN,Color.BLUE}, 
      new float[]{0, 1}, TileMode.CLAMP); 

    textView.setTypeface(tf); 
    textView.getPaint().setShader(textShader); 
    textView.getPaint().setStyle(Paint.Style.STROKE); 
    textView.getPaint().setStrokeWidth(2); 
    textView.setText("ABC"); 
    textView.setTextSize(30); 
    textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 

    return textView; 
} 

możesz teraz narysować widok tekstowy jako bitmapę na płótnie, Chociaż myślę, że te metody istnieją również w klasie malowania. Mam nadzieję, że ci się przyda.

Powiązane problemy