Niestandardowe atrybuty w styles.xml

178

Utworzyłem niestandardowy widget i ogłaszam go w layout.xml. Dodałem także niestandardowe atrybuty w pliku attr.xml. Jednak gdy próbuję zadeklarować te atrybuty w stylu w styles.xml, daje mi toNo resource found that matches the given name: attr 'custom:attribute'.

Umieściłem xmlns:custom="http://schemas.android.com/apk/res/com.my.package"we wszystkich tagach w styles.xml, w tym <?xml>, <resources>i <style>, ale nadal daje mi ten sam błąd, że nie może znaleźć mojej niestandardowej przestrzeni nazw XML.

Mogę jednak użyć mojej przestrzeni nazw, aby ręcznie przypisać atrybuty do widoku w moim layout.xml, więc nie ma nic złego w przestrzeni nazw. Mój problem polega na uświadomieniu styles.xml mojego attr.xml.

styler1972
źródło
1
cutsom:xmlns=...?? nie powinno być xmlns:cutsom=...?
Selvin
Tak, właśnie to dostaję za to, że nie korzystałem z funkcji kopiuj / wklej, dzięki
styler1972

Odpowiedzi:

362

Rozgryzłem to! Odpowiedź brzmi: NIE należy określać przestrzeni nazw w stylu.

<?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
źródło
13
Błąd znika, ale mój widok nie przyjmuje wartości atrybutu, podczas gdy przyjmuje inne (niestandardowe) atrybuty. Moim szczególnym atrybutem jest wyliczenie. Czy powyższy fragment działa dla Ciebie?
Paul Lammertsma,
@PaulLammertsma Używam wyliczenia i to też nie działa dla mnie. Jeśli nie masz niestandardowego atrybutu przestrzeni nazw xmlns, możesz wpisać dowolną wartość atrybutu nazwy elementu, która się skompiluje.
David Snabel-Caunt,
@DavidCaunt W końcu dostałem to, nad czym pracowałem . W końcu użyłem łańcucha declare-stylablezamiast enum. Nie jestem pewien, dlaczego wyliczenia nie działały, ale to obejście było dla mnie wystarczająco dobre.
Paul Lammertsma,
3
To nawet mnie nie kompiluje, używając API na poziomie 16
David Miler
3
Chociaż działa, podejrzewam, że wystąpiłby problem z rozwiązaniem atrybutów, gdyby atrybut o tej samej nazwie istniał w dwóch lub większej liczbie pakietów, ale o różnych nazwach pakietów.
AndroidDev,
43

powyższa odpowiedź jest dla mnie sprawdzona, próbowałem drobnej zmiany, deklaruję stylowy dla klasy element zasobów.

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

w declare-styleable The nazwa atrybutu odwołuje nazwę klasy, więc miałem widok klasy połączenia „com.my.package.name.VerticalView”, to stwierdzenie, że przedstawiciele muszą mieć zastosowanie w VerticalView lub podklas VerticalView. więc możemy zadeklarować styl w ten sposób:

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

dlatego nie zadeklarowaliśmy przestrzeni nazw w elemencie zasobów, nadal działa.

VinceStyling
źródło
11

wartości / styles.xml

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

wartości / attrs.xml

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

wartości / kolory.xml

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

wartości / dimens.xml

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

Za pomocą

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

wprowadź opis zdjęcia tutaj

PRÓBNY

Phan Van Linh
źródło
10

Modyfikacja Stylera i Vince'a działała dla mnie. Chciałem zauważyć, że wyjaśnienie @ vince'a może nie być całkowicie dokładne.

Aby przetestować hipotezę, że atrybut name declare-styleablepasujący do nazwy niestandardowej klasy widoku umożliwia nam dostęp do atrybutu niestandardowego bez przestrzeni nazw, zmieniłem nazwę declare-styleable(widok niestandardowy został nazwany TestViewFont:

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

Następnie zmieniłem obtainStyledAttributespołączenie w widoku niestandardowym, aby odzwierciedlić to:

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

Kod nadal działał. Więc nie sądzę, że jest to jakaś introspekcjadeclare-styleable klasy, od której pochodzi jej nazwa.

W ten sposób jestem przekonany, że wszelkie niestandardowe atrybuty mogą być użyte do deklarowania stylu bez odwoływania się do przestrzeni nazw.

Niezależnie od tego, dzięki za pomoc, chłopaki rozwiązali mój problem.

Abid H. Mujtaba
źródło
W rzeczywistości atrybuty mają tę samą przestrzeń nazw, niezależnie od tego, czy są zadeklarowane w declare-styleablebloku, czy nie. (przepraszam, nie mogę znaleźć strony referencyjnej dla tego…) Z wyjątkiem atrybutów z androidprzestrzeni nazw, powinieneś podać tylko nazwę atrybutu.
pr-shadoko
3
  • Zdefiniuj niektóre atrybuty

<declare-styleable name="refreshPullRefreshLayout">
        <attr name="refreshColors" format="reference"/>
        <attr name="refreshColor" format="reference"/>
</declare-styleable>
  • Użyj go w pliku układu, takim jak

<com.aolphn.PullRefreshLayout
     app:refreshColor="@color/main_green"
     app:refreshColors="@array/refresh_color"/>
  • Na koniec użyj go w pliku stylu

    Różnica między plikiem stylu a plikiem układu polega na tym, że nie dodajemy prefiksów app:
<style name="refreshStyle">
    <item name="refreshColor">@color/main_green</item>
    <item name="refreshColors">@array/refresh_color</item>
</style>

Spróbuj, miłego dnia, to działa dla mnie.

aolphn
źródło
2

Jeśli pomógłby komukolwiek innemu, mój błąd polegał na tym, że moja niestandardowa klasa widoku wywoływała AttributeSet.getAttributeValue np.

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

... co spowodowało, że mój niestandardowy atrybut nie został odczytany dla mojego widoku niestandardowego.

Poprawka polegała na użyciu obtainStyledAttributesw moim widoku niestandardowym:

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

Wskazówka, że ​​to działa poprawnie, polega na tym, że możesz Ctrl / Apple + kliknąć na, R.styleable.MyTextViewStyleable_customFontaby przejść bezpośrednio do definicji attrs.xml.

Zajęło mi trochę czasu zauważenie tej krytycznej różnicy między moim kodem a innymi przykładami, ponieważ niestandardowy atrybut działał dobrze, gdy był przekazywany bezpośrednio przez układ XML (zamiast przez styl).

Dan J.
źródło