Android:プログラムでビュースタイルを設定する


226

ここにXMLがあります:

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/LightStyle"
    android:layout_width="fill_parent"
    android:layout_height="55dip"
    android:clickable="true"
    android:orientation="horizontal" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal" />

</RelativeLayout>

styleプログラムで属性を設定する方法は?


こちら['response'] [1]をご覧ください。これでうまくいきました。[1]:stackoverflow.com/a/5488652/2938493
Artificioo

回答:


211

技術的には、カスタムビューを使用して、プログラムでスタイルを適用できます。

private MyRelativeLayout extends RelativeLayout {
  public MyRelativeLayout(Context context) {
     super(context, null, R.style.LightStyle);
  }
}

1つの引数のコンストラクタは、プログラムでビューをインスタンス化するときに使用されるものです。

したがって、このコンストラクタを、スタイルパラメータを受け取るスーパーにチェーンします。

RelativeLayout someLayout = new MyRelativeLayout(new ContextThemeWrapper(this,R.style.RadioButton));

または@Doriが簡単に指摘したように:

RelativeLayout someLayout = new RelativeLayout(new ContextThemeWrapper(activity,R.style.LightStyle));

34
3引数のコンストラクタはとにかく公開されてあなただけのプログラムで延長せずにこれを行うことがdeveloper.android.com/reference/android/widget/...、android.util.AttributeSet、INT)
通り

1
@ Turbo、docsとeclipseの両方がそれを教えてくれるはずですhttp://developer.android.com/reference/android/widget/LinearLayout.html#LinearLayout(android.content.Context, android.util.AttributeSet, int)。LinearLayoutでは、レベル11以上が必要です。
TheOne、2014

2
@Doriあなたは何を渡しAttributeSetますか?
Blundell

9
TextViewの場合、テキストに影響を与える属性(サイズ、色など)にはsetTextAppearance(R.style.small_text)を使用する必要があります
Maragues

2
なぜ第3引数のアプローチが機能しないのかわかりません。に応募しましたButton。@ベンジャミン・ピエットのアプローチはうまくいきます。
Youngjae

124

私のために働いたもの:

Button b = new Button(new ContextThemeWrapper(this, R.style.ButtonText), null, 0);
  • ContextThemeWrapperを使用する

そして

  • 3引数コンストラクタを使用します(これがないと動作しません)

メソッドの使用は機能しますが、W / ResourceTypeを取得します。属性参照が多すぎます。0x01010034で停止しました。回避策はありますか?
HaloMediaz 2015

私はその問題を見たことがありません。デバイス固有の問題か、最近のAndroidバージョンに関連した問題の可能性がありますか?
Benjamin Piette、2015

11
重要!このメソッド機能しますが、ContextThemeWrapperで新しいレイアウトを作成する場合は、すべての子ビューにもスタイルを設定します。
aProperFox

@aProperFoxはもっとよく説明できますか?私はボタンに追加するだけで機能します。レイアウトを参照しますか?
ギリアン

1
@Gilian正確には、1つ以上の子を持つ複合ビューでこれを使用すると、スタイルを設定した親ビューと同じスタイルになります。これは、内側のビュー内の余計な余白や余白につながる可能性があり、気付いていない場合は狂気に
陥る可能

88

更新:この質問に回答した時点(2012年半ば、APIレベル14-15)では、プログラムでビューを設定することは(いくつかの重要な回避策があったとしても)オプションではありませんでしたが、これは最近のAPIの後に可能になりましたリリース。詳細については、@ Blundellの回答を参照してください。

古い答え:

プログラムでビューのスタイルを設定することはまだできませんが、このスレッドは便利な場合があります。


16
違います。@Blundellの回答を参照してください。
a.bertucci 2014年

31
状況によっては(たとえばTextViewを使用して)、を使用できますtextView.setTextAppearance(context, R.style.mystyle);。ドキュメントによると、「指定されたTextAppearanceリソースから、テキストの色、サイズ、スタイル、ヒントの色、およびハイライトの色を設定します。」developer.android.com/reference/android/widget/...、INT)
Rogelガルシア

4
api> 23; textView.setTextAppearance(R.style.mystyle);
アリカンakyol

1
私は4年以上前にこの回答を投稿しました@HaydenKai。APIは、スタイルをプログラムで適用できるようにして以来、大幅に変更されています。
Korhan Ozturk

3
@KorhanOzturkは同意しましたが、SOでこのような質問があり、活動があるため、質問を再開して新しい回答を受け入れる必要があります
HaydenKai

16

新しいButton / TextViewの場合:

Button mMyButton = new Button(new ContextThemeWrapper(this, R.style.button_disabled), null, 0);

既存のインスタンスの場合:

mMyButton.setTextAppearance(this, R.style.button_enabled);

画像またはレイアウトの場合:

Image mMyImage = new ImageView(new ContextThemeWrapper(context, R.style.article_image), null, 0);

8

XMLの使用を継続し(これは受け入れられた回答では許可されていません)、ビューの作成後にスタイルを設定する場合は、利用可能なすべての属性のサブセットをサポートするParisライブラリを使用できる場合があります。

XMLからビューを拡張しているので、レイアウトでIDを指定する必要があります。

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/my_styleable_relative_layout"
    style="@style/LightStyle"
    ...

次に、レイアウトを拡張した後で、プログラムでスタイルを変更する必要がある場合:

// Any way to get the view instance will do
RelativeLayout myView = findViewById(R.id.my_styleable_relative_layout);

// This will apply all the supported attribute values of the style
Paris.style(myView).apply(R.style.LightStyle);

詳細:サポートされているビューのタイプと属性のリスト(背景、パディング、マージンなどが含まれ、簡単に拡張できます)および追加のドキュメントを含むインストール手順

免責事項:私はその図書館の原作者です。


これはまだ2019年に使用する推奨アプローチですか?
IgorGanapolsky

1
@IgorGanapolsky afaikはい!もっと良いものは知りません。
ナタナエル

このソリューションを提供してくれてありがとう@Nathanael。また、最新のline_height属性を備えたメンテナーでもあります。今後ともよろしくお願いいたします。本当に便利です。
Guillem Roca

7

次のようにして、アクティビティにスタイルを適用できます。

super.setTheme( R.style.MyAppTheme );

またはAndroidのデフォルト:

super.setTheme( android.R.style.Theme );

あなたの活動の前にsetContentView()


4
@siemian FOMに自分を自由に表現させてください。彼は編集する必要はありません!
ミカ

6

提供された回答のいずれも正しくありません。

プログラムでスタイルを設定できます。

短い答えは、http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/content/Context.java#435をご覧ください。

長い答え。プログラムでカスタム定義スタイルをビューに設定するためのスニペットを次に示します。

1)styles.xmlファイルにスタイルを作成します

 <style name="MyStyle">
    <item name="customTextColor">#39445B</item>
    <item name="customDividerColor">#8D5AA8</item>
</style>

attrs.xmlファイルでカスタム属性を定義することを忘れないでください

私のattrsl.xmlファイル:

<declare-styleable name="CustomWidget">
    <attr name="customTextColor" format="color" />
    <attr name="customDividerColor" format="color" />
</declare-styleable>

スタイル可能(my CustomWidget)には任意の名前を使用できます。

次に、スタイルをウィジェットにプログラムで設定します。これが私の簡単なウィジェットです。

public class StyleableWidget extends LinearLayout {

private final StyleLoader styleLoader = new StyleLoader();

private TextView textView;
private View divider;

public StyleableWidget(Context context) {
    super(context);
    init();
}

private void init() {
    inflate(getContext(), R.layout.widget_styleable, this);
    textView = (TextView) findViewById(R.id.text_view);
    divider = findViewById(R.id.divider);
    setOrientation(VERTICAL);
}

protected void apply(StyleLoader.StyleAttrs styleAttrs) {
    textView.setTextColor(styleAttrs.textColor);
    divider.setBackgroundColor(styleAttrs.dividerColor);
}

public void setStyle(@StyleRes int style) {
    apply(styleLoader.load(getContext(), style));
}
}

レイアウト:

<TextView
    android:id="@+id/text_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="22sp"
    android:layout_gravity="center"
    android:text="@string/styleble_title" />

<View
    android:id="@+id/divider"
    android:layout_width="match_parent"
    android:layout_height="1dp"/>

</merge>

そして最後にStyleLoaderクラスの実装

public class StyleLoader {

public StyleLoader() {

}

public static class StyleAttrs {
    public int textColor;
    public int dividerColor;
}

public StyleAttrs load(Context context, @StyleRes int styleResId) {
    final TypedArray styledAttributes = context.obtainStyledAttributes(styleResId, R.styleable.CustomWidget);
    return load(styledAttributes);
}

@NonNull
private StyleAttrs load(TypedArray styledAttributes) {
    StyleAttrs styleAttrs = new StyleAttrs();
    try {
        styleAttrs.textColor = styledAttributes.getColor(R.styleable.CustomWidget_customTextColor, 0);
        styleAttrs.dividerColor = styledAttributes.getColor(R.styleable.CustomWidget_customDividerColor, 0);
    } finally {
        styledAttributes.recycle();
    }
    return styleAttrs;
}
}

完全に機能する例は、https://github.com/Defuera/SetStylableProgramaticallyにあります。


13
これは、それはあなたのビューに保存した設定を設定/適用することにより、単に偽物(はい、それは実際にあなたのXMLファイルに保存された設定の一部のようなものだ)(真のスタイルですされていない、ここであなただけの2の固定ビューを持っている- そして、あなたは確かにそれを知っている必要があります予め)。すべての魔法は、apply何も面白くない方法にあります。スタイルの本当の意味は、将来動的に追加されるすべてのビューに何らかの視覚スタイルを自動的に適用することです。もちろん、このコードではそれができず、動的なものはありません。どのビューとどのプロパティ/フィールドを設定するかを知る必要があります。
キングキング

1
どのビューにスタイルを適用するかを指定してもかまいませんが、このソリューションではスタイル要素がハードコーディングされています(例:textColorやdividerColor)。スタイルで定義されているすべての要素を動的に検索してビューに適用することはありません。
nasch 2017

投稿したリンクが開きません。再投稿して頂けますか?
IgorGanapolsky

4

これはかなり古い質問ですが、今私のために機能した解決策は、コンストラクタの4番目のパラメータを使用することdefStyleResです-可能な場合..ビューで...スタイルを設定する

私の目的のために以下の作品(kotlin):

val textView = TextView(context, null, 0, R.style.Headline1)

3

これは私の簡単な例です。キーはContextThemeWrapperラッパーです。これがないと、スタイルが機能せず、ビューの3つのパラメーターコンストラクターを使用します。

ContextThemeWrapper themeContext = new ContextThemeWrapper(this, R.style.DefaultLabelStyle);
TextView tv = new TextView(themeContext, null, 0);
tv.setText("blah blah ...");
layout.addView(tv);

2

簡単な方法はコンストラクタを通過することです

RadioButton radioButton = new RadioButton(this,null,R.style.radiobutton_material_quiz);

このソリューションの使用方法についてもう少し説明すると役立ちます。
IgorGanapolsky

1

これを行うため、ContextThemeWrapperの使用は提案しません。

指定されたテーマは、ベースコンテキストのテーマの上に適用されます。

アプリケーションに望ましくない結果をもたらす可能性のあるもの。代わりに、Airbnbのエンジニアからこのための新しいライブラリ「パリ」を提案します。

https://github.com/airbnb/paris

プログラムでスタイルを定義し、Androidビューに適用します。

しかし、しばらく使用した後、実際には非常に制限されていることがわかり、すぐに使用する必要がある多くのプロパティをサポートしていないため、使用を中止しました。


あなたの反対票について説明してください... ContextThemeWrapperを使用したために1日半を失い、それが私のコンテキストテーマの白い背景に適用されましたが、突然Googleマテリアルライブラリのチップウィジェットがクラッシュしました。理由は何ですか...
Renetik

パリのライブラリはその下でContextThemeWrapperを使用していませんか?
IgorGanapolsky

@IgorGanapolskyそれはしません。XMLスタイルを読み取り、ビューの対応するメソッド呼び出しに変換します。
ナタナエル

実際にはかなり制限されています。必要な多くのプロパティがサポートされていないため、使用を中止しました...
Renetik

-1

複合ViewGroupでXMLで定義されたビューを使用し、それらをViewgroupに追加してインフレートしました。この方法では、スタイルを動的に変更することはできませんが、スタイルをカスタマイズすることができます。私のコンポジット:

public class CalendarView extends LinearLayout {

private GridView mCalendarGrid;
private LinearLayout mActiveCalendars;

private CalendarAdapter calendarAdapter;

public CalendarView(Context context) {
    super(context);

}

public CalendarView(Context context, AttributeSet attrs) {
    super(context, attrs);

}

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    init();
}

private void init() {
    mCalendarGrid = (GridView) findViewById(R.id.calendarContents);
    mCalendarGrid.setNumColumns(CalendarAdapter.NUM_COLS);

    calendarAdapter = new CalendarAdapter(getContext());
    mCalendarGrid.setAdapter(calendarAdapter);
    mActiveCalendars = (LinearLayout) findViewById(R.id.calendarFooter);
}

}

スタイルを割り当てることができるxmlの私のビュー:

<com.mfitbs.android.calendar.CalendarView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/calendar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical"
>

<GridView
    android:id="@+id/calendarContents"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

<LinearLayout
    android:id="@+id/calendarFooter"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    />


1
スタイルをどこで動的に設定していますか?
IgorGanapolsky

-3

あなたは所望のスタイルとレイアウトを含むXMLを作成し、同様に、ビューの背景リソースを変更することができ、この


あなたはAndroidのような「スタイル」ではなく、ボタンの「アスペクト」について語っています。これは非常に異なります。
キリスト
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.