问题
I am trying to use setEnabled(false)
on a Button
to show grey disabled state...
I can only get the desired result if I force a theme on the button with
android:theme="@style/Button"
and then change the parent on that Button style to something other than the
Theme.AppCompat.Light.DarkActionBar
, such as from Material:<style name="Button" parent="android:Theme.Material.Light.NoActionBar">
(even then, only the button background changes, the text color doesn't.)
I can't see the Button as grey when set disabled if I leave the Button to take the defaults. (My understanding is that when using
Theme.AppCompat.
,Button
becomesAppCompat.Widget.Button
and inherits aColorStateList
.)
In my res\values\styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!-- only way I could get this to work -->
<style name="Button" parent="android:Theme.Material.Light.NoActionBar">
<!--<item name="colorAccent">@color/butt</item>-->
<!--<item name="colorButtonNormal">@color/butt</item>-->
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>
In AndroidManifest.xml
<application
android:theme="@style/AppTheme"
( and nothing under <activity> )
My MainActivity
extends Activity
- but I have also tried extends
AppCompatActivity
and had the same problem.
So what is going on here? Why doesn't the default work for a "disabled button"?
- (And if I do inherit from
Material
theme (as above), why does the Button text color not change? Basically, why don't the Buttons look like they do in the theme editor?)
Also
when I specify a custom
ColorStateList
viares\color
, why can't I override just some of the states? I tried to have only<item android:state_enabled="false" android:color="#616161" />
But it didn't work. I was only able to get a greyed disable Button using this method if I specified more
<item>
s, even though I don't care to match other states. It only works If I add something like:<!-- disabled state --> <item android:state_enabled="false" android:color="#616161" /> <!-- enabled state --> <item android:state_enabled="true" android:color="@color/colorPrimaryLighter" /> <!-- default --> <item android:color="#ffffff"/>
My supportLibraryVersion = '27.1.1'
I have already seen
How to setup disabled color of button with AppCompat?
Widget.AppCompat.Button colorButtonNormal shows gray
State list drawable and disabled state
Android - default button style
Android: change color of disabled text using Theme/Style?
When should one use Theme.AppCompat vs ThemeOverlay.AppCompat?
Use android:theme and ThemeOverlay to theme specific Views and their descendents Pro-tip by +Ian Lake
and Nesting Android Themes
I don't want to override the defaults if I don't have to and specify anything I don't have to. Thanks in advance!
回答1:
Let me go into more detail to hopefully help clear up some of your questions:
Activating default material buttons:
Side note: Overall I think it leads to a more consistent look and behaviour when using the AppCompat Theme to also use AppCompatActivity
etc.
But as you noticed just by using the AppCompat
Theme, a Button
(Internally mapped to android.support.v7.widget.AppCompatButton
) doesn't automatically apply the compatibility material style.
I'm not sure if this is a bug, but I suspect it's to keep the look backwards compatible. You can easily activate it by applying the correct style directly on the view:
<Button
style="@style/Widget.AppCompat.Button.Colored"
... />
Here is a screenshot to show the different look of enabled and disabled buttons. The styled buttons are the first two. The active one has the pink accent color as background. The old Android button are the bottom two. As you can see disable only changes the text color and slightly the outline.
If you want this applied to any button you use in your app, you can add the following line to your AppTheme
:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="buttonStyle">@style/Widget.AppCompat.Button.Colored</item>
...
This will use your default colorAccent as button highlight color and a grey tone as a flat disabled button. You mentioned only defining the android:theme
for your App
in your Manifest. For this solution to work you might need to set the theme to each Activity
.
Defining a color with different states
The idea of the ColorStateList
is to define a color that changes depending on the state of a View
. It needs the default case as a fallback in case the conditions of the specific definitions don't match.
Your example can be simplified to the following:
<!-- disabled state -->
<item android:state_enabled="false" android:color="#616161" />
<!-- default = enabled state -->
<item android:color="@color/colorPrimaryLighter"/>
For buttons you can also make use of the default disabled alpha attribute e.g. define button_accent_stated
=
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false"
android:alpha="?android:attr/disabledAlpha"
android:color="@color/colorAccent"/>
<item android:color="@color/colorAccent" />
</selector>
Custom color styling
If you are happy with the defaults, then you can ignore the following part...
If you want to style a button (and same for other components) and give it custom colors you need to make the difference between applying styles and themes. Both are defined in the styles.xml
so this can be confusing. I can recommend giving the definitions names that represent how they are used.
When you want to overwrite for example the accent color, you create a custom ButtonTheme
and apply it with android:theme
as shown in your question.
When you want to adjust the look of a component (e.g. with the material buttons to get a different disabled color), you create a custom ButtonStyle
and apply it with style
. These definitions need a parent
that corresponds to the View
.
With material buttons and latest support libraries the previous approach to set the disabled color with colorButtonNormal
seems to not work anymore. Instead you can use the color defined in the previous step by creating a custom style and set it as backgroundTint
.
<style name="AppTheme.ButtonStyle" parent="@style/Widget.AppCompat.Button.Colored">
<item name="colorAccent">@color/colorAccent</item>
<item name="android:backgroundTint">@color/button_accent_stated</item>
</style>
This will lead to a disabled button like this:
Again you can apply this style as above per button or overall in your AppTheme
. If you still need to support pre-lollipop devices you probably will also need a custom theme to set the colorButtonNormal
.
Update: Default Material + stated text color:
Played with my example app and the only other explanation I found to what prevents the default stated text color is defining android:textColorPrimary
on your AppTheme
!
<item name="android:textColorPrimary">@color/colorPrimaryTextOnLight</item>
If you have this all buttons without a custom text color will use this text for both states! See Screenshot.
If you just want to fix the button text to change color, you can define your button style like this:
<style name="AppTheme.TextStatedButtonStyle" parent="@style/Widget.AppCompat.Button.Colored">
<item name="android:textColor">@color/button_text_stated</item>
</style>
With button_text_stated
a selector like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false"
android:alpha="?android:disabledAlpha"
android:color="@color/colorPrimaryTextOnLight" />
<item android:color="@color/colorPrimaryTextOnDark" />
</selector>
And simply apply this buttonStyle
for all buttons or as style
per button as shown above.
I've uploaded my demo project with more screenshots / combinations of setting styles and themes to Github since I felt this answer was getting too long and it's better to just play with it to understand how styles work.
Preview in Android studio
As mentioned in the comments I can confirm that the Preview in Android studio is sometimes showing elements wrong, especially when applying a custom theme to an element! Better to test in the emulator or on a real device.
来源:https://stackoverflow.com/questions/53071828/why-doesnt-setenabledfalse-trigger-a-colorstatelist-for-theme-theme-appcompat