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.