2011-12-03 6 views
34

作成するボタンのスタイルをコードから設定する場合は、このようなことをする必要があります。 attrs.xmlでなぜAndroidのコードからスタイルを設定するのが複雑か

Button btn = new Button (mActivity, null, R.attr.someattribute); 

、あなたがのstyles.xmlで

<attr name="someStyleRef" format="reference"/> 

参照を設定するには、テーマのstyles.xmlでlatesは、同様に定義されて

<resources> 
    <style name="Theme.SomeTheme" parent="android:style/Theme.Black"> 
    <item name="someStyleRef">@style/someStyle</item> 
    </style> 
</resources> 

を定義します例

<style name="someStyle"> 
     <item name="android:layout_width">2px</item> 
     <item name="android:layout_height">fill_parent</item> 
     <item name="android:background">@drawable/actionbar_compat_separator</item> 
</style> 

これは動作しますが、これは、私の理解によれば、AndroidのコードからViewにスタイルを設定する方法です。これは複雑すぎるようです。ボタンの3番目のコンストラクタArgumentは簡単にスタイルIDを受け入れることができましたR.style.XXX

誰もこの余分な複雑さが必要な理由を説明できますか?

+1

おかげで、それは私が自分の質問(http://stackoverflow.com/questions/11023335/how-to-set-android-button-backgroundに答える助けました-color/11024343#11024343) – Qwertie

答えて

64

これは、ビュー内でAndroidの奨励されたパターンと関係があります。これは、あなたがしようとしているように見えるための意図されたアプローチではありません。最初に、このメカニズムが何のためにあるのかを説明し、あなたのアプリのアプローチを提案します。

attrリソースを受け取るViewコンストラクタの3番目の引数は、Viewサブクラスを実装するときに一般的に使用され、表示されているように、Viewのデフォルトスタイルへの参照として使用するテーマ属性を指定できます。 AndroidのLayoutInflaterはそれが引数(Context, AttributeSet)と2引数のコンストラクタを使用してビューを膨張させるとき

public class AwesomeButton extends Button { 
    public AwesomeButton(Context context) { 
     this(context, null); 
    } 

    public AwesomeButton(Context context, AttributeSet attrs) { 
     this(context, attrs, R.attr.awesomeButtonStyle); 
    } 

    public AwesomeButton(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr) { 
     final TypedArray a = context.obtainStyledAttributes(attrs, 
       R.styleable.AwesomeButton, defStyleAttr, 0); 
     // Read AwesomeButton-specific style attributes from a 
     a.recycle(); 
    } 

    // More code 
} 

:あなたはAwesomeButtonと呼ばれるボタンの特別な種類を持っていた場合は、このようなそのコンストラクタを実装するかもしれません。 R.attr定数は、3引数のバージョンに渡され、super呼び出しでは、Buttonの3引数のコンストラクタに渡されます。これは、Buttonが、あなたのテーマに指定されたAwesomeButtonのデフォルトスタイルからカプセル化するもののデフォルトのスタイリング情報を読み込むことを意味します。 Androidの一部のビューは、使用するデフォルトスタイルでのみスーパークラスと異なります。 (Buttonは実際にはこれらのいずれかです)

あなたのスタイルでandroid:layout_widthandroid:layout_heightを指定しますが、これは問題になります。 LayoutParams(すべての属性がlayout_で始まる)は、親ビューに固有のものであり、表示されるビューではありません。これは、第2のパラメータとして意図された親ビューを常にLayoutInflater#inflateに渡す理由です。インフレータにどのクラスがLayoutParamsの解釈を担当するべきかを伝えます。これをスキップすると、多くの場合、LayoutParamsが期待どおりに動作せず、完全に無視されることがよくあります。慣例によっては、特別な場合には作品を並べ替えても、LayoutParamsはスタイルに入れません。

スタイルをテンプレートのように使用しようとしているようです。これにレイアウトリソースを使用せず、そこにスタイリングを指定しない理由はありますか?

final LayoutInflater inflater = LayoutInflater.from(mActivity); 
Button btn = (Button) inflater.inflate(R.layout.styled_button, parentView, false); 

res/layout/styled_button。XML:それはAndroidのシステムリソースにどのように機能するかを説明するための

<Button android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:background="@drawable/my_button_background" 
     [...] /> 
+0

これは非常に良い答えです。私のコードは今よりずっと簡単です。私は本当に "すべての方法"に行き、新しいテーマを作成する必要はありませんでした。私はアンドロイド:layout_height = "@ dimen/actionbar_compat_height"を保ちました。別のオプションは、layout-xlargeなどのために異なるstyled_button.xmlを作成することでした。時間をとってくれてありがとう。わかった。 –

+0

嬉しいことに、それはあなたのために明確なことを助けました。 – adamp

+0

うわー。私はこの回答をとても好きにしていました。同じユーザーから別のものをアップボードしました:-) – SJuan76