Programowo ustaw styl dla TextView


249

Próbuję użyć TextViewkonstruktora w stylu takim jak ten:

TextView myText = new TextView(MyActivity.this, null, R.style.my_style);

Jednak gdy to robię, widok tekstu nie wydaje się przyjmować stylu (zweryfikowałem styl, ustawiając go na obiekcie statycznym).

Próbowałem też używać, myText.setTextAppearance(MyActivity.this, R.style.my_style)ale to też nie działa.

Odpowiedzi:


318

Nie sądzę, aby można było ustawić styl programowo. Aby obejść ten problem, możesz utworzyć plik XML układu szablonu z przypisanym stylem, na przykład w res / layout utwórz plik tvtemplate.xml zgodnie z następującą zawartością:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="This is a template"
        style="@style/my_style" />

następnie napompuj to, aby utworzyć nowy TextView:

TextView myText = (TextView)getLayoutInflater().inflate(R.layout.tvtemplate, null);

Mam nadzieję że to pomoże.


1
To, co wygrywa w porównaniu z odpowiedzią Dandre Allison, to to, że nie wymaga API v11.
Martin Capodici,

2
To mogło zadziałać, ale to nie ma sensu. Jak można to ustawić za pomocą pliku xml? jeśli nie programowo . Istnieją powody, aby nie używać plików XML, jednym z nich jest to, że jestem przyzwyczajony do pisania kodu do budowy interfejsu użytkownika, więc nie chcę się uczyć nowego sposobu, ponieważ mam ograniczoną pamięć i chcę zachować trochę miejsca na inne rzeczy.
Iharob Al Asimi,

@IharobAlAsimi to prawda, wszystko można zrobić programowo, a LayoutInflater wie wszystko o przekształcaniu XML w obiekty. Niestety, wiele takich rzeczy jest ukrytych pod prywatnymi interfejsami API, a jedynym sposobem tworzenia niektórych obiektów jest dostarczenie konstruktora atrybutu.
Miha_x64 21.04.17

W przeciwieństwie do wszystkich innych odpowiedzi, tak naprawdę działało to z przędzarkami, więc złota gwiazda dla ciebie
Rowan Berry

121

Możesz stworzyć ogólny styl i ponownie użyć go w wielu widokach tekstu, takich jak ten poniżej:

textView.setTextAppearance(this, R.style.MyTextStyle);

Edit: to odnosi się do kontekstu


50
Twoja odpowiedź działa, dopóki wszystko, co robisz, polega na „dopasowywaniu” tekstu do stylu. Nie działa, jeśli próbujesz robić inne rzeczy w TextView, takie jak dodawanie dopełnienia lub marginesów. Nie twierdzę więc, że się mylisz, ale twoja odpowiedź jest ograniczona. Nadmuchiwanie widoku w środowisku wykonawczym jest jedynym sposobem na zastosowanie kompleksowego stylu.
Bill Mote

1
Oba rozwiązania polegające na użyciu zawyżonego szablonu i zastosowaniu setTextAppearance są uzasadnione. Aby rozwiązać problem wypełnienia / marginesów dla drugiego rozwiązania, możesz wywołać funkcję textView.setLayoutParams (layoutParams)
AlanKley,

Ta metoda została uznana za przestarzałą na poziomie API 23. Użyj setTextAppearance (int) zamiast w API 23+.
Sergii

Upewnij się, że wersja ma co najmniej API 23 (M)
Br0thazS0ul 21.04.16

4
użyj metody z biblioteki wsparcia,TextViewCompat.setTextAppearance
Rubin Yoo

97

Możesz przekazać ContextThemeWrapper do konstruktora w następujący sposób:

TextView myText = new TextView(new ContextThemeWrapper(MyActivity.this, R.style.my_style));

1
świetne rzeczy! jedynym sposobem, w jaki mogłem programowo ustawiać style, obsługując API 8.
tbraun,

Z jakiegoś powodu nie wpływa to na styl mojego przycisku. Mam mój styl zdefiniowany następująco: <style name="TabButton"><item name="android:background">@drawable/tabbar_button_bkgnd</item>...</style>. I wtedy powołać go z budowy: new Button(new ContextThemeWrapper(context, R.style.TabButton));. Ale przycisk po prostu ignoruje moje ustawienia. Czy robię tu coś złego?
Aleks N.

@ AlaksiejN.Należy odziedziczyć po stylu Widget.Button w ten sposóbparent="@android:style/Widget.Button"
maxcanna

@maxcanna Z jakiegoś powodu dodawanie parentsię nie zmieniło. Właśnie dlatego wybrałem inflaterozwiązanie.
Aleks N.

11
@AliakseiN. Musisz użyć konstruktora 3-arg, np new Button(new ContextThemeWrapper(context, R.style.TabButton), null, 0). W przeciwnym razie zostanie zastosowany domyślny styl przycisku, który zastąpi styl przycisku scalony z motywem za pomocą ContextThemeWrapper.
Newtonx,

17

Możesz ustawić styl w konstruktorze (ale stylów nie można dynamicznie zmieniać / ustawiać).

View(Context, AttributeSet, int)( intjest atrybutem w bieżącym motywie, który zawiera odniesienie do stylu)

Odpowiedź Romaina Guy'a

odniesienie


twoja odpowiedź jest myląca - czy próbowałeś przeczytać ten wątek do końca?
andr

3
Jak to jest wprowadzane w błąd? Przyjęta odpowiedź jest myląca, ponieważ Romain Guy wyraźnie mówi, że można „ustawić” styl programowo. Po prostu nie ma możliwości dynamicznej zmiany. Wydaje się, że ten wątek tak nie jest.
Dandre Allison

1
Uwaga, to wywołanie wymaga interfejsu API poziomu 11.
Martin Capodici

1
@PaulVerest to nie jest cytat.
Dandre Allison

6
Ostatnia int nie jest zasobem stylu. Jest to „Atrybut w bieżącym motywie, który zawiera odwołanie do zasobu stylu, który dostarcza wartości domyślne dla widoku”.
rve

11

Parametr int defStyleAttrnie określa stylu. Z dokumentacji Androida:

defStyleAttr - Atrybut w bieżącym motywie, który zawiera odwołanie do zasobu stylu, który dostarcza wartości domyślne dla widoku. Może wynosić 0, aby nie szukać wartości domyślnych.

Aby skonfigurować styl w Konstruktorze widoków, mamy 2 możliwe rozwiązania:

  1. Za pomocą ContextThemeWrapper:

    ContextThemeWrapper wrappedContext = new ContextThemeWrapper(yourContext, R.style.your_style);
    TextView textView = new TextView(wrappedContext, null, 0);
  2. Z czterargumentowym konstruktorem (dostępny od LOLLIPOP):

    TextView textView = new TextView(yourContext, null, 0, R.style.your_style);

Kluczowa rzecz dla obu rozwiązań - defStyleAttrparametr powinien wynosić 0, aby zastosować nasz styl do widoku.


5

Dynamicznie zmieniające się style nie są jeszcze obsługiwane. Musisz ustawić styl przed utworzeniem widoku za pomocą XML.


20
co tak naprawdę jest tym samym
njzk2

@ njzk2 dzięki ... oczywiście nie pomyślałem o jego komentarzu przed opublikowaniem. Nie ma możliwości programowego ustawienia stylu przed budowaniem interfejsu użytkownika, dlatego ten sam kod zostałby użyty do zmiany lub ustawienia stylu programowo.
Chris Cashwell

3

Przyjęta odpowiedź była dla mnie świetnym rozwiązaniem. Jedyną rzeczą do dodania jest inflate()metoda.

W zaakceptowanej odpowiedzi wszystkie android:layout_*parametry nie zostaną zastosowane.

Powodem nie ma sposobu, aby to skorygować, ponieważ przyczyna nullzostała uznana za ViewGroup parent.

Możesz użyć tego w następujący sposób:

View view = inflater.inflate(R.layout.view, parent, false);

i parentjest to ViewGroup, z którego chcesz się dostosować android:layout_*.

W takim przypadku zostaną ustawione wszystkie właściwości względne.

Mam nadzieję, że przyda się komuś.


2

Podczas korzystania z widoków niestandardowych, które mogą wykorzystywać dziedziczenie stylu (lub atrybuty stylowalne dla zdarzenia), musisz zmodyfikować drugi konstruktor, aby nie stracić stylu. To działało dla mnie, bez potrzeby używania setTextAppearence () :

public CustomView(Context context, AttributeSet attrs) {
    this(context, attrs, attrs.getStyleAttribute());
}

2

Spotkałem ten problem i znalazłem sposób na programowe ustawienie stylu. Może wszyscy tego potrzebujesz, więc aktualizuję.

Trzeci parametr konstruktora View akceptuje typ atrybutu w twoim motywie jako kod źródłowy poniżej:

public TextView(Context context, AttributeSet attrs) {
    this(context, attrs, com.android.internal.R.attr.textViewStyle);
}

Musisz więc przekazać rodzaj R.attr. ** zamiast R. style. **

W moich kodach wykonałem następujące kroki:

Najpierw dostosuj niestandardowy plik attr do użycia przez kompozycje w pliku attr.xml.

<attr name="radio_button_style" format="reference" />

Po drugie, określ swój styl w używanym motywie w style.xml.

 <style name="AppTheme" parent="android:Theme.Translucent">
    <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    <item name="radio_button_style">@style/radioButtonStyle</item>
</style>
<style name="radioButtonStyle" parent="@android:style/Widget.CompoundButton.RadioButton">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">64dp</item>
    <item name="android:background">#000</item>
    <item name="android:button">@null</item>
    <item name="android:gravity">center</item>
    <item name="android:saveEnabled">false</item>
    <item name="android:textColor">@drawable/option_text_color</item>
    <item name="android:textSize">9sp</item>
</style>

Na koniec użyj go!

            RadioButton radioButton = new RadioButton(mContext, null, R.attr.radio_button_style);

widok utworzony programowo użyje określonego stylu w twoim motywie.

Możesz spróbować i mam nadzieję, że będzie on dla Ciebie idealny.


0

Testowałem tylko z EditText, ale możesz użyć tej metody

public void setBackgroundResource (int resid)

zastosować styl zdefiniowany w pliku XML.

Ponieważ ta metoda należy do widoku, uważam, że będzie działać z dowolnym elementem interfejsu użytkownika.

pozdrowienia.


Zgodnie z dokumentacją powinno to działać tylko z rysunkami, a nie ze stylem. Tak więc, jeśli to naprawdę działa, jest to „przypadek” i nie powinieneś na nim polegać.
Heinzi

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.