Attributi personalizzati in styles.xml


178

Ho creato un widget personalizzato e lo sto dichiarando in layout.xml. Ho anche aggiunto alcuni attributi personalizzati in attr.xml. Tuttavia, quando provo a dichiarare questi attributi in uno stile in styles.xml, mi sta dandoNo resource found that matches the given name: attr 'custom:attribute'.

Ho inserito xmlns:custom="http://schemas.android.com/apk/res/com.my.package"tutti i tag in styles.xml, incluso <?xml>, <resources>e <style>, ma mi dà ancora lo stesso errore, che non riesce a trovare il mio spazio dei nomi XML personalizzato.

Tuttavia, posso usare il mio spazio dei nomi per assegnare manualmente gli attributi alla vista in mio layout.xml, quindi non c'è nulla di sbagliato nello spazio dei nomi. Il mio problema sta nel rendere styles.xml consapevole del mio attr.xml.


1
cutsom:xmlns=...?? non dovrebbe essere xmlns:cutsom=...?
Selvin,

Sì, è quello che ottengo per non aver usato copia / incolla grazie
styler1972,

Risposte:


362

L'avevo capito! La risposta è NON specificare lo spazio dei nomi nello stile.

<?xml version="1.0" encoding="utf-8" ?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <style name="CustomStyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>

        <item name="custom_attr">value</item> <!-- tee hee -->
    </style>
</resources>

13
L'errore scompare, ma la mia vista non adotta il valore dell'attributo, mentre adotta gli altri attributi (non personalizzati). Il mio attributo particolare è un enum. Lo snippet sopra funziona per te?
Paul Lammertsma,

@PaulLammertsma Sto usando un enum e questo non sembra funzionare neanche per me. Se non si dispone dell'attributo xmlns dello spazio dei nomi personalizzato, è possibile digitare qualsiasi valore desiderato per l'attributo nome elemento e verrà compilato.
David Snabel-Caunt,

@DavidCaunt Alla fine ho capito cosa stavo lavorando per funzionare. Alla fine ho usato una stringa per declare-stylableinvece di un enum. Non sono sicuro del motivo per cui gli enum non funzionassero, ma questa soluzione era abbastanza buona per me.
Paul Lammertsma,

3
Questo non si compila nemmeno per me, usando API lvl 16.
David Miler,

3
Mentre funziona, sospetto che ci sarebbe un problema a risolvere gli attributi se esistesse un attributo con lo stesso nome in due o più pacchetti ma con nomi di pacchetto diversi.
AndroidDev,

43

sopra la risposta ha funzionato per me, ho provato un cambio di litte, dichiaro modellabile per una classe nell'elemento risorse

<declare-styleable name="VerticalView">
    <attr name="textSize" format="dimension" />
    <attr name="textColor" format="color" />
    <attr name="textBold" format="boolean" />
</declare-styleable>

in declare-stylable , l' attributo name faceva riferimento a un nome di classe, quindi ho avuto una chiamata di classe view "com.my.package.name.VerticalView", che rappresentava questa dichiarazione deve essere utilizzata in VerticalView o nelle sottoclassi di VerticalView. così possiamo dichiarare lo stile in questo modo:

<resources>
    <style name="verticalViewStyle">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">36dip</item>

        <item name="textSize">28sp</item>  <!-- not namespace prefix -->
        <item name="textColor">#ff666666</item>
        <item name="textBold">true</item>
    </style>
</resources>

ecco perché non abbiamo dichiarato lo spazio dei nomi nell'elemento risorse, funziona ancora.


11

Valori / styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <item name="defaultButtonColor">@color/red</item>
    <item name="defaultButtonHeight">@dimen/dp_100</item>
</style>

Valori / attrs.xml

<resources>
    <attr name="defaultButtonColor" format="reference" />
    <attr name="defaultButtonHeight" format="reference"/>
</resources>

Valori / colors.xml

<resources>
    <color name="red">#f00</color>
</resources>

Valori / dimens.xml

<resources>
    <dimen name="dp_100">100dp</dimen>
</resources>

utilizzando

<Button
    android:layout_width="wrap_content"
    android:layout_height="?attr/defaultButtonHeight"
    android:text="Button"
    android:textColor="?attr/defaultButtonColor"
    />

inserisci qui la descrizione dell'immagine

DEMO


10

La modifica di Styler e Vince ha funzionato per me. Volevo sottolineare che la spiegazione di @ vince potrebbe non essere del tutto accurata.

Per verificare l'ipotesi che l'attributo name della declare-styleablecorrispondenza con il nome della classe della vista personalizzata ci consenta di accedere all'attributo personalizzato senza uno spazio dei nomi, ho cambiato il nome della declare-styleable(la vista personalizzata era denominata TestViewFont:

<declare-styleable name="TextViewFont2">
    <attr name="font" format="integer"/>
</declare-styleable>

Ho quindi modificato la obtainStyledAttributeschiamata nella vista personalizzata per riflettere questo:

TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TextViewFont2, 0, 0);

Il codice è ancora in esecuzione. Quindi non penso che sia una sorta di introspezione da parte declare-styleabledella classe da cui prende il nome.

Quindi sono portato a credere che qualsiasi attributo personalizzato possa essere usato per dichiarare uno stile senza fare riferimento a uno spazio dei nomi.

Indipendentemente da ciò, grazie per tutto l'aiuto ragazzi, ha risolto il mio problema.


In realtà, gli attributi condividono lo stesso spazio dei nomi, indipendentemente dal fatto che siano dichiarati in un declare-styleableblocco o meno. (scusate, non riesco a trovare la pagina di riferimento per questo ...) Tranne gli attributi dallo androidspazio dei nomi, dovreste solo indicare il nome dell'attributo.
pr-shadoko,

3
  • Definisci alcuni attributi

<declare-styleable name="refreshPullRefreshLayout">
        <attr name="refreshColors" format="reference"/>
        <attr name="refreshColor" format="reference"/>
</declare-styleable>
  • Usalo come file di layout come

<com.aolphn.PullRefreshLayout
     app:refreshColor="@color/main_green"
     app:refreshColors="@array/refresh_color"/>
  • Finalmente usalo nel file di stile

    La differenza tra file di stile e file di layout è che non aggiungiamo prefiex app:
<style name="refreshStyle">
    <item name="refreshColor">@color/main_green</item>
    <item name="refreshColors">@array/refresh_color</item>
</style>

Provalo, buona giornata, questo funziona per me.


2

Nel caso in cui aiuti qualcun altro, il mio errore è stato che la mia classe di visualizzazione personalizzata stava chiamando AttributeSet.getAttributeValue ad es.

String fontName = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "customFont");

... il che comportava la mancata lettura del mio attributo personalizzato per la mia vista personalizzata.

La correzione era da usare obtainStyledAttributesnella mia vista personalizzata:

 TypedArray styleAttrs = context.obtainStyledAttributes(attrs, R.styleable.MyTextViewStyleable);
 String fontName = styleAttrs.getString(R.styleable.MyTextViewStyleable_customFont);

Un suggerimento che questo funziona correttamente è che puoi Ctrl / Apple + fare clic su R.styleable.MyTextViewStyleable_customFontper essere portato direttamente alla tua definizione attrs.xml.

Mi ci è voluto un po 'per individuare questa differenza critica tra il mio codice e gli altri esempi, poiché l'attributo personalizzato ha funzionato bene quando è passato direttamente attraverso l'XML del layout (anziché attraverso uno stile).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.