Atributos personalizados em styles.xml

178

Criei um widget personalizado e estou declarando-o em layout.xml. Também adicionei alguns atributos personalizados no attr.xml. No entanto, ao tentar declarar esses atributos em um estilo em styles.xml, está me fornecendoNo resource found that matches the given name: attr 'custom:attribute'.

Eu coloquei o xmlns:custom="http://schemas.android.com/apk/res/com.my.package"em todas as tags em styles.xml, incluindo <?xml>, <resources>e <style>, mas ainda me dá o mesmo erro, que não conseguem encontrar o meu espaço de nomes XML personalizado.

No entanto, posso usar meu espaço para nome para atribuir atributos manualmente à exibição em meu layout.xml, para que não haja nada errado com o espaço para nome. Meu problema está em tornar o styles.xml ciente do meu attr.xml.

styler1972
fonte
1
cutsom:xmlns=...?? não deveria ser xmlns:cutsom=...?
Selvin
Sim, isso é o que eu recebo por não usar copiar / colar graças embora
styler1972

Respostas:

362

Eu descobri isso! A resposta é NÃO especificar o espaço para nome no estilo.

<?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>
styler1972
fonte
13
O erro desaparece, mas minha visão não adota o valor do atributo, enquanto adota os outros atributos (não personalizados). Meu atributo específico é uma enumeração. O snippet acima está funcionando para você?
Paul Lammertsma 7/11
@PaulLammertsma Estou usando uma enumeração e isso também não parece funcionar para mim. Se você não tiver o atributo xmlns do espaço para nome personalizado, poderá digitar qualquer valor que desejar para o atributo de nome do item e ele será compilado.
David Snabel-Caunt
@DavidCaunt Acabei conseguindo o que estava trabalhando para funcionar. Acabei usando uma string para o declare-stylableenum, em vez de. Não sei por que as enums não estavam funcionando, mas essa solução foi boa o suficiente para mim.
Paul Lammertsma
3
Este nem sequer compilar para mim, usando API lvl 16.
David Miler
3
Enquanto isso funciona, suspeito que haveria um problema na resolução dos atributos se um atributo com o mesmo nome existisse em dois ou mais pacotes, mas com nomes de pacotes diferentes.
AndroidDev 6/04/15
43

Como a resposta acima foi trabalhada para mim, tentei uma mudança no comitê, declaro ser estilosa para uma classe no elemento de recursos.

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

em declare-styleable , o atributo name referenciou um nome de classe, portanto, eu tive uma chamada de classe de exibição "com.my.package.name.VerticalView", pois representava que essa declaração deveria ser usada no VerticalView ou nas subclasses de VerticalView. para que possamos declarar estilo assim:

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

por isso não declaramos namespace no elemento resources, ele ainda funciona.

VinceStyling
fonte
11

values ​​/ styles.xml

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

values ​​/ attrs.xml

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

values ​​/ colors.xml

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

values ​​/ dimens.xml

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

Usando

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

insira a descrição da imagem aqui

DEMO

Phan Van Linh
fonte
10

A modificação de Styler e vince funcionou para mim. Queria ressaltar que a explicação de @ vince pode não ser totalmente exata.

Para testar a hipótese de que o atributo name da declare-styleablecorrespondência com o nome da classe de visualização customizada está nos permitindo acessar o atributo customizado sem um espaço para nome, alterei o nome do declare-styleable(a visualização customizada foi nomeada TestViewFont:

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

Alterei a obtainStyledAttributeschamada na exibição personalizada para refletir isso:

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

O código ainda foi executado. Portanto, não acho que seja algum tipo de introspecção por parte declare-styleableda classe que recebeu o nome.

Portanto, sou levado a acreditar que qualquer atributo personalizado pode ser usado para declarar um estilo sem se referir a um espaço para nome.

Independentemente disso, obrigado por toda a ajuda, resolveu o meu problema.

Abid H. Mujtaba
fonte
Na verdade, os atributos compartilham o mesmo espaço para nome, sejam eles declarados em um declare-styleablebloco ou não. (desculpe, não consigo encontrar a página de referência para isso ...) Exceto pelos atributos do androidespaço para nome, você deve indicar apenas o nome do atributo.
Pr-shadoko
3
  • Definir alguns atributos

<declare-styleable name="refreshPullRefreshLayout">
        <attr name="refreshColors" format="reference"/>
        <attr name="refreshColor" format="reference"/>
</declare-styleable>
  • Use-o no arquivo de layout como

<com.aolphn.PullRefreshLayout
     app:refreshColor="@color/main_green"
     app:refreshColors="@array/refresh_color"/>
  • Finalmente use-o no arquivo de estilo

    A diferença entre o arquivo de estilo e o arquivo de layout é que não adicionamos prefiex app:
<style name="refreshStyle">
    <item name="refreshColor">@color/main_green</item>
    <item name="refreshColors">@array/refresh_color</item>
</style>

Experimente, tenha um bom dia, isso funciona para mim.

aolphn
fonte
2

Caso isso ajude mais alguém, meu erro foi que minha classe de exibição personalizada estava chamando AttributeSet.getAttributeValue, por exemplo

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

... o que resultou em meu atributo personalizado não ser lido na minha visualização personalizada.

A correção era para usar obtainStyledAttributesna minha exibição personalizada:

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

Uma dica de que isso está funcionando corretamente é que você pode pressionar Ctrl / Apple + R.styleable.MyTextViewStyleable_customFonte ser direcionado diretamente à sua definição attrs.xml.

Demorei um pouco para identificar essa diferença crítica entre meu código e os outros exemplos, pois o atributo customizado funcionava bem quando transmitido diretamente pelo XML do layout (e não por um estilo).

Dan J
fonte