Пользовательские атрибуты в styles.xml

178

Я создал собственный виджет и объявляю его в layout.xml. Я также добавил несколько пользовательских атрибутов в attr.xml. Тем не менее, при попытке объявить эти атрибуты в стиле в styles.xml, это дает мнеNo resource found that matches the given name: attr 'custom:attribute'.

Я поместил xmlns:custom="http://schemas.android.com/apk/res/com.my.package"все теги в styles.xml, в том числе <?xml>, <resources>и <style>, но все равно выдает ту же ошибку, что не может найти мое собственное пространство имен XML.

Однако я могу использовать свое пространство имен, чтобы вручную назначать атрибуты представлению в layout.xml, поэтому с пространством имен все в порядке. Моя проблема заключается в информировании файла styles.xml о моем файле attr.xml.

styler1972
источник
1
cutsom:xmlns=...?? не должно быть xmlns:cutsom=...?
Селвин
Да, это то, что я получаю за то, что не использую копирование / вставку, спасибо
styler1972

Ответы:

362

Я понял! Ответ - НЕ указывать пространство имен в стиле.

<?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
источник
13
Ошибка исчезает, но мое представление не принимает значение атрибута, в то время как оно принимает другие (не пользовательские) атрибуты. Мой особенный атрибут - enum. Фрагмент выше работает на вас?
Пол Ламмерцма
@PaulLammertsma Я использую перечисление, и это, похоже, не работает для меня. Если у вас нет пользовательского атрибута пространства имен xmlns, вы можете ввести любое значение для атрибута имени элемента, и он скомпилируется.
Дэвид Снабел-Каунт
@DavidCaunt Я в итоге получил то, над чем работал. В конце концов я использовал строку declare-stylableвместо перечисления. Я не уверен, почему перечисления не работали, но этот обходной путь был достаточно хорош для меня.
Пол Ламмерцма
3
Это даже не компилируется для меня, используя API lvl 16.
David Miler
3
Хотя это работает, я подозреваю, что будет проблема с разрешением атрибутов, если атрибут с одинаковым именем существует в двух или более пакетах, но с разными именами пакетов.
AndroidDev
43

Приведенный выше ответ работает для меня, я попробовал небольшое изменение, я объявляю styleable для класса в элементе ресурсов.

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

в возвещайте-styleable , то имя атрибута ссылается имя класса, так что я имел вид класса вызов «com.my.package.name.VerticalView», он представлял это DECLARE должно быть использование в VerticalView или подклассов VerticalView. поэтому мы можем объявить стиль следующим образом:

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

вот почему мы не объявили пространство имен в элементе ресурсов, оно все еще работает.

VinceStyling
источник
11

Значения / styles.xml

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

Значения / attrs.xml

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

Значения / colors.xml

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

Значения / dimens.xml

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

С помощью

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

введите описание изображения здесь

DEMO

Фан Ван Линь
источник
10

Модификация Стилера и Винса сработала для меня. Я хотел отметить, что объяснение @ vince может быть не совсем точным.

Чтобы проверить гипотезу о том, что атрибут name, declare-styleableсовпадающий с именем пользовательского класса представления, позволяет нам получить доступ к пользовательскому атрибуту без пространства имен, я изменил имя declare-styleable(пользовательское представление было названо TestViewFont:

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

Затем я изменил obtainStyledAttributesвызов в пользовательском представлении, чтобы отразить это:

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

Код все еще работает. Так что я не думаю, что это какой-то самоанализ declare-styleableкласса, в честь которого он назван.

Таким образом, меня убеждают, что любые пользовательские атрибуты могут использоваться для объявления стиля без обращения к пространству имен.

Несмотря на это, спасибо за помощь, ребята, это решило мою проблему.

Абид Х. Муджаба
источник
Фактически, атрибуты совместно используют одно и то же пространство имен, независимо от того, объявлены они в declare-styleableблоке или нет. (извините, я не могу найти справочную страницу для этого ...) За исключением атрибутов из androidпространства имен, вы должны указывать только имя атрибута.
пр-шадоко
3
  • Определите некоторые атрибуты

<declare-styleable name="refreshPullRefreshLayout">
        <attr name="refreshColors" format="reference"/>
        <attr name="refreshColor" format="reference"/>
</declare-styleable>
  • Используйте его в файле макета, как

<com.aolphn.PullRefreshLayout
     app:refreshColor="@color/main_green"
     app:refreshColors="@array/refresh_color"/>
  • Наконец, используйте его в файле стиля

    Разница между файлом стиля и файлом макета в том, что мы не добавляем prefiex app:
<style name="refreshStyle">
    <item name="refreshColor">@color/main_green</item>
    <item name="refreshColors">@array/refresh_color</item>
</style>

Попробуйте, хорошего дня, это работает для меня.

aolphn
источник
2

В случае, если это поможет кому-то еще, моя ошибка состояла в том, что мой класс пользовательского представления вызывал AttributeSet.getAttributeValue, например

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

... что привело к тому, что мой пользовательский атрибут не был прочитан для моего пользовательского представления.

Исправление было использовать obtainStyledAttributesв моем пользовательском представлении:

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

Намек на то, что это работает правильно, заключается в том, что вы можете нажать Ctrl / Apple +, нажав на R.styleable.MyTextViewStyleable_customFont чтобы перейти прямо к определению attrs.xml.

Мне потребовалось некоторое время, чтобы обнаружить это критическое различие между моим кодом и другими примерами, так как пользовательский атрибут работал нормально, когда передавался напрямую через XML макета (а не через стиль).

Дэн Дж
источник