35 votes

Pourquoi si complexe définir le style du code dans Android

Si vous souhaitez définir le style d'un Bouton que vous créez à partir du code que vous avez à faire quelque chose comme ceci;

Button  btn  = new Button (mActivity, null, R.attr.someattribute);

dans attrs.xml, vous définissez une référence

<attr name="someStyleRef" format="reference"/>

Dans styles.xml vous permet de définir un thème

<resources>
  <style name="Theme.SomeTheme" parent="android:style/Theme.Black">
     <item name="someStyleRef">@style/someStyle</item>
  </style>
</resources>

Que lates dans styles.xml est défini comme par exemple

<style name="someStyle">
        <item name="android:layout_width">2px</item>
        <item name="android:layout_height">fill_parent</item>
        <item name="android:background">@drawable/actionbar_compat_separator</item>
 </style>

Cela fonctionne, et c'est, selon ma compréhension, le moyen de définir un style sur une Vue à partir du code d'Android. Cela semble trop Complexe. Le bouton du troisième Argument du constructeur pourrait facilement avoir accepté un style ID R. style.XXX

Quelqu'un peut-il expliquer pourquoi cette complexité supplémentaire est-elle nécessaire?

65voto

adamp Points 19097

Il a à voir avec la encouragée motifs au sein d'Android autour à l'aide des points de Vue. Ce n'est pas l'approche choisie pour ce qu'il semble que vous essayez de faire. D'abord je vais vous expliquer ce que ce mécanisme est, et ensuite de suggérer une approche pour votre application.

Le troisième argument de Vue des constructeurs qui prend un attribut de ressource est généralement utilisé lors de la mise en œuvre de Vue sous-classes et comme vous l'avez indiqué, vous permet de spécifier un thème attribut à utiliser comme une référence à la Vue par défaut du style. Si vous aviez un type spécial de bouton appelé AwesomeButton vous pourriez mettre en œuvre ses constructeurs comme ceci:

public class AwesomeButton extends Button {
    public AwesomeButton(Context context) {
        this(context, null);
    }

    public AwesomeButton(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.awesomeButtonStyle);
    }

    public AwesomeButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr) {
        final TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.AwesomeButton, defStyleAttr, 0);
        // Read AwesomeButton-specific style attributes from a
        a.recycle();
    }

    // More code
}

Quand Android est LayoutInflater gonfle vues il utilise le 2-l'argument du constructeur avec arguments (Context, AttributeSet). Le R. attr constante est transmise à la 3-l'argument de la version et puis vers le bas à l' Buttons'3-l'argument du constructeur dans l' super appel. Cela signifie qu' Button sera lu par défaut le style d'info pour les choses qu'il encapsule de AwesomeButton's style par défaut comme indiqué dans votre thème. Certains points de Vue à l'intérieur d'Android diffèrent de leur super-classe seulement dans le style par défaut qu'ils utilisent. (Button est en fait l'une de ces valeurs).

Vous spécifiez android:layout_width et android:layout_height dans votre style, mais cela peut être problématique. LayoutParams (de n'importe quel attribut commence par layout_) sont spécifiques à la vue parent, pas de la vue qu'elles apparaissent sur. C'est pourquoi vous devez toujours passer le parent est le deuxième paramètre LayoutInflater#inflate - il dit à la inflater classe qui devrait être responsable de l'interprétation de l' LayoutParams. Si vous ignorez ce que vous trouverez souvent que votre LayoutParams ne se comportent pas comme prévu et sont souvent ignorés dans l'absolu. Par convention, nous n'avons pas mis LayoutParams dans les styles, même si dans certains cas particuliers, il sorte de travaux.

Il semble que vous essayez d'utiliser un style comme une sorte de modèle. Est-il une raison de ne pas utiliser une mise en page de ressources pour le présent et spécifier le style là?

final LayoutInflater inflater = LayoutInflater.from(mActivity);
Button btn = (Button) inflater.inflate(R.layout.styled_button, parentView, false);

res/layout/styled_button.xml:

<Button android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/my_button_background"
        [...] />

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X