2011-12-03 8 views
34

Se si desidera impostare lo stile di un pulsante che si crea dal codice, è necessario eseguire qualcosa di simile;Perché è così complesso impostare lo stile dal codice in Android

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

in attrs.xml, è istituito un riferimento

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

In styles.xml, si definisce un tema

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

Che lates in styles.xml è definito come per esempio

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

Questo funziona, e questo è, secondo la mia comprensione, il modo di impostare uno stile su una vista dal codice in Android. Questo sembra troppo complesso. Il terzo argomento del costruttore del pulsante avrebbe potuto facilmente accettare un ID di stile R.style.XXX

Qualcuno può spiegare perché è necessaria questa ulteriore complessità?

+1

Grazie per spiegare come funziona in risorse di sistema di Android, che mi ha aiutato a rispondere alla mia domanda (http://stackoverflow.com/questions/11023335/how-to-set-android-button-background -color/11024343 # 11024343) – Qwertie

risposta

64

Ha a che fare con i pattern incoraggiati all'interno di Android attorno all'uso di Views. Questo non è l'approccio previsto per quello che sembra che tu stia cercando di fare. Per prima cosa spiegherò a cosa serve questo meccanismo e poi suggerirò un approccio per la tua app.

Il terzo argomento di Visualizza costruttori che accetta una risorsa attr viene generalmente utilizzato quando si implementa la vista Visualizza sottoclassi e, come è stato mostrato, consente di specificare un attributo tema da utilizzare come riferimento per lo stile predefinito della vista. Se tu avessi un particolare tipo di pulsante chiamato AwesomeButton si potrebbe attuare i suoi costruttori in questo modo:

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 
} 

Quando Android di LayoutInflater gonfia vista si utilizza il costruttore 2-discussione con gli argomenti (Context, AttributeSet). La costante R.attr viene fatto passare attraverso la versione 3-argomento e poi giù per Button 's costruttore 3-argomento nella chiamata super. Ciò significa che Button leggerà le informazioni di stile predefinite per le cose che incapsula dallo stile predefinito di AwesomeButton come specificato nel tema. Alcune viste all'interno di Android differiscono dalla loro superclasse solo nello stile predefinito che usano. (Button in realtà è uno di questi.)

Specifica android:layout_width e android:layout_height nel tuo stile ma questo può essere problematico. LayoutParams (qualsiasi attributo che inizia con layout_) è specifico per la visualizzazione padre, non per la vista in cui vengono visualizzati. Questo è il motivo per cui si passa sempre la vista genitore desiderata come secondo parametro a LayoutInflater#inflate - indica all'infatturatore quale classe dovrebbe essere responsabile dell'interpretazione dello LayoutParams. Se si salta questo si trovano spesso che il vostro LayoutParams non si comportano come ci si aspetta e sono spesso ignorati a titolo definitivo. Per convenzione non inseriamo lo LayoutParams negli stili, anche se in alcuni casi speciali funziona in qualche modo.

Sembra che si sta cercando di utilizzare uno stile come una sorta di modello. C'è un motivo per non utilizzare una risorsa di layout per questo e specificare lo stile 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" 
     [...] /> 
+0

Questa è un'ottima risposta e il mio codice ora è molto più semplice. Non avevo davvero bisogno di andare "fino in fondo" e creare un nuovo tema. Ho finito per mantenere il mio androide: layout_height = "@ dimen/actionbar_compat_height". Un'altra opzione avrebbe potuto essere la creazione di diversi styled_button.xml per layout-xlarge ecc. Grazie per aver dedicato del tempo. Lo capisco adesso. –

+0

Grande, felice che abbia aiutato a chiarire le cose per te. – adamp

+0

Wow. Questa risposta mi è piaciuta così tanto che ho svettato questo e un altro dallo stesso utente :-) – SJuan76

Problemi correlati