Comment définir l'attribut de style par programmation dans une vue

107

J'obtiens une vue du 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 faire cela en java car je veux utiliser plusieurs styles pour chaque bouton que j'utiliserai.

Peluche_
la source

Réponses:

52

En général, vous ne pouvez pas modifier les styles par programme; vous pouvez définir l'apparence 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 de styles . Les thèmes peuvent cependant être appliqués par programme .

Il existe également une chose telle que StateListDrawablequi vous permet de définir différents drawables pour chaque état dans lequel vous Buttonpouvez être, qu'il soit focalisé, sélectionné, enfoncé, désactivé, etc.

Par exemple, pour que votre bouton change de couleur lorsqu'il est enfoncé, vous pouvez définir un fichier XML appelé res/drawable/my_button.xmlrépertoire comme ceci:

<?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 à a Buttonen définissant la propriété android:background="@drawable/my_button".

Christophe Orr
la source
4
Mon problème est que je charge des données à partir d'un service Web qui décrivent les informations de mon bouton. Les boutons doivent avoir un style différent en fonction de la catégorie à laquelle ils appartiennent. C'est pourquoi j'aimerais définir le style de manière dynamique.
Lint_
3
Eh bien, vous ne pouvez pas changer l' styleattribut Android , mais vous pouvez définir par programme l'arrière-plan d'un Buttoncomme vous pouvez avec n'importe quelle autre vue, si cela suffit. En outre, comme Buttonhérite de TextView, vous pouvez modifier les propriétés du texte. Il suffit de regarder la documentation de l'API pour ces éléments ... developer.android.com/reference/android/view/…
Christopher Orr
Je pensais juste faire ça, juste avant de vérifier si j'avais de nouvelles réponses. Merci beaucoup.
Lint_
5
N'est-il pas possible de créer un style pour un bouton qui définit la taille du texte, les marges, etc., puis l'appliquer à un bouton par programme. Sûrement son possible dire si j'ai six boutons qui veulent avoir le même style?
Ours le
quel attribut pouvons-nous gonfler? pouvons-nous gonfler les marges, le rembourrage?
Android Man
49

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 souhaitez styliser le bouton, vous avez 2 choix: le plus simple consiste simplement à 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 a ContextThemeWrapperpour cela:

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 un fichier ContextThemeWrapper. Mais pour la couleur du texte, la taille, etc., vous pouvez utiliser setTextAppearance.

Beetstra
la source
1
Tout simplement génial. ContextThemeWrapper - c'est ce que je cherchais depuis si longtemps.
Ayaz Alifov
Cela fonctionne à merveille. Je recherche cette solution depuis un certain temps.
jasonjwwilliams
14

Oui, vous pouvez utiliser par exemple dans un bouton

Button b = new Button(this);
b.setBackgroundResource(R.drawable.selector_test);
Dayerman
la source
5
Cela définira l'arrière-plan, mais un style peut spécifier plus qu'un simple arrière-plan. De nombreuses vues (y compris Button) semblent avoir un constructeur qui prend un identifiant de style comme paramètre. Cependant, j'ai des problèmes pour que cela fonctionne pour moi - le bouton apparaît sous forme de texte sans bordure ou quoi que ce soit. Ce que je pourrais faire à la place, c'est créer une mise en page avec seulement un bouton (avec un style spécifié), gonfler cette mise en page, puis définir le texte du bouton et ainsi de suite.
spaaarky21
11

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"

    />
Kristy Welsh
la source
7
Une bonne réponse considérant qu'un bouton doit être créé. Ce serait bien de voir comment faire cela pour un bouton existant.
Quality Catalyst
Voir la réponse de cesards.
Kristy Welsh
10

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

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

pour TextViews et boutons. Il existe des classes similaires pour le reste des vues :-)

cesards
la source
quel package R devez-vous utiliser pour obtenir ce style?
htafoya
6

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

J'ai utilisé une combinaison de cette réponse pour définir la couleur du 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_buttonpeut être juste un Buttonbouton normal 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é-sucette ne fonctionnent pas avec le code ci-dessus. Voir cet article sur la façon d'ajouter la prise en charge des appareils pré-sucette: https://stackoverflow.com/a/30277424/3075340

En gros, faites 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);
}
Micro
la source
6

Selon les 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.

Avis de non-responsabilité: j'ai créé la bibliothèque.

Nathanael
la source
5

La réponse de @Dayerman et @h_rules est juste. Pour donner un exemple élaboré avec du code, dans le dossier drawable, 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 à 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 définit la couleur sur argent.

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

<resources>

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

</resources>
biniam
la source
4
@Pacerier: la question ne dit pas du tout cela. Il est ambigu de savoir si le style est XML ou en java. Il demande uniquement comment définir le style par programme.
Harvey
3

Au moment de l'exécution, vous savez quel style vous voulez que votre bouton ait. Donc, au préalable, en xml dans le dossier de mise en page, vous pouvez avoir tous les boutons prêts à l'emploi avec les styles dont vous avez besoin. Ainsi, dans le dossier layout, vous pourriez avoir un fichier nommé: button_style_1.xml. Le contenu de ce fichier pourrait 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:

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

où container est le conteneur ViewGroup associé à la méthode onCreateView que vous remplacez 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 personnalisés et stylisés au conteneur de disposition 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 dynamiquement avec des boutons stylisés.

Jerry Frost
la source
0

J'ai créé une interface d'aide pour cela en utilisant le modèle 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 garde le code propre et détaillé, je recommanderais de l'utiliser uniquement comme variable locale afin que nous puissions permettre au ramasse-miettes de faire son travail une fois que nous avons terminé de définir tous les styles .

Kostyantin2216
la source
-1

J'ai été confronté 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 des couleurs d'arrière-plan différentes pour avoir l'effet final.

Merci !

dev242
la source