以编程方式膨胀的Button不接受XML样式

时间:2016-07-10 03:08:47

标签: android android-button android-theme android-styles

我正在尝试在整个应用程序中应用自定义Button背景,但只有在我以编程方式执行时才会起作用。

这是 styles.xml 。我使用<item name="android:buttonStyle">@style/OverlayButton</item>来表示自定义样式“OverlayButton”(顺便说一下,<item name="buttonStyle">@style/OverlayButton</item>给出“找不到与给定名称匹配的资源:attr'buttonStyle'。”)然后<item name="android:background">@drawable/overlay_button</item>调用自定义Drawable

<resources xmlns:android="http://schemas.android.com/apk/res/android">

    <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>

    <!-- Application theme -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
        <!-- http://stackoverflow.com/questions/6159113/android-where-is-the-spinner-widgets-text-color-attribute-hiding -->
        <item name="android:spinnerItemStyle">@style/SpinnerItem</item>
        <item name="android:spinnerDropDownItemStyle">@style/SpinnerItem.DropDownItem</item>
        <!-- http://stackoverflow.com/questions/8922924/how-to-change-android-spinner-popupbackground -->
        <!-- http://www.ezzylearning.com/tutorial.aspx?tid=1763429 -->
        <item name="android:listViewStyle">@style/myListView</item>
        <item name="android:buttonStyle">@style/OverlayButton</item>
    </style>

    <style name="SpinnerItem" parent="@android:style/Widget.TextView.SpinnerItem">
        <item name="android:textColor">#ADD8E6</item>
    </style>

    <style name="SpinnerItem.DropDownItem" parent="@android:style/Widget.DropDownItem.Spinner">
        <item name="android:textColor">#ADD8E6</item>
    </style>

    <style name="myListView" parent="@android:style/Widget.ListView">
        <item name="android:background">@drawable/intro_spinner</item>
    </style>

    <!-- Style for Overlay Buttons -->
    <style name="OverlayButton" parent="@android:style/Widget.Button">
        <item name="android:background">@drawable/overlay_button</item>
        <item name="android:gravity">center_vertical|center_horizontal</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textSize">12sp</item>
        <item name="android:textColor">#FF000000</item>
        <item name="android:layout_marginLeft">0dp</item>
        <item name="android:layout_marginRight">0dp</item>
        <item name="android:layout_marginTop">10dp</item>
        <item name="android:layout_marginBottom">10dp</item>
    </style>

    <!-- Style for Confirmation Dialog -->
    <style name="AlertDialogCustom" parent="@android:style/Theme.Dialog">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:background">@drawable/dialog_background</item>
        <item name="android:textColor">#FF000000</item>
        <item name="android:textSize">12sp</item>
        <item name="android:typeface">monospace</item>
    </style>

</resources>

自定义Drawable, overlay_button.xml 就在这里。

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

    <item android:state_pressed="true" >
        <shape>
            <gradient
                android:startColor="#999999"
                android:endColor="#c0c0c0"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="#202619" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="1dp"
                android:top="1dp"
                android:right="1dp"
                android:bottom="1dp" />
            <margin
                android:left="5dp"
                android:top="5dp"
                android:right="5dp"
                android:bottom="5dp" />
        </shape>
    </item>

    <item android:state_focused="true" >
        <shape>
            <gradient
                android:endColor="#999999"
                android:startColor="#c0c0c0"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="#202619" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="1dp"
                android:top="1dp"
                android:right="1dp"
                android:bottom="1dp" />
            <margin
                android:left="5dp"
                android:top="5dp"
                android:right="5dp"
                android:bottom="5dp" />
        </shape>
    </item>

    <item>        
        <shape>
            <gradient
                android:endColor="#aa393939"
                android:startColor="#aa737373"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="#202619" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="1dp"
                android:top="1dp"
                android:right="1dp"
                android:bottom="1dp" />
            <margin
                android:left="5dp"
                android:top="5dp"
                android:right="5dp"
                android:bottom="5dp" />
        </shape>
    </item>
</selector>

当我使用final Button b = new Button(context);创建一个按钮时,我没有获得自定义Drawable。然而,这有效:

final Button b = new Button(context);
Drawable buttonStates; // get Drawable to set button states
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    buttonStates = context.getResources().getDrawable(R.drawable.overlay_button, context.getTheme());
} else {
    buttonStates = context.getResources().getDrawable(R.drawable.overlay_button);
}
b.setBackground(buttonStates);

为什么这应该以编程方式工作,而不是在XML中工作?

更新:@ r-zagórski有一个很好的线索。 XML膨胀按钮采用自定义样式并按预期工作。无法工作的按钮以编程方式创建,并通过LinearLayout.addView(b)插入。 (顺便说一句,final Button b = new Button(context, null, R.drawable.overlay_button_selector)不起作用。)我不明白为什么这不像XML夸大的按钮那样工作。

1 个答案:

答案 0 :(得分:0)

不幸的是,这不是应该如何定义适当的有状态背景。 一种正确的方法是为每个状态定义一个drawable并使用&#34; selector&#34;来绑定它们。

在您的情况下,在res/drawable文件夹中定义3个文件:

overlay_button

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
   <item>
       <shape>
           <gradient
               android:endColor="#aa393939"
               android:startColor="#aa737373"
               android:angle="270" />
           <stroke
               android:width="3dp"
               android:color="#202619" />
           <corners
               android:radius="3dp" />
           <padding
               android:left="1dp"
               android:top="1dp"
               android:right="1dp"
               android:bottom="1dp" />
           <margin
               android:left="5dp"
               android:top="5dp"
               android:right="5dp"
               android:bottom="5dp" />
        </shape>
    </item>
</layer-list>

overlay_button_focused

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <gradient
                android:endColor="#999999"
                android:startColor="#c0c0c0"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="#202619" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="1dp"
                android:top="1dp"
                android:right="1dp"
                android:bottom="1dp" />
            <margin
                android:left="5dp"
                android:top="5dp"
                android:right="5dp"
                android:bottom="5dp" />
        </shape>
    </item>
</layer-list>

overlay_button_pressed

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item >
        <shape>
            <gradient
                android:startColor="#999999"
                android:endColor="#c0c0c0"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="#202619" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="1dp"
                android:top="1dp"
                android:right="1dp"
                android:bottom="1dp" />
            <margin
                android:left="5dp"
                android:top="5dp"
                android:right="5dp"
                android:bottom="5dp" />
        </shape>
    </item>
</layer-list>

选择器文件 overlay_selector

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

styles.xml

<style name="OverlayButton" parent="@android:style/Widget.Button">
    <item name="android:background">@drawable/overlay_selector</item>
    ....
</style>

如果此选择器不适合您的需要,请创建其他状态。在Android btn_default.xml文件夹中的Android res/drawable中查找参考。

进一步参考see this