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프로그래밍 방식으로 속성 을 설정하는 방법은 무엇입니까?


[ '답변'] [1]을 참조하십시오. 이것은 저에게 효과적이었습니다. [1] : stackoverflow.com/a/5488652/2938493
Artificioo

답변:


211

기술적으로 사용자 정의보기를 사용하여 프로그래밍 방식으로 스타일을 적용 할 수 있습니다.

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

하나의 인수 생성자는 프로그래밍 방식으로 뷰를 인스턴스화 할 때 사용되는 생성자입니다.

따라서이 생성자를 스타일 매개 변수를 사용하는 수퍼에 연결하십시오.

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

또는 @Dori가 간단히 지적한 것처럼 :

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

34
3 arg 생성자가 public이므로 확장하지 않고도 프로그래밍 방식 으로이 작업을 수행 할 수 있습니다. developer.android.com/reference/android/widget/… , android.util.AttributeSet, int)
Dori

1
@Turbo, 문서와 이클립스 모두 다음과 같이 알려줍니다 http://developer.android.com/reference/android/widget/LinearLayout.html#LinearLayout(android.content.Context, android.util.AttributeSet, int).. LinearLayout 레벨 11 이상이 필요합니다.
TheOne

2
@Dori 무엇을 전달 AttributeSet하시겠습니까?
Blundell

9
TextView 인 경우 텍스트 (크기, 색상 등)에 영향을주는 속성에 대해 setTextAppearance (R.style.small_text)를 사용해야합니다.
Maragues

2
왜 3 차 인수 접근법이 효과가 없는지 모르겠습니다. 에 신청했습니다 Button. @ Benjamin Piette 접근법은 잘 작동합니다.
영재 September

124

나를 위해 일한 것 :

Button b = new Button(new ContextThemeWrapper(this, R.style.ButtonText), null, 0);
  • ContextThemeWrapper 사용

  • 3- 인수 생성자를 사용하십시오 (이것이 없으면 작동하지 않습니다)

귀하의 방법을 사용하는 것은 효과가 있지만 W / ResourceType ﹕ 너무 많은 속성 참조가 0x01010034에서 중지되었습니다. 해결 방법이 있습니까?
HaloMediaz

나는 그 문제를 본 적이 없다. 기기 관련 문제이거나 최신 Android 버전과 관련이 있습니까?
Benjamin Piette

11
중대한! 이 방법 작동하지만 ContextThemeWrapper를 사용하여 새 레이아웃을 만드는 경우 모든 자식 뷰 의 스타일을 설정 합니다.
aProperFox

@aProperFox 더 잘 설명 할 수 있습니까? 나와 함께 버튼에 추가하여 작동합니다. 레이아웃을 참조하십니까?
Gilian

1
@Gilian 정확하게, 하나 이상의 자식이있는 복합보기에서 이것을 사용하면 스타일을 설정 한 부모보기와 동일한 스타일이 적용됩니다. 이렇게하면 내부보기에서 패딩이나 여백이 너무 커져이를
모르면

88

업데이트 :이 질문에 대한 답변 (2012 년 중반, API 레벨 14-15)에서 프로그래밍 방식으로 뷰를 설정하는 것은 옵션이 아니었지만 (몇 가지 사소한 해결 방법이 있었음에도 불구하고) 더 최근의 API 후에 가능했습니다. 릴리스. 자세한 내용은 @Blundell의 답변을 참조하십시오.

이전 답변 :

프로그래밍 방식으로 뷰의 스타일을 설정할 수 는 없지만 이 스레드가 유용 할 수 있습니다 .


16
사실이 아니다. @Blundell의 답변을 참조하십시오.
a.bertucci

31
경우에 따라 (예 : TextView 사용)을 사용할 수 있습니다 textView.setTextAppearance(context, R.style.mystyle);. 문서에 따르면 "지정된 TextAppearance 리소스에서 텍스트 색상, 크기, 스타일, 힌트 색상 및 강조 색상을 설정합니다." developer.android.com/reference/android/widget/… , int)
Rogel Garcia

4
api> 23; textView.setTextAppearance (R.style.mystyle);
alican 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을 계속 사용하고 (허용 된 답변으로는 허용하지 않음)보기가 작성된 후 스타일을 설정하려면 사용 가능한 모든 속성의 서브 세트를 지원하는 파리 라이브러리를 사용할 수 있습니다.

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

이 솔루션을 제공해 주신 @Nathanael에게 감사합니다. 또한 최신 line_height 속성을 가진 유지 관리자이기도합니다. 좋은 일을 계속하십시오! 정말 유용합니다.
ille 로카

7

다음을 수행하여 활동에 스타일을 적용 할 수 있습니다.

super.setTheme( R.style.MyAppTheme );

또는 Android 기본값 :

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

귀하의 활동에서 setContentView().


4
@siemian FOM이 자유롭게 자신을 표현하게 할 수 있습니까? 그는 편집 할 필요가 없습니다!
Mika

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>

스타일 지정에 내 이름을 사용할 수 있습니다 (내 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
- 이것은 당신이 단지 2 개의 고정 뷰를 여기 (당신의 조회수에 저장된 설정 (예 그것은 당신의 XML 파일에 저장된 설정 실제로 어떤 종류의) 설정 / 적용하여 단지 가짜, 진정한 스타일하지 않습니다 당신은 분명히을 알 필요가 미리). 모든 마술은 apply흥미 있는 방법이 아닙니다. 스타일의 진정한 의미 는 향후 동적으로 추가 된 모든 뷰에 시각적 스타일을 자동으로 적용한다는 것입니다. 이 코드는 물론 그렇게 할 수 없으며 여기에는 역동적 인 것이 없으므로 어떤 뷰와 어떤 속성 / 필드를 설정 해야하는지 알아야 합니다 .
King King

1
스타일을 적용 할 뷰를 지정하는 것은 중요하지 않지만이 솔루션에는 스타일 요소 (예 : textColor 및 dividerColor)가 하드 코딩되어 있습니다. 스타일에 정의 된 모든 요소를 ​​동적으로 찾아서보기에 적용하지는 않습니다.
nasch

게시 한 링크가 열리지 않습니다. 다시 게시 해 주시겠습니까?
IgorGanapolsky

4

이것은 꽤 오래된 질문이지만 지금 나를 위해 일한 솔루션은 생성자의 4 번째 매개 변수를 사용 defStyleRes하는 것입니다.

내 목적을 위해 다음과 같은 작품 (kotlin) :

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

3

이것은 간단한 예입니다. 키가 ContextThemeWrapper없으면 래퍼입니다. 스타일이 작동하지 않으며 View의 세 가지 매개 변수 생성자를 사용합니다.

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를 사용할 것을 제안하지 않습니다.

지정된 테마는 기본 컨텍스트 테마 위에 적용됩니다.

애플리케이션에서 원하지 않는 결과를 초래할 수있는 것 대신 에어 비앤비의 엔지니어들에게이를위한 새로운 라이브러리 "파리"를 제안합니다.

https://github.com/airbnb/paris

프로그래밍 방식으로 Android보기에 스타일을 정의하고 적용하십시오.

그러나 그것을 사용 한 시간이 지나면 실제로 상당히 제한적이라는 것을 알았습니다. 많은 속성을 지원하지 않기 때문에 사용을 중단했습니다. 따라서 상자 밖으로 나가야하므로 항상 체크 아웃하고 결정해야합니다.


당신의 downvote 친구를 설명하십시오 ... 나는 ContextThemeWrapper를 사용했기 때문에 하루 반을 잃어 버렸고 컨텍스트 테마 흰색 배경에 적용 한 다음 갑자기 Google 자료 라이브러리의 칩 위젯이 충돌했습니다. 왜 그런지 추측하십시오 ...
Renetik

파리 도서관은 ContextThemeWrapper를 사용하지 않습니까?
IgorGanapolsky

@IgorGanapolsky는 그렇지 않습니다. XML 스타일을 읽고이를 뷰의 해당 메소드 호출로 변환합니다.
Nathanael

그것은 내가 필요한 많은 속성을 지원하지 않기 때문에 사용을 중지 실제로 실제로 상당히 제한되어 있습니다 ...
Renetik

-1

복합 ViewGroup에서 XML로 정의 된 뷰를 사용하여 뷰 그룹에 추가하여 부풀 렸습니다. 이 방법으로 스타일을 동적으로 변경할 수는 없지만 스타일을 사용자 지정할 수 있습니다. 내 합성 :

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을 생성 한 다음과 같은보기의 배경 자원을 변경할 수 있습니다 .


당신은 안드로이드 에서처럼 "스타일"에 대해 이야기하지만 버튼의 "종료"에 대해 이야기하고 있습니다. 이것은 매우 다릅니다.
그리스도
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.