How to programmatically set style attribute in a view

前端 未结 11 2029
北恋
北恋 2020-11-22 06:38

I\'m getting a view from the XML with the code below:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
相关标签:
11条回答
  • 2020-11-22 06:55

    For anyone looking for a Material answer see this SO post: Coloring Buttons in Android with Material Design and AppCompat

    I used a combination of this answer to set the default text color of the button to white for my button: https://stackoverflow.com/a/32238489/3075340

    Then this answer https://stackoverflow.com/a/34355919/3075340 to programmatically set the background color. The code for that is:

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

    your_colored_button can be just a regular Button or a AppCompat button if you wish - I tested the above code with both types of buttons and it works.

    EDIT: I found that pre-lollipop devices do not work with the above code. See this post on how to add support for pre-lollipop devices: https://stackoverflow.com/a/30277424/3075340

    Basically do this:

    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);
    }
    
    0 讨论(0)
  • 2020-11-22 07:00

    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.

    0 讨论(0)
  • 2020-11-22 07:00

    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 !

    0 讨论(0)
  • 2020-11-22 07:01

    The answer by @Dayerman and @h_rules is right. To give an elaborated example with code, In drawable folder, create an xml file called button_disabled.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>
    

    Then in Java,

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

    This will set the button's property to disabled and sets the color to silver.

    [The color is defined in color.xml as:

    <resources>
    
        <color name="silver">#C0C0C0</color>
    
    </resources>
    
    0 讨论(0)
  • 2020-11-22 07:05

    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.

    • List of currently supported attributes
    • Installation instructions

    Disclaimer: I authored the library.

    0 讨论(0)
提交回复
热议问题