web-dev-qa-db-fra.com

Android: définir le style d'affichage par programme

Voici XML:

<RelativeLayout 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    style="@style/LightStyle"
    Android:layout_width="fill_parent"
    Android:layout_height="55dip"
    Android:clickable="true"
    Android:orientation="horizontal" >

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="horizontal" />

</RelativeLayout>

Comment définir l'attribut style par programme? 

174
Jim

Techniquement, vous pouvez appliquer des styles par programmation, avec des vues personnalisées de toute façon:

private MyRelativeLayout extends RelativeLayout {
  public MyRelativeLayout(Context context) {
     super(context, null, R.style.LightStyle);
  }
}

Le constructeur à un argument est celui utilisé lorsque vous instanciez des vues par programme.

Alors chaînez ce constructeur au super qui prend un paramètre de style.

RelativeLayout someLayout = new MyRelativeLayout(context);

Ou comme @Dori l'a simplement souligné:

RelativeLayout someLayout = new RelativeLayout(context, null, R.style.LightStyle);
169
Blundell

Ce qui a fonctionné pour moi:

Button b = new Button(new ContextThemeWrapper(this, R.style.ButtonText), null, 0);
  • Utiliser un ContextThemeWrapper

ET

  • Utilisez le constructeur à 3 arguments (ne fonctionnera pas sans cela)
96
Benjamin Piette

Vous ne pouvez pas définir le style d'une vue par programme pour le moment, mais vous pouvez trouver ce fil utile.

Update: au moment de répondre à cette question (mi-2012, API 14-15), il n'était pas possible de définir la vue par programme (même s'il existait des solutions de contournement non triviales), alors que cela a été rendu possible après. les versions les plus récentes de l'API. Voir la réponse de @ Blundell pour plus de détails.

84
Korhan Ozturk

Vous pouvez appliquer un style à votre activité en faisant:

super.setTheme( R.style.MyAppTheme );

ou Android par défaut:

super.setTheme( Android.R.style.Theme );

dans votre activité avant setContentView().

9
FOMDeveloper

Pour un nouveau Button/TextView:

Button mMyButton = new Button(new ContextThemeWrapper(this, R.style.button_disabled), null, 0);

Pour une instance existante:

mMyButton.setTextAppearance(this, R.style.button_enabled);

Pour l'image ou les mises en page:

Image mMyImage = new ImageView(new ContextThemeWrapper(context, R.style.article_image), null, 0);
7
Alon Kogan

Aucune des réponses fournies est correcte.

Vous pouvez définir le style par programmation. 

Réponse courte: jetez un oeil à http://grepcode.com/file/repository.grepcode.com/Java/ext/com.google.Android/android/5.1.1_r1/Android/content/Context.Java#435

Réponse longue . Voici mon extrait de code pour définir le style personnalisé défini par programme à votre vue:

1) Créez un style dans votre fichier styles.xml

 <style name="MyStyle">
    <item name="customTextColor">#39445B</item>
    <item name="customDividerColor">#8D5AA8</item>
</style>

N'oubliez pas de définir vos attributs personnalisés dans le fichier attrs.xml

Mon fichier attrsl.xml:

<declare-styleable name="CustomWidget">
    <attr name="customTextColor" format="color" />
    <attr name="customDividerColor" format="color" />
</declare-styleable>

Remarquez que vous pouvez utiliser n'importe quel nom pour votre style (mon CustomWidget)

Définissons maintenant le style du widget par programmation Voici mon widget simple:

public class StyleableWidget extends LinearLayout {

private final StyleLoader styleLoader = new StyleLoader();

private TextView textView;
private View divider;

public StyleableWidget(Context context) {
    super(context);
    init();
}

private void init() {
    inflate(getContext(), R.layout.widget_styleable, this);
    textView = (TextView) findViewById(R.id.text_view);
    divider = findViewById(R.id.divider);
    setOrientation(VERTICAL);
}

protected void apply(StyleLoader.StyleAttrs styleAttrs) {
    textView.setTextColor(styleAttrs.textColor);
    divider.setBackgroundColor(styleAttrs.dividerColor);
}

public void setStyle(@StyleRes int style) {
    apply(styleLoader.load(getContext(), style));
}
}

disposition:

<TextView
    Android:id="@+id/text_view"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:textSize="22sp"
    Android:layout_gravity="center"
    Android:text="@string/styleble_title" />

<View
    Android:id="@+id/divider"
    Android:layout_width="match_parent"
    Android:layout_height="1dp"/>

</merge>

Et enfin, l'implémentation de la classe StyleLoader

public class StyleLoader {

public StyleLoader() {

}

public static class StyleAttrs {
    public int textColor;
    public int dividerColor;
}

public StyleAttrs load(Context context, @StyleRes int styleResId) {
    final TypedArray styledAttributes = context.obtainStyledAttributes(styleResId, R.styleable.CustomWidget);
    return load(styledAttributes);
}

@NonNull
private StyleAttrs load(TypedArray styledAttributes) {
    StyleAttrs styleAttrs = new StyleAttrs();
    try {
        styleAttrs.textColor = styledAttributes.getColor(R.styleable.CustomWidget_customTextColor, 0);
        styleAttrs.dividerColor = styledAttributes.getColor(R.styleable.CustomWidget_customDividerColor, 0);
    } finally {
        styledAttributes.recycle();
    }
    return styleAttrs;
}
}

Vous pouvez trouver des exemples entièrement fonctionnels sur https://github.com/Defuera/SetStylableProgramically

2
Defuera

Si vous souhaitez continuer à utiliser XML (ce que la réponse acceptée ne vous permet pas de faire) et définir le style une fois la vue créée, vous pourrez peut-être utiliser la bibliothèque Paris, qui prend en charge un sous-ensemble de tous les attributs disponibles.

Puisque vous gonflez votre vue à partir de XML, vous devez spécifier un identifiant dans la présentation:

<RelativeLayout 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/my_styleable_relative_layout"
    style="@style/LightStyle"
    ...

Ensuite, lorsque vous devez modifier le style par programme, une fois la mise en page gonflée:

// Any way to get the view instance will do
RelativeLayout myView = findViewById(R.id.my_styleable_relative_layout);

// This will apply all the supported attribute values of the style
Paris.style(myView).apply(R.style.LightStyle);

Pour en savoir plus: la liste des types de vues et attributs pris en charge (comprend l’arrière-plan, le remplissage, la marge, etc. et peut être facilement étendue) et les instructions d’installation avec une documentation supplémentaire .

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

1
Nathanael

Je ne propose pas d'utiliser ContextThemeWrapper de la manière suivante:

Le thème spécifié sera appliqué par-dessus le thème du contexte de base.

Qu'est-ce qui peut donner des résultats indésirables dans votre application? Au lieu de cela, je propose une nouvelle bibliothèque "paris" pour cela à partir des gars d’airbnb

https://github.com/airbnb/paris

Définir et appliquer des styles aux vues Android par programme.

Mais après un certain temps d’utilisation, j’ai découvert que c’était en fait assez limité et j’ai cessé de l’utiliser, car il ne prend pas en charge un grand nombre de propriétés dont j’ai besoin, alors il faut vérifier et décider, comme toujours.

1
Renetik

le moyen le plus simple passe par le constructeur

RadioButton radioButton = new RadioButton(this,null,R.style.radiobutton_material_quiz);
0
saigopi

Ceci est mon exemple simple, la clé est le wrapper ContextThemeWrapper, sans cela, mon style ne fonctionne pas, et en utilisant les trois paramètres constructeur de la vue.

ContextThemeWrapper themeContext = new ContextThemeWrapper(this, R.style.DefaultLabelStyle);
TextView tv = new TextView(themeContext, null, 0);
tv.setText("blah blah ...");
layout.addView(tv);
0
guogangj

J'ai utilisé les vues définies dans XML dans mon groupe de vues composite, les ai gonflées et ajoutées à Viewgroup. De cette façon, je ne peux pas changer de style de manière dynamique, mais je peux effectuer certaines personnalisations de style. Mon composite:

public class CalendarView extends LinearLayout {

private GridView mCalendarGrid;
private LinearLayout mActiveCalendars;

private CalendarAdapter calendarAdapter;

public CalendarView(Context context) {
    super(context);

}

public CalendarView(Context context, AttributeSet attrs) {
    super(context, attrs);

}

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    init();
}

private void init() {
    mCalendarGrid = (GridView) findViewById(R.id.calendarContents);
    mCalendarGrid.setNumColumns(CalendarAdapter.NUM_COLS);

    calendarAdapter = new CalendarAdapter(getContext());
    mCalendarGrid.setAdapter(calendarAdapter);
    mActiveCalendars = (LinearLayout) findViewById(R.id.calendarFooter);
}

}

et ma vue en xml où je peux assigner des styles:

<com.mfitbs.Android.calendar.CalendarView
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/calendar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_gravity="center_horizontal"
Android:orientation="vertical"
>

<GridView
    Android:id="@+id/calendarContents"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content" />

<LinearLayout
    Android:id="@+id/calendarFooter"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:orientation="horizontal"
    />

0
user3918502