developer tip

뷰에서 프로그래밍 방식으로 스타일 속성을 설정하는 방법

optionbox 2020. 8. 27. 07:42
반응형

뷰에서 프로그래밍 방식으로 스타일 속성을 설정하는 방법


아래 코드를 사용하여 XML에서보기를 얻습니다.

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);

내가 사용할 각 버튼에 여러 스타일을 사용하기를 원하기 때문에 자바에서 어떻게 할 수있는 버튼에 대한 "스타일"을 설정하고 싶습니다.


일반적으로 프로그래밍 방식으로 스타일을 변경할 수 없습니다. 테마 또는 스타일을 사용하여 XML 레이아웃의 화면 또는 레이아웃의 일부 또는 개별 버튼의 모양을 설정할 수 있습니다 . 그러나 테마는 프로그래밍 방식으로 적용 할 수 있습니다 .

또한 포커스, 선택, 눌림, 비활성화 등의 StateListDrawable각 상태에 대해 다른 드로어 블을 정의 할 수 있는 것과 같은 것이 Button있습니다.

예를 들어 버튼을 눌렀을 때 색상이 변경되도록하려면 다음 res/drawable/my_button.xml과 같이 directory 라는 XML 파일을 정의 할 수 있습니다 .

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item
    android:state_pressed="true"
    android:drawable="@drawable/btn_pressed" />
  <item
    android:state_pressed="false"
    android:drawable="@drawable/btn_normal" />
</selector>

그런 다음 Button속성을 설정 하여이 선택기를에 적용 할 수 있습니다 android:background="@drawable/my_button".


우선, 간단한 Button을 만들기 위해 레이아웃 인플레이터를 사용할 필요가 없습니다. 다음을 사용할 수 있습니다.

button = new Button(context);

버튼의 스타일을 지정하려면 두 가지 선택이 있습니다. 가장 간단한 방법은 다른 많은 답변이 제안하는 것처럼 코드의 모든 요소를 ​​지정하는 것입니다.

button.setTextColor(Color.RED);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);

다른 옵션은 XML로 스타일을 정의하고 단추에 적용하는 것입니다. 일반적인 경우에는 다음과 같이 사용할 수 있습니다 ContextThemeWrapper.

ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle);
button = new Button(newContext);

TextView (또는 Button과 같은 하위 클래스)의 텍스트 관련 속성을 변경하려면 다음과 같은 특별한 방법이 있습니다.

button.setTextAppearance(context, R.style.MyTextStyle);

이 마지막 속성은 모든 속성을 변경하는 데 사용할 수 없습니다. 예를 들어 패딩을 변경하려면 ContextThemeWrapper. 그러나 텍스트 색상, 크기 등의 경우 setTextAppearance.


예, 예를 들어 버튼에 사용할 수 있습니다.

Button b = new Button(this);
b.setBackgroundResource(R.drawable.selector_test);

다음과 같이 스타일 속성을 수행 할 수 있습니다.

Button myButton = new Button(this, null,android.R.attr.buttonBarButtonStyle);

대신에:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/btn"
    style="?android:attr/buttonBarButtonStyle"

    />

지원 라이브러리를 사용하는 경우 간단히 사용할 수 있습니다.

TextViewCompat.setTextAppearance(textView, R.style.AppTheme_TextStyle_ButtonDefault_Whatever);

TextViews 및 Buttons. 나머지 뷰에도 비슷한 클래스가 있습니다. :-)


Material 답변을 찾고있는 사람은이 SO 게시물을 참조하십시오 : Material Design 및 AppCompat을 사용하는 Android의 Coloring Buttons

이 답변의 조합을 사용하여 버튼의 기본 텍스트 색상을 흰색으로 설정했습니다. https://stackoverflow.com/a/32238489/3075340

그런 다음이 답변 https://stackoverflow.com/a/34355919/3075340 프로그래밍 방식으로 배경색을 설정합니다. 그 코드는 다음과 같습니다.

ViewCompat.setBackgroundTintList(your_colored_button,
 ContextCompat.getColorStateList(getContext(),R.color.your_custom_color));

your_colored_buttonButton원하는 경우 일반 또는 AppCompat 버튼 일 수 있습니다. 위의 코드를 두 가지 유형의 버튼으로 테스트했으며 작동합니다.

편집 : 사전 롤리팝 장치가 위의 코드에서 작동하지 않음을 발견했습니다. 사전 롤리팝 장치에 대한 지원을 추가하는 방법에 대한이 게시물을 참조하십시오. https://stackoverflow.com/a/30277424/3075340

기본적으로 다음을 수행하십시오.

Button b = (Button) findViewById(R.id.button);
ColorStateList c = ContextCompat.getColorStateList(mContext, R.color.your_custom_color;
Drawable d = b.getBackground();
if (b instanceof AppCompatButton) {
    // appcompat button replaces tint of its drawable background
    ((AppCompatButton)b).setSupportBackgroundTintList(c);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Lollipop button replaces tint of its drawable background
    // however it is not equal to d.setTintList(c)
    b.setBackgroundTintList(c);
} else {
    // this should only happen if 
    // * manually creating a Button instead of AppCompatButton
    // * LayoutInflater did not translate a Button to AppCompatButton
    d = DrawableCompat.wrap(d);
    DrawableCompat.setTintList(d, c);
    b.setBackgroundDrawable(d);
}

@Dayerman과 @h_rules의 대답이 맞습니다. 코드로 정교한 예제를 제공하려면 드로어 블 폴더에 button_disabled.xml이라는 xml 파일을 만듭니다.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">   
 <solid android:color="@color/silver"/>
<corners
   android:bottomRightRadius="20dp"
   android:bottomLeftRadius="20dp"
   android:topLeftRadius="20dp"
   android:topRightRadius="20dp"/>
</shape>

그런 다음 Java에서

((Button) findViewById(R.id.my_button)).setEnabled(false);
((Button) findViewById(R.id.my_button)).setBackgroundResource(R.drawable.button_disabled);

그러면 버튼의 속성이 비활성화되고 색상이 은색으로 설정됩니다.

[색상은 color.xml에서 다음과 같이 정의됩니다.

<resources>

    <color name="silver">#C0C0C0</color>

</resources>

At runtime, you know what style you want your button to have. So beforehand, in xml in the layout folder, you can have all ready to go buttons with the styles you need. So in the layout folder, you might have a file named: button_style_1.xml. The contents of that file might look like:

<?xml version="1.0" encoding="utf-8"?>
<Button
    android:id="@+id/styleOneButton"
    style="@style/FirstStyle" />

If you are working with fragments, then in onCreateView you inflate that button, like:

Button firstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);

where container is the ViewGroup container associated with the onCreateView method you override when creating your fragment.

Need two more such buttons? You create them like this:

Button secondFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
Button thirdFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);

You can customize those buttons:

secondFirstStyleBtn.setText("My Second");
thirdFirstStyleBtn.setText("My Third");

Then you add your customized, stylized buttons to the layout container you also inflated in the onCreateView method:

_stylizedButtonsContainer = (LinearLayout) rootView.findViewById(R.id.stylizedButtonsContainer);

_stylizedButtonsContainer.addView(firstStyleBtn);
_stylizedButtonsContainer.addView(secondFirstStyleBtn);
_stylizedButtonsContainer.addView(thirdFirstStyleBtn);

And that's how you can dynamically work with stylized buttons.


Depending on what style attributes you'd like to change you may be able to use the Paris library:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
Paris.style(view).apply(R.style.YourStyle);

Many attributes like background, padding, textSize, textColor, etc. are supported.

Disclaimer: I authored the library.


I made a helper interface for this using the holder pattern.

public interface StyleHolder<V extends View> {
    void applyStyle(V view);
}

Now for every style you want to use pragmatically just implement the interface, for example:

public class ButtonStyleHolder implements StyleHolder<Button> {

    private final Drawable background;
    private final ColorStateList textColor;
    private final int textSize;

    public ButtonStyleHolder(Context context) {
        TypedArray ta = context.obtainStyledAttributes(R.style.button, R.styleable.ButtonStyleHolder);

        Resources resources = context.getResources();

        background = ta.getDrawable(ta.getIndex(R.styleable.ButtonStyleHolder_android_background));

        textColor = ta.getColorStateList(ta.getIndex(R.styleable.ButtonStyleHolder_android_textColor));

        textSize = ta.getDimensionPixelSize(
                ta.getIndex(R.styleable.ButtonStyleHolder_android_textSize),
                resources.getDimensionPixelSize(R.dimen.standard_text_size)
        );

        // Don't forget to recycle!
        ta.recycle();
    }

    @Override
    public void applyStyle(Button btn) {
        btn.setBackground(background);
        btn.setTextColor(textColor);
        btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    }
}

Declare a stylable in your attrs.xml, the styleable for this example is:

<declare-styleable name="ButtonStyleHolder">
    <attr name="android:background" />
    <attr name="android:textSize" />
    <attr name="android:textColor" />
</declare-styleable>

Here is the style declared in styles.xml:

<style name="button">
    <item name="android:background">@drawable/button</item>
    <item name="android:textColor">@color/light_text_color</item>
    <item name="android:textSize">@dimen/standard_text_size</item>
</style>

And finally the implementation of the style holder:

Button btn = new Button(context);    
StyleHolder<Button> styleHolder = new ButtonStyleHolder(context);
styleHolder.applyStyle(btn);

I found this very helpful as it can be easily reused and keeps the code clean and verbose, i would recommend using this only as a local variable so we can allow the garbage collector to do its job once we're done with setting all the styles.


I faced the same problem recently. here is how i solved it.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <!-- This is the special two colors background START , after this LinearLayout, you can add all view that have it for main background-->
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:weightSum="2"

    android:background="#FFFFFF"
    android:orientation="horizontal"
    >

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#0000FF" />

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#F000F0" />
    </LinearLayout>
    <!-- This is the special two colors background END-->

   <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:text="This Text is centered with a special backgound,
    You can add as much elements as you want as child of this RelativeLayout"
    android:textColor="#FFFFFF"
    android:textSize="20sp" />
</RelativeLayout>
  • I used a LinearLayout with android:weightSum="2"
  • I gave to the two child elements android:layout_weight="1" (I gave each 50% of the parent space(width & height))
  • And finally, i gave the two child element different background colors to have the final effect.

Thanks !

참고URL : https://stackoverflow.com/questions/2016249/how-to-programmatically-set-style-attribute-in-a-view

반응형