Jak programowo ustawić atrybut stylu w widoku


107

Otrzymuję widok z XML z poniższym kodem:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);

Chciałbym ustawić „styl” dla przycisku. Jak mogę to zrobić w Javie, skoro chcę użyć kilku stylów dla każdego przycisku, którego będę używał.

Odpowiedzi:


52

Generalnie nie można programowo zmieniać stylów; możesz ustawić wygląd ekranu, części układu lub pojedynczego przycisku w układzie XML za pomocą motywów lub stylów . Motywy można jednak stosować programowo .

Istnieje również coś, StateListDrawableco pozwala zdefiniować różne drawables dla każdego stanu, w którym Buttonmożesz się znajdować, niezależnie od tego, czy jest skoncentrowany, wybrany, wciśnięty, wyłączony i tak dalej.

Na przykład, aby przycisk zmieniał kolor po naciśnięciu, możesz zdefiniować plik XML o nazwie res/drawable/my_button.xmlkatalog w następujący sposób:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item
    android:state_pressed="true"
    android:drawable="@drawable/btn_pressed" />
  <item
    android:state_pressed="false"
    android:drawable="@drawable/btn_normal" />
</selector>

Następnie możesz zastosować ten selektor do a Button, ustawiając właściwość android:background="@drawable/my_button".


4
Mój problem polega na tym, że ładuję dane z usługi internetowej, które opisują informacje o moim przycisku. Przyciski muszą mieć inny styl w zależności od kategorii, do której należą. Dlatego chciałbym dynamicznie nadawać styl.
Lint_

3
Cóż, nie możesz zmienić styleatrybutu Androida , ale możesz programowo ustawić tło w Buttontaki sam sposób, jak możesz, z dowolnym innym widokiem, jeśli to wystarczy. Ponadto, jako Buttondziedziczenie z TextView, możesz zmieniać właściwości tekstu. Wystarczy spojrzeć na dokumentację API dla tych elementów ... developer.android.com/reference/android/view/
Christopher Orr,

Właśnie o tym myślałem, tuż przed sprawdzeniem, czy mam nowe odpowiedzi. Wielkie dzięki.
Lint_

5
Czy nie jest możliwe utworzenie stylu dla przycisku, który definiuje rozmiar tekstu, marginesy itp., A następnie programowe zastosowanie tego do przycisku? Z pewnością można powiedzieć, czy mam sześć przycisków, które chcą mieć ten sam styl?
Niedźwiedź

który atrybut możemy nadmuchać? czy możemy zawyżać marginesy, dopełnienie?
Android Man

49

Po pierwsze, nie musisz używać inflatera układu, aby utworzyć prosty przycisk. Możesz po prostu użyć:

button = new Button(context);

Jeśli chcesz nadać styl przyciskowi, masz dwie możliwości: najprostsza to po prostu określenie wszystkich elementów w kodzie, jak sugeruje wiele innych odpowiedzi:

button.setTextColor(Color.RED);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);

Inną opcją jest zdefiniowanie stylu w XML i zastosowanie go do przycisku. W ogólnym przypadku możesz użyć ContextThemeWrapperdo tego:

ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle);
button = new Button(newContext);

Aby zmienić atrybuty związane z tekstem w TextView (lub jego podklasach, takich jak Button), istnieje specjalna metoda:

button.setTextAppearance(context, R.style.MyTextStyle);

Ten ostatni nie może być użyty do zmiany wszystkich atrybutów; na przykład, aby zmienić dopełnienie, musisz użyć pliku ContextThemeWrapper. Ale dla koloru, rozmiaru tekstu itp. Możesz użyć setTextAppearance.


1
Po prostu genialne. ContextThemeWrapper - to jest to, czego szukałem tak długo.
Ayaz Alifov

Działa to fantastycznie. Od jakiegoś czasu szukałem tego rozwiązania.
jasonjwwilliams

14

Tak, możesz użyć na przykład w przycisku

Button b = new Button(this);
b.setBackgroundResource(R.drawable.selector_test);

5
To ustawi tło, ale styl może określać więcej niż tylko tło. Wygląda na to, że wiele widoków (w tym Button) ma konstruktora, który przyjmuje identyfikator stylu jako parametr. Jednak mam problemy z uruchomieniem tego dla mnie - przycisk pojawia się jako tekst bez obramowania lub czegokolwiek. Zamiast tego mógłbym utworzyć układ zawierający tylko przycisk (z określonym stylem), nadmuchać ten układ, a następnie ustawić tekst przycisku i tak dalej.
spaaarky21

11

Możesz tworzyć atrybuty stylu, takie jak:

Button myButton = new Button(this, null,android.R.attr.buttonBarButtonStyle);

zamiast:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/btn"
    style="?android:attr/buttonBarButtonStyle"

    />

7
Powinna być stworzona dobra odpowiedź biorąc pod uwagę przycisk. Byłoby miło zobaczyć, jak to zrobić dla istniejącego przycisku.
Jakość Catalyst

Zobacz odpowiedź z córek.
Kristy Welsh

10

Jeśli korzystasz z biblioteki pomocy technicznej, możesz po prostu użyć

TextViewCompat.setTextAppearance(textView, R.style.AppTheme_TextStyle_ButtonDefault_Whatever);

dla TextViews i Buttons. Dla pozostałych widoków są podobne klasy :-)


którego pakietu R potrzebujesz, aby uzyskać ten styl?
htafoya

6

Dla każdego, kto szuka materialnej odpowiedzi, zobacz ten wpis SO: Przyciski kolorowania w systemie Android z Material Design i AppCompat

Użyłem kombinacji tej odpowiedzi, aby ustawić domyślny kolor tekstu przycisku na biały dla mojego przycisku: https://stackoverflow.com/a/32238489/3075340

Następnie ta odpowiedź https://stackoverflow.com/a/34355919/3075340, aby programowo ustawić kolor tła. Kod do tego to:

ViewCompat.setBackgroundTintList(your_colored_button,
 ContextCompat.getColorStateList(getContext(),R.color.your_custom_color));

your_colored_buttonmoże to być zwykły Buttonprzycisk lub przycisk AppCompat, jeśli chcesz - przetestowałem powyższy kod z obydwoma typami przycisków i działa.

EDYCJA: Odkryłem, że urządzenia pre-Lollipop nie działają z powyższym kodem. Zobacz ten post, aby dowiedzieć się, jak dodać obsługę urządzeń sprzed wersji Lollipop: https://stackoverflow.com/a/30277424/3075340

Zasadniczo zrób to:

Button b = (Button) findViewById(R.id.button);
ColorStateList c = ContextCompat.getColorStateList(mContext, R.color.your_custom_color;
Drawable d = b.getBackground();
if (b instanceof AppCompatButton) {
    // appcompat button replaces tint of its drawable background
    ((AppCompatButton)b).setSupportBackgroundTintList(c);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Lollipop button replaces tint of its drawable background
    // however it is not equal to d.setTintList(c)
    b.setBackgroundTintList(c);
} else {
    // this should only happen if 
    // * manually creating a Button instead of AppCompatButton
    // * LayoutInflater did not translate a Button to AppCompatButton
    d = DrawableCompat.wrap(d);
    DrawableCompat.setTintList(d, c);
    b.setBackgroundDrawable(d);
}

6

W zależności od atrybutów stylu, które chcesz zmienić, możesz skorzystać z biblioteki Paryża:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
Paris.style(view).apply(R.style.YourStyle);

Obsługiwanych jest wiele atrybutów, takich jak tło, wypełnienie, textSize, textColor itp.

Zastrzeżenie: jestem autorem biblioteki.


5

Odpowiedź udzielona przez @Dayerman i @h_rules jest właściwa. Aby podać rozbudowany przykład z kodem, w folderze do rysowania utwórz plik xml o nazwie button_disabled.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">   
 <solid android:color="@color/silver"/>
<corners
   android:bottomRightRadius="20dp"
   android:bottomLeftRadius="20dp"
   android:topLeftRadius="20dp"
   android:topRightRadius="20dp"/>
</shape>

Następnie w Javie

((Button) findViewById(R.id.my_button)).setEnabled(false);
((Button) findViewById(R.id.my_button)).setBackgroundResource(R.drawable.button_disabled);

Spowoduje to ustawienie właściwości przycisku na wyłączone i ustawienie koloru na srebrny.

[Kolor jest zdefiniowany w color.xml jako:

<resources>

    <color name="silver">#C0C0C0</color>

</resources>

4
@Pacerier: pytanie wcale tego nie mówi. Nie jest jednoznaczne, czy styl to XML, czy java. Pyta tylko, jak programowo ustawić styl.
Harvey

3

W czasie działania wiesz, jaki styl chcesz mieć przycisk. Tak więc wcześniej, w XML w folderze układu, możesz mieć wszystkie gotowe przyciski z potrzebnymi stylami. Więc w folderze układu możesz mieć plik o nazwie: button_style_1.xml. Zawartość tego pliku może wyglądać następująco:

<?xml version="1.0" encoding="utf-8"?>
<Button
    android:id="@+id/styleOneButton"
    style="@style/FirstStyle" />

Jeśli pracujesz z fragmentami, to w onCreateView nadmuchujesz ten przycisk, na przykład:

Button firstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);

gdzie container to kontener ViewGroup skojarzony z metodą onCreateView, którą nadpisujesz podczas tworzenia fragmentu.

Potrzebujesz jeszcze dwóch takich przycisków? Tworzysz je w ten sposób:

Button secondFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
Button thirdFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);

Możesz dostosować te przyciski:

secondFirstStyleBtn.setText("My Second");
thirdFirstStyleBtn.setText("My Third");

Następnie dodajesz dostosowane, stylizowane przyciski do kontenera układu, który również zawyżasz w metodzie onCreateView:

_stylizedButtonsContainer = (LinearLayout) rootView.findViewById(R.id.stylizedButtonsContainer);

_stylizedButtonsContainer.addView(firstStyleBtn);
_stylizedButtonsContainer.addView(secondFirstStyleBtn);
_stylizedButtonsContainer.addView(thirdFirstStyleBtn);

I tak można dynamicznie pracować ze stylizowanymi przyciskami.


0

Zrobiłem do tego interfejs pomocniczy, używając wzoru uchwytu.

public interface StyleHolder<V extends View> {
    void applyStyle(V view);
}

Teraz dla każdego stylu, którego chcesz używać pragmatycznie, po prostu zaimplementuj interfejs, na przykład:

public class ButtonStyleHolder implements StyleHolder<Button> {

    private final Drawable background;
    private final ColorStateList textColor;
    private final int textSize;

    public ButtonStyleHolder(Context context) {
        TypedArray ta = context.obtainStyledAttributes(R.style.button, R.styleable.ButtonStyleHolder);

        Resources resources = context.getResources();

        background = ta.getDrawable(ta.getIndex(R.styleable.ButtonStyleHolder_android_background));

        textColor = ta.getColorStateList(ta.getIndex(R.styleable.ButtonStyleHolder_android_textColor));

        textSize = ta.getDimensionPixelSize(
                ta.getIndex(R.styleable.ButtonStyleHolder_android_textSize),
                resources.getDimensionPixelSize(R.dimen.standard_text_size)
        );

        // Don't forget to recycle!
        ta.recycle();
    }

    @Override
    public void applyStyle(Button btn) {
        btn.setBackground(background);
        btn.setTextColor(textColor);
        btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    }
}

Zadeklaruj styl w swoim attrs.xml, stylizowany na ten przykład to:

<declare-styleable name="ButtonStyleHolder">
    <attr name="android:background" />
    <attr name="android:textSize" />
    <attr name="android:textColor" />
</declare-styleable>

Oto styl zadeklarowany w styles.xml:

<style name="button">
    <item name="android:background">@drawable/button</item>
    <item name="android:textColor">@color/light_text_color</item>
    <item name="android:textSize">@dimen/standard_text_size</item>
</style>

I wreszcie implementacja posiadacza stylu:

Button btn = new Button(context);    
StyleHolder<Button> styleHolder = new ButtonStyleHolder(context);
styleHolder.applyStyle(btn);

Uważam, że jest to bardzo pomocne, ponieważ można go łatwo ponownie wykorzystać i zachowuje kod czysty i rozwlekły, zalecałbym używanie tego tylko jako zmiennej lokalnej, abyśmy mogli pozwolić odśmiecaczowi pamięci wykonać swoją pracę, gdy skończymy ustawiać wszystkie style .


-1

Ostatnio miałem ten sam problem. oto jak to rozwiązałem.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <!-- This is the special two colors background START , after this LinearLayout, you can add all view that have it for main background-->
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:weightSum="2"

    android:background="#FFFFFF"
    android:orientation="horizontal"
    >

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#0000FF" />

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#F000F0" />
    </LinearLayout>
    <!-- This is the special two colors background END-->

   <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:text="This Text is centered with a special backgound,
    You can add as much elements as you want as child of this RelativeLayout"
    android:textColor="#FFFFFF"
    android:textSize="20sp" />
</RelativeLayout>
  • Użyłem LinearLayout z androidem: weightSum = "2"
  • Dałem dwóm elementom podrzędnym android: layout_weight = "1" (dałem każdemu 50% przestrzeni nadrzędnej (szerokość i wysokość))
  • Na koniec nadałem dwóm elementom potomnym różne kolory tła, aby uzyskać ostateczny efekt.

Dzięki !

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.