Jak mogę rozszerzyć TextView
, aby umożliwić rysowanie tekstu z efektem gradientu?Tekst z gradientem w systemie Android
Odpowiedz
Nie wydaje się możliwe rozszerzenie TextView w celu narysowania tekstu z gradientem. Efekt ten można jednak osiągnąć, tworząc płótno i rysując na nim. Najpierw musimy declare our custom UI element. W inicjacji musimy stworzyć podklasę o nazwie Layout. W takim przypadku użyjemy BoringLayout, który obsługuje tylko tekst z pojedynczą linią.
Shader textShader=new LinearGradient(0, 0, 0, 20,
new int[]{bottom,top},
new float[]{0, 1}, TileMode.CLAMP);//Assumes bottom and top are colors defined above
textPaint.setTextSize(textSize);
textPaint.setShader(textShader);
BoringLayout.Metrics boringMetrics=BoringLayout.isBoring(text, textPaint);
boringLayout=new BoringLayout(text, textPaint, 0, Layout.Alignment.ALIGN_CENTER,
0.0f, 0.0f, boringMetrics, false);
Następnie zastąpić onMeasure
i onDraw
:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
setMeasuredDimension((int) textPaint.measureText(text), (int) textPaint.getFontSpacing());
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
boringLayout.draw(canvas);
}
Nasza realizacja onDraw
jest w tym momencie dość leniwy (nie jest to całkowicie ignoruje specyfikacje pomiarowych !, ale tak długo, jak zagwarantować, że widok jest biorąc pod uwagę wystarczającą ilość miejsca, powinien on działać poprawnie:
Alternatywnie możliwe byłoby dziedziczenie z Canvas
i zastąpienie metody onPaint
. jeden, to niestety kotwica dla narysowanego tekstu zawsze będzie na dole, więc musimy dodać -textPaint.getFontMetricsInt().ascent()
do naszej współrzędnej y.
Prosty, ale nieco ograniczone rozwiązaniem byłoby wykorzystać te atrybuty:
android:fadingEdge="horizontal"
android:scrollHorizontally="true"
Użyłem go na pól tekstowych, gdzie chcę, żeby znikną, jeśli się zbyt długo.
To jest fajny hack. Nie sądzę, że możesz wykonać tę pracę pionowo? Nie ma żadnej cechy android: scrollVertically o ile widzę – Casebash
Niestety, nie wiem jak to zrobić :( – pgsandstrom
TextView secondTextView = new TextView(this);
Shader textShader=new LinearGradient(0, 0, 0, 20,
new int[]{Color.GREEN,Color.BLUE},
new float[]{0, 1}, TileMode.CLAMP);
secondTextView.getPaint().setShader(textShader);
+1 dla ułatwienia i wydajności –
Dzięki za bardzo proste rozwiązanie :) –
Na moim urządzeniu ICS, nie wydaje się działać - - jest całkowicie przezroczysty.Ktoś jeszcze widział to samo? Widok nie jest przyspieszany sprzętowo. –
Zwołałem bibliotekę, która obejmuje obie te metody. Możesz utworzyć GradientTextView w XML lub po prostu użyć GradientTextView.setGradient (TextView textView ...), aby zrobić to na zwykłym obiekcie TextView.
Oto przykład dla linearlayout, można użyć tego przykładu dla TextView też, a w kodzie źródłowym tam przyzwyczajenie być kodowanie gradient, można uzyskać kod źródłowy i dodać kod z tej samej strony - http://android-codes-examples.blogspot.com/2011/07/design-linearlayout-or-textview-and-any.html
Oto dobry sposób, aby to zrobić:
/**
* sets a vertical gradient on the textView's paint, so that on its onDraw method, it will use it.
*
* @param viewAlreadyHasSize
* set to true only if the textView already has a size
*/
public static void setVerticalGradientOnTextView(final TextView tv, final int positionsAndColorsResId,
final boolean viewAlreadyHasSize) {
final String[] positionsAndColors = tv.getContext().getResources().getStringArray(positionsAndColorsResId);
final int[] colors = new int[positionsAndColors.length];
float[] positions = new float[positionsAndColors.length];
for (int i = 0; i < positionsAndColors.length; ++i) {
final String positionAndColors = positionsAndColors[i];
final int delimeterPos = positionAndColors.lastIndexOf(':');
if (delimeterPos == -1 || positions == null) {
positions = null;
colors[i] = Color.parseColor(positionAndColors);
} else {
positions[i] = Float.parseFloat(positionAndColors.substring(0, delimeterPos));
String colorStr = positionAndColors.substring(delimeterPos + 1);
if (colorStr.startsWith("0x"))
colorStr = '#' + colorStr.substring(2);
else if (!colorStr.startsWith("#"))
colorStr = '#' + colorStr;
colors[i] = Color.parseColor(colorStr);
}
}
setVerticalGradientOnTextView(tv, colors, positions, viewAlreadyHasSize);
}
/**
* sets a vertical gradient on the textView's paint, so that on its onDraw method, it will use it. <br/>
*
* @param colors
* the colors to use. at least one should exist.
* @param tv
* the textView to set the gradient on it
* @param positions
* where to put each color (fraction, max is 1). if null, colors are spread evenly .
* @param viewAlreadyHasSize
* set to true only if the textView already has a size
*/
public static void setVerticalGradientOnTextView(final TextView tv, final int[] colors, final float[] positions,
final boolean viewAlreadyHasSize) {
final Runnable runnable = new Runnable() {
@Override
public void run() {
final TileMode tile_mode = TileMode.CLAMP;
final int height = tv.getHeight();
final LinearGradient lin_grad = new LinearGradient(0, 0, 0, height, colors, positions, tile_mode);
final Shader shader_gradient = lin_grad;
tv.getPaint().setShader(shader_gradient);
}
};
if (viewAlreadyHasSize)
runnable.run();
else
runJustBeforeBeingDrawn(tv, runnable);
}
public static void runJustBeforeBeingDrawn(final View view, final Runnable runnable) {
final OnPreDrawListener preDrawListener = new OnPreDrawListener() {
@Override
public boolean onPreDraw() {
view.getViewTreeObserver().removeOnPreDrawListener(this);
runnable.run();
return true;
}
};
view.getViewTreeObserver().addOnPreDrawListener(preDrawListener);
}
Ponadto, jeśli chcesz użyć bitmapy gradientu, zamiast albo prawdziwy, zastosowanie:
/**
* sets an image for the textView <br/>
* NOTE: this function must be called after you have the view have its height figured out <br/>
*/
public static void setBitmapOnTextView(final TextView tv, final Bitmap bitmap) {
final TileMode tile_mode = TileMode.CLAMP;
final int height = tv.getHeight();
final int width = tv.getWidth();
final Bitmap temp = Bitmap.createScaledBitmap(bitmap, width, height, true);
final BitmapShader bitmapShader = new BitmapShader(temp, tile_mode, tile_mode);
tv.getPaint().setShader(bitmapShader);
}
Tutaj jest obsługa wielolinii jako jednej liniowej. Powinno to również działać w przypadku przycisków.
textView.getPaint().setShader(new LinearGradient(0,0,0,textView.getLineHeight(), startColor, endColor, Shader.TileMode.REPEAT));
proste i działa doskonale !! –
Działa, ale na wysokość możesz wziąć pod uwagę litery, które znajdują się poniżej rzeczywistej linii (np. Y, g, j, itp.) I pomnożyć wysokość linii przez 1,10f, np. 'textView.getLineHeight() * 1.10f'. –
- 1. Jak podkreślić tekst przycisku w systemie Android?
- 2. Jak narysować tekst z obramowaniem na MapView w systemie Android?
- 3. Jak wyrównać tekst w TextView w systemie Android?
- 4. Tekst w slajdach tekstowych w systemie Android 3.0
- 5. Pobieranie ciągów z kursora w systemie Android?
- 6. Jak wyśrodkować tekst podpowiedzi w EditText w systemie Android?
- 7. Kopiowanie z gradientem bez nadpisywania
- 8. Jak zmienić tekst na pogrubiony w systemie Android?
- 9. Wejście głosowe do zapełniania Edytuj tekst w systemie Android?
- 10. Jak zmienić Przełącz tekst na prawą stronę w systemie Android?
- 11. Wypełnij Panel z gradientem w trzech kolorach
- 12. Jak odświeżyć tekst podczas pętli w systemie Android?
- 13. Jak stylizować tekst zakładki ActionaBar w systemie Android?
- 14. Wypełnianie kształtu gradientem w CGContext
- 15. Android get tekst z przeglądarki
- 16. Tekst centralny przycisk android
- 17. jak pisać tekst od prawej do lewej (tekst arabski) w systemie Android?
- 18. Wypełnić kształt SVG gradientem
- 19. Tekst Android TextView Truncate Behavior
- 20. Wykres R - krzywe normalne z gradientem koloru
- 21. Polecenie color matplotlib plot_surface z gradientem powierzchni
- 22. Tworzenie strony wypełnienia gradientem z css
- 23. oddzwonienie w systemie Android?
- 24. Miga tekst w widoku z Androidem
- 25. Jak zdobyć nazwę dzwonka w systemie Android?
- 26. Jak korzystać z runOnUiThread w systemie Android?
- 27. Usługa z priorytetową kolejką w systemie Android
- 28. Przyciski kolorowania w systemie Android z AppCompat
- 29. Korzystanie z funkcji putSerializable w systemie Android
- 30. Jak korzystać z crontab w systemie Android?
Witam, czy możesz dodać trochę kodu do tej odpowiedzi? W szczególności, reszta rozłożonego układu BoringLayout klasa dziękuję! – ekatz
Łącze do BoringLayout, które powinno być zawarte w SDK – Casebash