カスタムビューのattrs.xml内の同じ名前の属性


179

同じ名前の属性を共有するカスタムビューをいくつか書いています。それぞれの<declare-styleable>セクションでattrs.xml、属性に同じ名前を使用したいと思います。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyView1">
        <attr name="myattr1" format="string" />
        <attr name="myattr2" format="dimension" />
        ...
    </declare-styleable>

    <declare-styleable name="MyView2">
        <attr name="myattr1" format="string" />
        <attr name="myattr2" format="dimension" />
        ...
    </declare-styleable>
</resources>

私はそれを言って、エラーを取得していますmyattr1し、myattr2すでに定義されています。私は省略すべきであることがわかったformatの属性をmyattr1してmyattr2MyView2、私はそれを行う場合、私は、コンソールで次のエラーを取得します:

[2010-12-13 23:53:11 - MyProject] ERROR: In <declare-styleable> MyView2, unable to find attribute 

これを達成する方法はありますか、おそらく何らかの名前空間(推測)ですか?

回答:


401

解決策:両方のビューから共通の属性を抽出し、<resources>ノードの子として直接追加します。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="myattr1" format="string" />
    <attr name="myattr2" format="dimension" />

    <declare-styleable name="MyView1">
        <attr name="myattr1" />
        <attr name="myattr2" />
        ...
    </declare-styleable>

    <declare-styleable name="MyView2">
        <attr name="myattr1" />
        <attr name="myattr2" />
        ...
    </declare-styleable>
</resources>

11
とき何が起こるmyattr1の文字列であるMyView1との整数はMyView2
foxx1337 2013

4
私はそうは思いません。例えば、 'orientation'属性を持つことができ、一部のビューでは 'horizo​​ntal' / 'vertical'で、他の 'landscape' / 'portrait' / 'square'です。私の観点から見ると、これはAndroidのバグ(または少なくとも一貫性のない動作)です(次の点に注意してください:1.スタイル可能な属性は常にprefix = view nameで始まります。2。このようなビューに対して個別のライブラリプロジェクトを作成すると、すべてが正常に機能します)
se.solovyev 2013

4
この回答に従うと、私が ERROR: In <declare-styleable> com_app_view_widget, unable to find attribute customAttr 宣言しようとするすべてのビューに対して、何か案は?
Dapp

45
@Google:不機嫌なデザイン
Glenn Bech

6
@ foxx1337だけを使用してください<attr name="myattr1" format="string|integer" />。私のために働く。
Mygod

57

上記の投稿されたソリューションがAndroid Studioでうまく機能しなかったので、私はこの回答を投稿しています。カスタムビュー間でカスタム属性を共有する必要があるため、Android Studioで上記のソリューションを試しましたが、うまくいきませんでした。だから私は実験し、それを行う方法に行きます。それが同じ問題を探している誰かを助けるかもしれないことを願っています。

  <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <!-- parent styleable -->
     <declare-styleable name="MyView">
         <attr name="myattr1" format="string" />
         <attr name="myattr2" format="dimension" />
     </declare-styleable>

     <!-- inheriting parent styleable -->
     <!-- also note "myBackgroundColor" belongs to child styleable"MyView1"-->
    <declare-styleable name="MyView1" parent="MyView">
        <attr name="myattr1" />
        <attr name="myattr2" />
        <attr name="myBackgroundColor" format="color"/>
    </declare-styleable>


    <!-- inheriting parent styleable -->
    <!-- same way here "myfonnt" belongs to child styelable "MyView2" -->
    <declare-styleable name="MyView2" parent="MyView">
        <attr name="myattr1" />
        <attr name="myattr2" />
        <attr name="myfont" format="string"/>
        ...
    </declare-styleable>
</resources>

これは私にとっては完全に機能します。親をスタイル可能にしてから、その親をスタイル可能に継承する必要があります。たとえば、上で行ったように、親スタイル可能名MyViewを継承し、これをそれぞれMyView1やMyView2などの他のスタイル可能に継承します。


1
これでうまくいきました。受け入れられた回答からコードで抽出された属性を参照する方法が見つかりませんでした。
Nemanja Kovacevic

うーん..それは奇妙です..受け入れられたソリューションは私にとってうまく機能しているようです(targetSdkVersion 27)。「text」などの属性が一般的で、他のattrs.xml ..に存在した可能性があるためでしょうか?
Aba

おそらく珍しい名前で試してみましたが、受け入れられた解決策はまだうまくいきました。
Aba

最初のコメントに同意します!typedArrayから抽出された属性を参照する方法はありません。したがって、スタイル可能な親を定義する必要があります
reavcn

これが機能するためには、子ではなく親でこの属性に対処することを忘れないでください(クラスの場合MyView2R.styleable.MyView2_myattr1、間違った:R.styleable.MyView_myattr1
警戒

27

Priya Singhalが答えたように、Android Studioでは、共通の属性名を独自のスタイル名内で定義する必要があります。彼らはもうルートにいることはできません。

ただし、他にも注意すべきことがいくつかあります(そのため、私も回答を追加しています)。

  • 一般的なスタイルには、ビューと同じ名前を付ける必要はありません。(それを指摘してくれたこの回答に感謝します。)
  • 親との継承を使用する必要はありません。

これは、両方が同じ属性を共有する2つのカスタムビューを持つ最近のプロジェクトで私がやったことです。カスタムビューに属性の名前があり、が含まれていないformat限り、コードから通常どおりにアクセスできます。

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- common attributes to all custom text based views -->

    <declare-styleable name="TextAttributes">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color"/>
        <attr name="gravity">
            <flag name="top" value="48" />
            <flag name="center" value="17" />
            <flag name="bottom" value="80" />
        </attr>
    </declare-styleable>

    <!-- custom text views -->

    <declare-styleable name="View1">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

    <declare-styleable name="View2">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

</resources>

合理化された例

実際、属性をカスタム名の下に置く必要さえありません。format少なくとも1つのカスタムビューに対してそれらを定義する(それらにを与える)限り、どこでも(なしでformat)使用できます。したがって、これも機能します(そして見た目がきれいになります)。

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="View1">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color"/>
        <attr name="gravity">
            <flag name="top" value="48" />
            <flag name="center" value="17" />
            <flag name="bottom" value="80" />
        </attr>
    </declare-styleable>

    <declare-styleable name="View2">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

</resources>

ただし、大規模なプロジェクトの場合、これは煩雑になる可能性があり、1つの場所の上部で定義する方がよい場合があります(ここで推奨)。


継承の何が問題になっていますか?私は、関連付けられたスタイル可能要素がこの関係を反映しないカスタムビュー階層を持っています。これは、命名規則とそこに定義された特定のアイテムによって関連付けられたスタイル定義でのみ推定できます(いくつかは1つのスタイル可能に属し、いくつかは別のスタイル可能に属していることに注意してください)。私はむしろparent属性でそれを明示的にしたいのですが、その使用法を示唆する多くの投稿を見ていません。
samis

@samis、私はしばらくこれに取り組んでいませんが、の使用に問題はありませんparent。必要ないと言っていたと思います。
Suragch

必須ではありません。基本クラスに入れたくない追加の属性をラップした別のサブクラスを作成しました。コメントと命名規則を使用して、分離を示しています。
samis

8

おかげでルイス同じ問題がありました、そしてあなたの継承ソリューションは以下のようにそれを行うためのヒントを私に与えました、そしてそれはうまくいきます。私は上記で共通の属性を宣言し、フォーマットせずにスタイル宣言の本体にもう一度書き直しました。誰かのお役に立てば幸いです

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- common attributes -->
     <attr name="myattr1" format="string" />
     <attr name="myattr2" format="dimension" />

 <!-- also note "myBackgroundColor" belongs to child styleable"MyView1"-->
<declare-styleable name="MyView1" >
    <attr name="myattr1" />
    <attr name="myattr2" />
    <attr name="myBackgroundColor" format="color"/>
</declare-styleable>

<!-- same way here "myfonnt" belongs to child styelable "MyView2" -->
<declare-styleable name="MyView2" parent="MyView">
    <attr name="myattr1" />
    <attr name="myattr2" />
    <attr name="myfont" format="string"/>
    ...
</declare-styleable>


1

誰かが利用可能な解決策を試した後でもまだこの問題で立ち往生している場合に備えて。フォーマット付きのsubtitle属性の追加にこだわっていstringます。

私の解決策は、フォーマットを削除することです。

前:

<attr name="subtitle" format="string"/>

後:

<attr name="subtitle"/>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.