web-dev-qa-db-fra.com

Comment définir par programme un attribut de style dans une vue

Je reçois une vue du code XML avec le code ci-dessous: 

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

Je voudrais définir un "style" pour le bouton, comment puis-je le faire en Java car je veux utiliser plusieurs styles pour chaque bouton que je vais utiliser.

87
Lint_

Généralement, vous ne pouvez pas changer de style par programmation; vous pouvez définir l'aspect d'un écran, d'une partie d'une mise en page ou d'un bouton individuel dans votre mise en page XML à l'aide de thèmes ou styles . Les thèmes peuvent, cependant, être appliqués par programme .

Il existe également une chose telle que StateListDrawable qui vous permet de définir différents éléments dessinables pour chaque état dans lequel votre Button peut être, qu'il soit activé, sélectionné, appuyé, désactivé, etc.

Par exemple, pour que votre bouton change de couleur lorsque vous appuyez dessus, vous pouvez définir un fichier XML appelé répertoire res/drawable/my_button.xml comme suit:

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

Vous pouvez ensuite appliquer ce sélecteur à une Button en définissant la propriété Android:background="@drawable/my_button".

47
Christopher Orr

Tout d'abord, vous n'avez pas besoin d'utiliser un gonfleur de mise en page pour créer un simple bouton. Vous pouvez simplement utiliser:

button = new Button(context);

Si vous voulez styler le bouton, vous avez 2 choix: le plus simple est de spécifier tous les éléments du code, comme le suggèrent de nombreuses autres réponses

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

L'autre option consiste à définir le style en XML et à l'appliquer au bouton. Dans le cas général, vous pouvez utiliser une ContextThemeWrapper pour ceci:

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

Pour modifier les attributs liés au texte sur un TextView (ou ses sous-classes comme Button), il existe une méthode spéciale:

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

Ce dernier ne peut pas être utilisé pour changer tous les attributs; Par exemple, pour modifier le remplissage, vous devez utiliser une variable ContextThemeWrapper. Mais pour la couleur du texte, la taille, etc., vous pouvez utiliser setTextAppearance .

36
beetstra

Oui, vous pouvez utiliser par exemple un bouton 

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

Vous pouvez faire des attributs de style comme ceci: 

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

au lieu de: 

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

    />
8
Kristy Welsh

Pour ceux qui recherchent une réponse matérielle, consultez cet article SO: Boutons à colorier dans Android avec Material Design et AppCompat

J'ai utilisé une combinaison de cette réponse pour définir la couleur de texte par défaut du bouton sur blanc pour mon bouton: https://stackoverflow.com/a/32238489/3075340

Ensuite, cette réponse https://stackoverflow.com/a/34355919/3075340 pour définir par programme la couleur d'arrière-plan. Le code pour cela est:

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

your_colored_button peut être juste une Button régulière ou un bouton AppCompat si vous le souhaitez - j'ai testé le code ci-dessus avec les deux types de boutons et cela fonctionne.

EDIT: J'ai trouvé que les appareils pré-Lollipop ne fonctionnent pas avec le code ci-dessus. Voir ce message sur la façon d’ajouter un support pour les appareils pré-Lollipop: https://stackoverflow.com/a/30277424/3075340

Fondamentalement faire ceci:

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
Micro

La réponse de @Dayerman et @h_rules est juste. Pour donner un exemple élaboré avec le code, Dans un dossier pouvant être dessiné, créez un fichier XML appelé 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>

Puis en Java,

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

Cela définira la propriété du bouton sur désactivé et la couleur sur argent.

[La couleur est définie dans color.xml comme suit:

<resources>

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

</resources>
5
biniam

Au moment de l'exécution, vous savez quel style vous souhaitez que votre bouton ait. Donc au préalable, en XML dans le dossier de disposition, vous pouvez avoir tous les boutons prêts à l'emploi avec les styles dont vous avez besoin. Donc, dans le dossier de disposition, vous pourriez avoir un fichier nommé: button_style_1.xml. Le contenu de ce fichier peut ressembler à:

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

Si vous travaillez avec des fragments, dans onCreateView, vous gonflez ce bouton, comme suit:

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

où conteneur est le conteneur ViewGroup associé à la méthode onCreateView que vous substituez lors de la création de votre fragment. 

Besoin de deux autres boutons? Vous les créez comme ceci:

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

Vous pouvez personnaliser ces boutons:

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

Ensuite, vous ajoutez vos boutons stylisés personnalisés au conteneur de dispositions que vous avez également gonflé dans la méthode onCreateView:

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

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

Et c'est ainsi que vous pouvez travailler de manière dynamique avec des boutons stylisés.

3
Jerry Frost

Si vous utilisez la bibliothèque de support, vous pouvez simplement utiliser

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

pour TextViews et boutons. Il y a des classes similaires pour le reste de Views :-)

2
cesards

En fonction des attributs de style que vous souhaitez modifier, vous pourrez peut-être utiliser la bibliothèque de Paris:

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

De nombreux attributs tels que background, padding, textSize, textColor, etc. sont pris en charge.

Disclaimer: Je suis l'auteur de la bibliothèque.

2
Nathanael

J'ai fait face au même problème récemment. voici comment je l'ai résolu.

<?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>
  • J'ai utilisé un LinearLayout avec Android: weightSum = "2" 
  • J'ai donné aux deux éléments enfants Android: layout_weight = "1" (J'ai donné à chacun 50% de l'espace parent (largeur et hauteur))
  • Et enfin, j'ai donné aux deux éléments enfants différentes couleurs d'arrière-plan pour obtenir l'effet final.

Merci !

0
steve111MV

J'ai créé une interface d'aide pour cela en utilisant le motif de support.

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

Maintenant, pour chaque style que vous souhaitez utiliser de manière pragmatique, implémentez simplement l'interface, par exemple:

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

Déclarez un stylable dans votre attrs.xml, le stylable pour cet exemple est:

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

Voici le style déclaré dans 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>

Et enfin la mise en place du porte-style:

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

J'ai trouvé cela très utile car il peut être facilement réutilisé et conserve le code propre et détaillé, je vous recommande de l'utiliser uniquement comme variable locale afin de permettre au garbage collector de faire son travail une fois que nous aurons fini de définir tous les styles .

0
Kostyantin2216