Come impostare a livello di codice l'attributo di stile in una vista


107

Sto ottenendo una vista dall'XML con il codice seguente:

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

Vorrei impostare uno "stile" per il pulsante, come posso farlo in java poiché voglio utilizzare diversi stili per ogni pulsante che userò.

Risposte:


52

In genere non è possibile modificare gli stili a livello di programmazione; è possibile impostare l'aspetto di una schermata, di una parte di un layout o di un singolo pulsante nel layout XML utilizzando temi o stili . I temi possono, tuttavia, essere applicati a livello di codice .

Esiste anche qualcosa come un StateListDrawableche ti consente di definire diversi drawables per ogni stato in cui puoi trovarti Button, che sia focalizzato, selezionato, premuto, disabilitato e così via.

Ad esempio, per fare in modo che il tuo pulsante cambi colore quando viene premuto, puoi definire un file XML chiamato res/drawable/my_button.xmldirectory come questo:

<?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>

È quindi possibile applicare questo selettore a Buttonimpostando la proprietà android:background="@drawable/my_button".


4
Il mio problema è che carico i dati da un servizio web che descrivono le mie informazioni sui pulsanti. I pulsanti devono avere uno stile diverso in base alla categoria a cui appartengono. Ecco perché vorrei impostare lo stile in modo dinamico.
Lint_

3
Beh, non puoi cambiare l' styleattributo Android , ma puoi impostare a livello di codice lo sfondo di un Buttoncome puoi con qualsiasi altra vista, se questo è sufficiente. Inoltre, come Buttoneredita da TextView, puoi modificare le proprietà del testo. Basta guardare la documentazione API per questi elementi ... developer.android.com/reference/android/view/…
Christopher Orr

Stavo solo pensando di farlo, subito prima di controllare se avevo nuove risposte. Molte grazie.
Lint_

5
Non è possibile creare uno stile per un pulsante che definisca la dimensione del testo, i margini, ecc. Ecc. E quindi applicarlo a un pulsante in modo programmatico. Sicuramente è possibile dire se ho sei pulsanti che vogliono avere lo stesso stile?
Bear

quale attributo possiamo gonfiare? possiamo gonfiare i margini, il padding?
Android Man

49

Prima di tutto, non è necessario utilizzare un inflater di layout per creare un semplice Button. Puoi semplicemente usare:

button = new Button(context);

Se vuoi dare uno stile al pulsante hai 2 scelte: la più semplice è semplicemente specificare tutti gli elementi nel codice, come suggeriscono molte altre risposte:

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

L'altra opzione è definire lo stile in XML e applicarlo al pulsante. Nel caso generale, puoi usare a ContextThemeWrapperper questo:

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

Per modificare gli attributi relativi al testo su un TextView (o sulle sue sottoclassi come Button) esiste un metodo speciale:

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

Quest'ultimo non può essere utilizzato per modificare tutti gli attributi; ad esempio per modificare il padding è necessario utilizzare un file ContextThemeWrapper. Ma per il colore del testo, la dimensione, ecc. Puoi usare setTextAppearance.


1
Semplicemente geniale. ContextThemeWrapper - è quello che stavo cercando da così tanto tempo.
Ayaz Alifov

Funziona in modo fantastico. Ho cercato questa soluzione per un po '.
jasonjwwilliams

14

Sì, puoi usare ad esempio in un pulsante

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

5
Ciò imposterà lo sfondo, ma uno stile può specificare più di un semplice sfondo. Molte viste (incluso Button) sembrano avere un costruttore che accetta un ID di stile come parametro. Tuttavia, ho problemi a farlo funzionare per me: il pulsante viene visualizzato come testo senza bordi o altro. Quello che potrei fare invece è creare un layout con solo un pulsante (con uno stile specificato), gonfiare quel layout, quindi impostare il testo del pulsante e quant'altro.
spaaarky21

11

Puoi eseguire attributi di stile in questo modo:

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

al posto di:

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

    />

7
Buona risposta considerando che deve essere creato un pulsante. Sarebbe bello vedere come farlo per un pulsante esistente.
Quality Catalyst

Vedi la risposta da cesards.
Kristy Welsh

10

Se stai usando la libreria di supporto, puoi semplicemente usare

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

per TextView e pulsanti. Ci sono classi simili per il resto di Views :-)


quale pacchetto R devi usare per ottenere questo stile?
htafoya

6

Per chiunque cerchi una risposta Material, vedere questo post SO: Colorare i pulsanti in Android con Material Design e AppCompat

Ho usato una combinazione di questa risposta per impostare il colore del testo predefinito del pulsante su bianco per il mio pulsante: https://stackoverflow.com/a/32238489/3075340

Quindi questa risposta https://stackoverflow.com/a/34355919/3075340 per impostare a livello di codice il colore di sfondo. Il codice per questo è:

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

your_colored_buttonpuò essere solo un Buttonpulsante normale o AppCompat, se lo desideri: ho testato il codice sopra con entrambi i tipi di pulsanti e funziona.

EDIT: ho scoperto che i dispositivi pre-lollipop non funzionano con il codice sopra. Guarda questo post su come aggiungere il supporto per i dispositivi pre-lecca-lecca: https://stackoverflow.com/a/30277424/3075340

Fondamentalmente fai questo:

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

A seconda degli attributi di stile che desideri modificare, potresti essere in grado di utilizzare la libreria di Parigi:

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

Sono supportati molti attributi come background, padding, textSize, textColor, ecc.

Disclaimer: ho creato la libreria.


5

La risposta di @Dayerman e @h_rules è giusta. Per fornire un esempio elaborato con il codice, nella cartella drawable, creare un file xml chiamato 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>

Quindi in Java,

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

Ciò imposterà la proprietà del pulsante su disabilitato e il colore verrà impostato su argento.

[Il colore è definito in color.xml come:

<resources>

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

</resources>

4
@ Pacerier: la domanda non lo dice affatto. È ambiguo se lo stile è XML o in java. Chiede solo come impostare lo stile a livello di programmazione.
Harvey

3

In fase di esecuzione, sai quale stile vuoi che abbia il tuo pulsante. Quindi in anticipo, in xml nella cartella del layout, puoi avere tutti i pulsanti pronti per l'uso con gli stili di cui hai bisogno. Quindi nella cartella del layout, potresti avere un file chiamato: button_style_1.xml. Il contenuto di quel file potrebbe essere simile a:

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

Se stai lavorando con i frammenti, allora in onCreateView gonfi quel pulsante, come:

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

dove container è il contenitore ViewGroup associato al metodo onCreateView che sostituisci durante la creazione del frammento.

Hai bisogno di altri due pulsanti di questo tipo? Li crei in questo modo:

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

Puoi personalizzare questi pulsanti:

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

Quindi aggiungi i tuoi pulsanti personalizzati e stilizzati al contenitore di layout che hai anche gonfiato nel metodo onCreateView:

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

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

Ed è così che puoi lavorare dinamicamente con i pulsanti stilizzati.


0

Ho creato un'interfaccia di supporto per questo utilizzando il modello di supporto.

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

Ora, per ogni stile che desideri utilizzare pragmaticamente, implementa semplicemente l'interfaccia, ad esempio:

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);
    }
}

Dichiara uno stylable nel tuo attrs.xml, lo stile per questo esempio è:

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

Ecco lo stile dichiarato in 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>

E infine l'implementazione dello style holder:

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

L'ho trovato molto utile in quanto può essere facilmente riutilizzato e mantiene il codice pulito e dettagliato, consiglierei di usarlo solo come variabile locale in modo da poter consentire al garbage collector di fare il suo lavoro una volta che abbiamo finito di impostare tutti gli stili .


-1

Di recente ho affrontato lo stesso problema. ecco come l'ho risolto.

<?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>
  • Ho utilizzato LinearLayout con android: weightSum = "2"
  • Ho dato ai due elementi figli android: layout_weight = "1" (ho assegnato a ciascuno il 50% dello spazio genitore (larghezza e altezza))
  • Infine, ho dato ai due elementi figlio colori di sfondo diversi per ottenere l'effetto finale.

Grazie !

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.