Czy istnieje prosty sposób, aby tekst miał czarny kontur? Mam widoki tekstu, które będą miały różne kolory, ale niektóre kolory nie są tak dobrze widoczne na moim tle, więc zastanawiałem się, czy istnieje łatwy sposób na uzyskanie czarnego konturu lub czegoś innego, co będzie działać? Wolałbym nie tworzyć niestandardowego widoku, tworzyć płótna i tym podobne.
83
Odpowiedzi:
Możesz umieścić cień za tekstem, co często może poprawić czytelność. Spróbuj poeksperymentować z półprzezroczystymi czarnymi cieniami na zielonym tekście w 50%. Szczegóły, jak to zrobić, znajdziesz tutaj: Android - cień na tekście?
Aby naprawdę dodać obrys wokół tekstu, musisz zrobić coś bardziej skomplikowanego , na przykład: Jak narysować tekst z obramowaniem w MapView w systemie Android?
źródło
efekt konturu można uzyskać za pomocą cienia w TextView:
android:shadowColor="#000000" android:shadowDx="1.5" android:shadowDy="1.3" android:shadowRadius="1.6" android:text="CCC" android:textAllCaps="true" android:textColor="@android:color/white"
źródło
Trochę późno, ale MagicTextView między innymi wykona kontury tekstu.
<com.qwerjk.better_text.MagicTextView xmlns:qwerjk="http://schemas.android.com/apk/res/com.qwerjk.better_text" android:textSize="78dp" android:textColor="#ff333333" android:layout_width="fill_parent" android:layout_height="wrap_content" qwerjk:strokeColor="#FFff0000" qwerjk:strokeJoinStyle="miter" qwerjk:strokeWidth="5" android:text="Magic" />
Uwaga: zrobiłem to i publikuję więcej ze względu na przyszłych podróżników niż OP. To spam z pogranicza, ale poruszanie się na temat, może akceptowalne?
źródło
onDraw
wywołanie w sposób rekurencyjny z powodu wywołaniasetTextColor
wewnątrzonDraw
.To dość stare pytanie, ale nadal nie widzę pełnych odpowiedzi. Dlatego zamieszczam to rozwiązanie, mając nadzieję, że ktoś borykający się z tym problemem może uznać je za przydatne. Najprostszym i najbardziej efektywnym rozwiązaniem jest przesłonięcie metody onDraw klasy TextView. Większość implementacji, które widziałem, używa metody drawText do narysowania obrysu, ale to podejście nie uwzględnia całego wyrównania formatowania i zawijania tekstu. W rezultacie często obrys i tekst kończą się w różnych miejscach. Poniższe podejście wykorzystuje super.onDraw do narysowania zarówno obrysu, jak i wypełnienia części tekstu, więc nie musisz martwić się o resztę. Oto kroki
I ponownie wywołaj klasę nadrzędną onDraw, aby narysować obrys nad wcześniej renderowanym tekstem.
package com.example.widgets; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Typeface; import android.util.AttributeSet; import android.widget.Button; public class StrokedTextView extends Button { private static final int DEFAULT_STROKE_WIDTH = 0; // fields private int _strokeColor; private float _strokeWidth; // constructors public StrokedTextView(Context context) { this(context, null, 0); } public StrokedTextView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public StrokedTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if(attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.StrokedTextAttrs); _strokeColor = a.getColor(R.styleable.StrokedTextAttrs_textStrokeColor, getCurrentTextColor()); _strokeWidth = a.getFloat(R.styleable.StrokedTextAttrs_textStrokeWidth, DEFAULT_STROKE_WIDTH); a.recycle(); } else { _strokeColor = getCurrentTextColor(); _strokeWidth = DEFAULT_STROKE_WIDTH; } //convert values specified in dp in XML layout to //px, otherwise stroke width would appear different //on different screens _strokeWidth = dpToPx(context, _strokeWidth); } // getters + setters public void setStrokeColor(int color) { _strokeColor = color; } public void setStrokeWidth(int width) { _strokeWidth = width; } // overridden methods @Override protected void onDraw(Canvas canvas) { if(_strokeWidth > 0) { //set paint to fill mode Paint p = getPaint(); p.setStyle(Paint.Style.FILL); //draw the fill part of text super.onDraw(canvas); //save the text color int currentTextColor = getCurrentTextColor(); //set paint to stroke mode and specify //stroke color and width p.setStyle(Paint.Style.STROKE); p.setStrokeWidth(_strokeWidth); setTextColor(_strokeColor); //draw text stroke super.onDraw(canvas); //revert the color back to the one //initially specified setTextColor(currentTextColor); } else { super.onDraw(canvas); } } /** * Convenience method to convert density independent pixel(dp) value * into device display specific pixel value. * @param context Context to access device specific display metrics * @param dp density independent pixel value * @return device specific pixel value. */ public static int dpToPx(Context context, float dp) { final float scale= context.getResources().getDisplayMetrics().density; return (int) (dp * scale + 0.5f); } }
To wszystko. Ta klasa używa niestandardowych atrybutów XML, aby umożliwić określanie koloru i szerokości obrysu z plików układu XML. Dlatego musisz dodać te atrybuty do pliku attr.xml w podfolderze „values” w folderze „res”. Skopiuj i wklej następujące elementy w pliku attr.xml.
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="StrokedTextAttrs"> <attr name="textStrokeColor" format="color"/> <attr name="textStrokeWidth" format="float"/> </declare-styleable> </resources>
Gdy skończysz, możesz użyć niestandardowej klasy StrokedTextView w swoich plikach układu XML, a także określić kolor i szerokość obrysu. Oto przykład
<com.example.widgets.StrokedTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Stroked text sample" android:textColor="@android:color/white" android:textSize="25sp" strokeAttrs:textStrokeColor="@android:color/black" strokeAttrs:textStrokeWidth="1.7" />
Pamiętaj, aby zastąpić nazwę pakietu nazwą pakietu projektu. Dodaj również przestrzeń nazw xmlns w pliku układu, aby użyć niestandardowych atrybutów XML. Możesz dodać następujący wiersz w węźle głównym pliku układu.
xmlns:strokeAttrs="http://schemas.android.com/apk/res-auto"
źródło
invalidate()
wywołania ukrytego w wewnętrznym działaniusetTextColor
. O ile nie chcesz skopiować każdego ostatniego wiersza koduTextView
do swojej własnej klasy, jedynym sposobem obejścia tego jest brutalne wymuszenie dostępu do prywatnegomCurTextColor
polaTextView
przy użyciu Reflection. Zobacz tę odpowiedź, aby z grubsza zobaczyć, jak to zrobić. Po prostu użyjfield.set(this, colorInt)
zamiast używaćfield.get()
.Framework obsługuje cień tekstu, ale nie obsługuje konturu tekstu. Jest jednak pewien podstęp: cień jest półprzezroczysty i blaknie. Przerysuj cień kilka razy, a cała alfa zostanie zsumowana, a wynikiem jest zarys.
Bardzo prosta implementacja rozszerza
TextView
i zastępujedraw(..)
metodę. Za każdym razem, gdy wymagane jest losowanie, nasza podklasa wykonuje 5-10 rysunków.public class OutlineTextView extends TextView { // Constructors @Override public void draw(Canvas canvas) { for (int i = 0; i < 5; i++) { super.draw(canvas); } } } <OutlineTextView android:shadowColor="#000" android:shadowRadius="3.0" />
źródło
java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet
Właśnie próbowałem wymyślić, jak to zrobić i nie mogłem znaleźć dobrego przewodnika w Internecie, ale w końcu to rozgryzłem. Jak zasugerował Steve Pomeroy, musisz zrobić coś bardziej zaangażowanego. Aby uzyskać efekt konturu tekstu, rysujesz tekst dwukrotnie: raz grubym konturem, a następnie drugi raz rysujemy tekst główny nad konturem. Ale zadanie jest łatwiejsze, ponieważ można bardzo łatwo dostosować jeden z przykładów kodu dostarczonych z SDK, a mianowicie ten pod tą nazwą w katalogu SDK: "/ samples / android- / ApiDemos / src / com / example / android /apis/view/LabelView.java ”. Które można również znaleźć w witrynie programisty Androida tutaj .
W zależności od tego, co robisz, bardzo łatwo jest zauważyć, że będziesz musiał dokonać tylko drobnych modyfikacji w tym kodzie, takich jak zmiana go na rozszerzenie z TextView itp. Zanim odkryłem ten przykład, zapomniałem nadpisać onMeasure () (co musisz zrobić oprócz zastąpienia onDraw (), jak wspomniano w przewodniku „Tworzenie niestandardowych komponentów” na stronie Android Developer), co jest jednym z powodów, dla których miałem problemy.
Kiedy już to zrobisz, możesz zrobić to, co ja:
public class TextViewOutline extends TextView { private Paint mTextPaint; private Paint mTextPaintOutline; //add another paint attribute for your outline ... //modify initTextViewOutline to setup the outline style private void initTextViewOutline() { mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize(16); mTextPaint.setColor(0xFF000000); mTextPaint.setStyle(Paint.Style.FILL); mTextPaintOutline = new Paint(); mTextPaintOutline.setAntiAlias(true); mTextPaintOutline.setTextSize(16); mTextPaintOutline.setColor(0xFF000000); mTextPaintOutline.setStyle(Paint.Style.STROKE); mTextPaintOutline.setStrokeWidth(4); setPadding(3, 3, 3, 3); } ... //make sure to update other methods you've overridden to handle your new paint object ... //and finally draw the text, mAscent refers to a member attribute which had //a value assigned to it in the measureHeight and Width methods @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, mTextPaintOutline); canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, mTextPaint); }
Tak więc, aby uzyskać efekt konturu tekstu, rysujesz tekst dwukrotnie: raz grubym konturem, a następnie drugi raz rysujemy tekst główny nad konturem.
źródło
kredyt do @YGHM dodaj obsługę cienia
package com.megvii.demo; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; public class TextViewOutline extends android.support.v7.widget.AppCompatTextView { // constants private static final int DEFAULT_OUTLINE_SIZE = 0; private static final int DEFAULT_OUTLINE_COLOR = Color.TRANSPARENT; // data private int mOutlineSize; private int mOutlineColor; private int mTextColor; private float mShadowRadius; private float mShadowDx; private float mShadowDy; private int mShadowColor; public TextViewOutline(Context context) { this(context, null); } public TextViewOutline(Context context, AttributeSet attrs) { super(context, attrs); setAttributes(attrs); } private void setAttributes(AttributeSet attrs) { // set defaults mOutlineSize = DEFAULT_OUTLINE_SIZE; mOutlineColor = DEFAULT_OUTLINE_COLOR; // text color mTextColor = getCurrentTextColor(); if (attrs != null) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.TextViewOutline); // outline size if (a.hasValue(R.styleable.TextViewOutline_outlineSize)) { mOutlineSize = (int) a.getDimension(R.styleable.TextViewOutline_outlineSize, DEFAULT_OUTLINE_SIZE); } // outline color if (a.hasValue(R.styleable.TextViewOutline_outlineColor)) { mOutlineColor = a.getColor(R.styleable.TextViewOutline_outlineColor, DEFAULT_OUTLINE_COLOR); } // shadow (the reason we take shadow from attributes is because we use API level 15 and only from 16 we have the get methods for the shadow attributes) if (a.hasValue(R.styleable.TextViewOutline_android_shadowRadius) || a.hasValue(R.styleable.TextViewOutline_android_shadowDx) || a.hasValue(R.styleable.TextViewOutline_android_shadowDy) || a.hasValue(R.styleable.TextViewOutline_android_shadowColor)) { mShadowRadius = a.getFloat(R.styleable.TextViewOutline_android_shadowRadius, 0); mShadowDx = a.getFloat(R.styleable.TextViewOutline_android_shadowDx, 0); mShadowDy = a.getFloat(R.styleable.TextViewOutline_android_shadowDy, 0); mShadowColor = a.getColor(R.styleable.TextViewOutline_android_shadowColor, Color.TRANSPARENT); } a.recycle(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setPaintToOutline(); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } private void setPaintToOutline() { Paint paint = getPaint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(mOutlineSize); super.setTextColor(mOutlineColor); super.setShadowLayer(0, 0, 0, Color.TRANSPARENT); } private void setPaintToRegular() { Paint paint = getPaint(); paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(0); super.setTextColor(mTextColor); super.setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColor); } @Override public void setTextColor(int color) { super.setTextColor(color); mTextColor = color; } public void setOutlineSize(int size) { mOutlineSize = size; } public void setOutlineColor(int color) { mOutlineColor = color; } @Override protected void onDraw(Canvas canvas) { setPaintToOutline(); super.onDraw(canvas); setPaintToRegular(); super.onDraw(canvas); } }
attr zdefiniować
<declare-styleable name="TextViewOutline"> <attr name="outlineSize" format="dimension"/> <attr name="outlineColor" format="color|reference"/> <attr name="android:shadowRadius"/> <attr name="android:shadowDx"/> <attr name="android:shadowDy"/> <attr name="android:shadowColor"/> </declare-styleable>
XML poniżej
<com.megvii.demo.TextViewOutline android:id="@+id/product_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="110dp" android:background="#f4b222" android:fontFamily="@font/kidsmagazine" android:padding="10dp" android:shadowColor="#d7713200" android:shadowDx="0" android:shadowDy="8" android:shadowRadius="1" android:text="LIPSTICK SET" android:textColor="@android:color/white" android:textSize="30sp" app:outlineColor="#cb7800" app:outlineSize="3dp" />
źródło
Oto sztuczka, którą znalazłem, która działa lepiej niż IMO obrysu MagicTextView
@Override protected void onDraw(Canvas pCanvas) { int textColor = getTextColors().getDefaultColor(); setTextColor(mOutlineColor); // your stroke's color getPaint().setStrokeWidth(10); getPaint().setStyle(Paint.Style.STROKE); super.onDraw(pCanvas); setTextColor(textColor); getPaint().setStrokeWidth(0); getPaint().setStyle(Paint.Style.FILL); super.onDraw(pCanvas); }
źródło
TextView
do własnej klasy jest użycie Reflection, aby uzyskać bezpośredni dostęp do prywatnegomCurTextColor
pola wTextView
. Ta odpowiedź zawiera ogólne wytyczne, jak to zrobić. Jeśli chcesz, aby podpowiedź i tekst łącza również miały obrys, będziesz musiał również zmienićmHintTextColor
imLinkTextColor
. Niestety zmianamTextColor
nic nie daje, ponieważ jest tylko przywoływana.Napisałem klasę, aby wykonywać tekst z konturem i nadal obsługiwać wszystkie inne atrybuty i rysowanie normalnego widoku tekstu.
w zasadzie używa
super.onDraw(Canves canvas)
on the,TextView
ale rysuje dwa razy z różnymi stylami.mam nadzieję że to pomoże.
public class TextViewOutline extends TextView { // constants private static final int DEFAULT_OUTLINE_SIZE = 0; private static final int DEFAULT_OUTLINE_COLOR = Color.TRANSPARENT; // data private int mOutlineSize; private int mOutlineColor; private int mTextColor; private float mShadowRadius; private float mShadowDx; private float mShadowDy; private int mShadowColor; public TextViewOutline(Context context) { this(context, null); } public TextViewOutline(Context context, AttributeSet attrs) { super(context, attrs); setAttributes(attrs); } private void setAttributes(AttributeSet attrs){ // set defaults mOutlineSize = DEFAULT_OUTLINE_SIZE; mOutlineColor = DEFAULT_OUTLINE_COLOR; // text color mTextColor = getCurrentTextColor(); if(attrs != null) { TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.TextViewOutline); // outline size if (a.hasValue(R.styleable.TextViewOutline_outlineSize)) { mOutlineSize = (int) a.getDimension(R.styleable.TextViewOutline_outlineSize, DEFAULT_OUTLINE_SIZE); } // outline color if (a.hasValue(R.styleable.TextViewOutline_outlineColor)) { mOutlineColor = a.getColor(R.styleable.TextViewOutline_outlineColor, DEFAULT_OUTLINE_COLOR); } // shadow (the reason we take shadow from attributes is because we use API level 15 and only from 16 we have the get methods for the shadow attributes) if (a.hasValue(R.styleable.TextViewOutline_android_shadowRadius) || a.hasValue(R.styleable.TextViewOutline_android_shadowDx) || a.hasValue(R.styleable.TextViewOutline_android_shadowDy) || a.hasValue(R.styleable.TextViewOutline_android_shadowColor)) { mShadowRadius = a.getFloat(R.styleable.TextViewOutline_android_shadowRadius, 0); mShadowDx = a.getFloat(R.styleable.TextViewOutline_android_shadowDx, 0); mShadowDy = a.getFloat(R.styleable.TextViewOutline_android_shadowDy, 0); mShadowColor = a.getColor(R.styleable.TextViewOutline_android_shadowColor, Color.TRANSPARENT); } a.recycle(); } PFLog.d("mOutlineSize = " + mOutlineSize); PFLog.d("mOutlineColor = " + mOutlineColor); } private void setPaintToOutline(){ Paint paint = getPaint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(mOutlineSize); super.setTextColor(mOutlineColor); super.setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColor); } private void setPaintToRegular() { Paint paint = getPaint(); paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(0); super.setTextColor(mTextColor); super.setShadowLayer(0, 0, 0, Color.TRANSPARENT); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setPaintToOutline(); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override public void setTextColor(int color) { super.setTextColor(color); mTextColor = color; } @Override public void setShadowLayer(float radius, float dx, float dy, int color) { super.setShadowLayer(radius, dx, dy, color); mShadowRadius = radius; mShadowDx = dx; mShadowDy = dy; mShadowColor = color; } public void setOutlineSize(int size){ mOutlineSize = size; } public void setOutlineColor(int color){ mOutlineColor = color; } @Override protected void onDraw(Canvas canvas) { setPaintToOutline(); super.onDraw(canvas); setPaintToRegular(); super.onDraw(canvas); } }
attr.xml
<declare-styleable name="TextViewOutline"> <attr name="outlineSize" format="dimension"/> <attr name="outlineColor" format="color|reference"/> <attr name="android:shadowRadius"/> <attr name="android:shadowDx"/> <attr name="android:shadowDy"/> <attr name="android:shadowColor"/> </declare-styleable>
źródło
Możesz to zrobić programowo za pomocą poniższego fragmentu kodu. To zapewnia białe litery z czarnym tłem:
textView.setTextColor(Color.WHITE); textView.setShadowLayer(1.6f,1.5f,1.3f,Color.BLACK);
Parametry metody to promień, dx, dy, kolor. Możesz je zmienić dla swoich potrzeb.
Mam nadzieję, że pomogę komuś, kto programowo tworzy TextView i nie ma go w XML.
Pozdrawiam społeczność stackOverflow!
źródło
Stworzyłem bibliotekę na podstawie odpowiedzi Noumana Hanifa z kilkoma dodatkami. Na przykład naprawienie błędu, który powodował pośrednią nieskończoną pętlę w wywołaniach View.invalidate ().
OTOH, biblioteka obsługuje również konturowany tekst w widżetach EditText, ponieważ był to mój prawdziwy cel i wymagał nieco więcej pracy niż TextView.
Oto link do mojej biblioteki: https://github.com/biomorgoth/android-outline-textview
Podziękowania dla Nouman Hanif za wstępny pomysł na rozwiązanie!
źródło
Chcę dodać rozwiązanie, aby rozwiązać problem z wydajnością. Na przykład odpowiedź @YGHM i kilku innych działa, ale powoduje nieskończone wezwanie,
onDraw
ponieważsetTextColor
dzwoniinvalidate()
. Aby go rozwiązać, musisz również nadpisaćinvalidate()
i dodać zmiennąisDrawing
, którą ustawisztrue
, gdyonDraw()
jest w toku i rysuje pociągnięciem. Niepoprawne zwróci wartość, jeśli zmienna totrue
.override fun invalidate() { if (isDrawing) return super.invalidate() }
Twój onDraw będzie wyglądał następująco:
override fun onDraw(canvas: Canvas) { if (strokeWidth > 0) { isDrawing = true val textColor = textColors.defaultColor setTextColor(strokeColor) paint.strokeWidth = strokeWidth paint.style = Paint.Style.STROKE super.onDraw(canvas) setTextColor(textColor) paint.strokeWidth = 0f paint.style = Paint.Style.FILL isDrawing = false super.onDraw(canvas) } else { super.onDraw(canvas) } }
źródło
MagicTextView jest bardzo przydatny do tworzenia czcionki obrysowej, ale w moim przypadku powoduje błąd taki jak ten, spowodowany atrybutami powielania tła ustawionymi przez MagicTextView
więc musisz edytować attrs.xml i MagicTextView.java
attrs.xml
<attr name="background" format="reference|color" /> ↓ <attr name="mBackground" format="reference|color" />
MagicTextView.java 88:95
if (a.hasValue(R.styleable.MagicTextView_mBackground)) { Drawable background = a.getDrawable(R.styleable.MagicTextView_mBackground); if (background != null) { this.setBackgroundDrawable(background); } else { this.setBackgroundColor(a.getColor(R.styleable.MagicTextView_mBackground, 0xff000000)); } }
źródło
Znalazłem prosty sposób na zarysowanie widoku bez dziedziczenia po TextView . Napisałem prostą bibliotekę, która używa Spannable Androida do konspektu tekstu. Takie rozwiązanie daje możliwość obrysowania tylko części tekstu.
Odpowiedziałem już na to samo pytanie ( odpowiedź )
Klasa:
class OutlineSpan( @ColorInt private val strokeColor: Int, @Dimension private val strokeWidth: Float ): ReplacementSpan() { override fun getSize( paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt? ): Int { return paint.measureText(text.toString().substring(start until end)).toInt() } override fun draw( canvas: Canvas, text: CharSequence, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint ) { val originTextColor = paint.color paint.apply { color = strokeColor style = Paint.Style.STROKE this.strokeWidth = this@OutlineSpan.strokeWidth } canvas.drawText(text, start, end, x, y.toFloat(), paint) paint.apply { color = originTextColor style = Paint.Style.FILL } canvas.drawText(text, start, end, x, y.toFloat(), paint) } }
Biblioteka: OutlineSpan
źródło
Więc chcesz obrysować widok tekstu? Niestety nie ma prostego sposobu na zrobienie tego stylizacją. Będziesz musiał utworzyć inny widok i umieścić widok tekstu na górze, dzięki czemu widok nadrzędny (ten, na którym znajduje się), będzie tylko kilka pikseli większy - powinno to stworzyć kontur.
źródło
Oto najprostszy sposób, jaki mogłem znaleźć, rozszerzając TextView
public class CustomTextView extends androidx.appcompat.widget.AppCompatTextView { float mStroke; public CustomTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView); mStroke=a.getFloat(R.styleable.CustomTextView_stroke,1.0f); a.recycle(); } @Override protected void onDraw(Canvas canvas) { TextPaint paint = this.getPaint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(mStroke); super.onDraw(canvas); } }
wtedy wystarczy dodać następujące elementy do pliku attrs.xml
<declare-styleable name="CustomTextView"> <attr name="stroke" format="float"/> </declare-styleable>
a teraz będziesz mógł ustawić szerokość obrysu
app:stroke
, zachowując wszystkie inne pożądane właściwości TextView. moje rozwiązanie rysuje tylko obrys bez wypełnienia. to sprawia, że jest to nieco prostsze niż inne. poniżej zrzut ekranu z wynikiem, ustawiając niestandardową czcionkę w moim niestandardowym widoku tekstu.źródło