How can I override the default value of the background color for a button in a v21/v22 style.xml?
I made an application that is compatible from Honeycomb to Lollipop and I'd like to make a better style for Lollipop but I can't find how to override the default background color of buttons (for API before 21) to transparent (on API>21 I use <item name="android:colorButtonNormal">color</item> and <item name="android:colorControlHighlight">color</item>)
You can create drawable like this in v21
?xml version="1.0" encoding="utf-8"?>
<!--drawable-v21/btn_fab_default.xml-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/fab_color_shadow">
<item>
<shape android:shape="oval">
<solid android:color="#color/style_color_accent" />
</shape>
</item>
</ripple>
for more information visit this link
Ok, it worked partially and I try to explain:
now I have a buttons.xml file in the main drawable folder and a buttons.xml file in the drawable-v21 folder, everything works well.
The main layout.xml contains:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
android:background="#drawable/buttons" />
Now my goal is set a sort of "background: none" only for v21 and more.
Why?
Because if I set a background for v21 buttons I can't use the style effect
<item name="android:colorButtonNormal">color</item> and <item name="android:colorControlHighlight">color</item>that I setted in the values-v21\style.xml
If I set up the transparent color for my v21 buttons the BackgroundTint property doesn't have effect on a Lollipop phone.
I don't want to make a layout only for lollipop devices, I'd like to find a better way to manage this problem.
Related
I find out that since Android Studio 4.1 I cannot change the background color of a Button by setting color on its android:background, just no effect. And custom Drawable is not working as well.
My background Drawable:
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1.5dp"
android:color="#android:color/black" />
<solid
android:color="#android:color/white" />
<corners
android:radius="8dp" />
</shape>
My Button:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add To Cart"
android:background="#drawable/background3"/>
Result:
The Android Studio 4.1 new-project wizard, for many of its templates, has the project use the Material Components for Android library. And, it sets up the default theme to be based on Theme.MaterialComponents.DayNight.DarkActionBar.
A side effect of this is that any <Button> elements in a layout get turned into MaterialButton widgets, not regular Button widgets. MaterialButton ignores android:background.
If all you want to do is to change the color, use android:backgroundTint or change the colorPrimary attribute in the theme.
If you want a button that has a custom background, and your theme is set up to use Theme.MaterialComponents, you could switch the XML element in the layout to be <android.widget.Button> instead of <Button>. This should cause the Material Components for Android to ignore that element, and you can manipulate this button normally with respect to XML attributes.
UPDATE 03/2021
app:backgroundTint="#null" //just need this
android:background="#drawable/background_button"
Ok, since MaterialButton is the default Button starting from Android Studio 4.1, we can modify the shape by using app:shapeAppearanceOverlay attribute.
1. Create a Custom Style in themes.xml:
<style name="leaf">
<item name="cornerSizeTopLeft">70%</item> //can specify corner position
<!--<item name="cornerFamilyTopLeft">cut</item>-->
<item name="cornerSizeBottomRight">70%</item>
<!--<item name="cornerFamilyBottomRight">cut</item>-->
</style>
2. Apply Style in Material Button:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Show"
app:shapeAppearanceOverlay="#style/leaf" /> //here
Result:
Helpful video:
https://www.youtube.com/watch?v=jihLJ0oVmGo
Add only this:
app:backgroundTint="#null"
I found easiest solution in this video.
https://www.youtube.com/watch?v=E_1H52FEqII
Just go to themes.xml under values folder in project window and change the MaterialComponents to AppCompact in both themes and button start working as normal as it was in past.
Existing: Theme.MaterialComponents.DayNight.DarkActionBar
After Modification: Theme.AppCompat.DayNight.DarkActionBar
It worked for me, hope it works for others as weell.
Just set null to backgroundTint.
android:backgroundTint="#null".
Short question:
Suppose I use this style on a button:
<Button
style="#style/Widget.AppCompat.Button.Borderless.Colored" ...
(or without the "Colored" part).
How do I set the background of it to be a selector that has a different color when being pressed? The default one is quite a bold color on pre-Lollipop...
I want to have all of the style working as the default (including padding), except for the color of the selector.
I think the easiest would be to create a typical multi-state drawable and replicate Android's default button drawable properties for padding, etc...
From the Android SDK AppCompat theme:
<!-- Colored bordered ink button -->
<style name="Base.Widget.AppCompat.Button.Colored">
<item name="android:background">#drawable/abc_btn_colored_material</item>
<item name="android:textAppearance">#style/TextAppearance.AppCompat.Widget.Button.Inverse</item>
</style>
They use the drawable abc_btn_colored_material, whose source is like this: https://github.com/dandar3/android-support-v7-appcompat/blob/master/res/drawable/abc_btn_borderless_material.xml
You can see it's just a layer list with the following multi-state drawable:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:drawable="#drawable/abc_btn_default_mtrl_shape"/>
<item android:state_pressed="true" android:drawable="#drawable/abc_btn_default_mtrl_shape"/>
<item android:drawable="#android:color/transparent"/>
</selector>
https://github.com/dandar3/android-support-v7-appcompat/blob/master/res/drawable/abc_btn_default_mtrl_shape.xml
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="#dimen/abc_button_inset_horizontal_material"
android:insetTop="#dimen/abc_button_inset_vertical_material"
android:insetRight="#dimen/abc_button_inset_horizontal_material"
android:insetBottom="#dimen/abc_button_inset_vertical_material">
<shape android:shape="rectangle">
<corners android:radius="#dimen/abc_control_corner_material" />
<solid android:color="#android:color/white" />
<padding android:left="#dimen/abc_button_padding_horizontal_material"
android:top="#dimen/abc_button_padding_vertical_material"
android:right="#dimen/abc_button_padding_horizontal_material"
android:bottom="#dimen/abc_button_padding_vertical_material" />
</shape>
</inset>
So just make it yours :) Copy the drawable xml into your app and customize it.
I don't know if you will be able to access the #dimen/... from outside the SDK package, those values are defined in the SDK Values.xml, take a look at https://github.com/dandar3/android-support-v7-appcompat/blob/master/res/values/values.xml . If it's not possible, just create your own version of the dimens in your values.xml
If there's a cleaner solution any android guru can point out, I'll be glad to know!
Requested Update
Another trick is to apply a ColorFilter to the whole Button View. It's a very simple thing but not useful for all situations, as the color filter will blindly change the view as a whole (including Font color, borders, etc...). However, smartly selecting Alpha on the colors, could work for specific situations.
I'd suggest a LightningColorFilter. To apply a color filter to the Button, or to any view, you can do something like
myButton.getBackground().setColorFilter(new LightingColorFilter(Color.WHITE, Color.RED));
Check out what every color means here: http://developer.android.com/reference/android/graphics/LightingColorFilter.html
I'm having a very similar problem as to what was described in this question, but the answer is hacky and not really a proper answer, although it works.
Android Studio 1.4: drawable-v21 ignored when using "File/New/Vector Asset" option
I have a button, that I want to apply a pressed color to on pre21 devices, and use the ripple on v21+ devices.
In the drawable folder I have button_primary_theme
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="#color/themePimaryrOnePressed" />
</shape>
</item>
<item>
<shape>
<solid android:color="#color/themePrimaryOne" />
</shape>
</item>
</selector>
In the drawable-v21 folder I have
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:drawable="?attr/colorPrimary"/>
</ripple>
No matter what I do, I can't get my layout to use the ripple effect from the v21 folder on my Lollipop device. It keeps using the pre lollipop drawable.
<Button
android:id="#+id/getting_started"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button_primary_theme" />
In the other answer, he made a separately named file for v21 effect, but that means I need a new copy of the layout in addition to the new drawable, and that shouldn't be necessary to get this to work.
I've tried cleaning the project, but it still uses the non v21 drawable.
How do I get this to work without making copies of everything?
Looks like this was my fault. Hopefully this might help someone else.
My normal drawable was actually in the drawable-nodpi folder, not drawable. I guess that was somehow overriding the v21 folder version.
I want to use ripple effects on Buttons. AppCompat v22.1 added AppCompatButton and new functionalities to AppCompat tinting.
My Layout:
<android.support.v7.widget.AppCompatButton
android:id="#+id/add_remove_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:backgroundTint="#color/primary"
android:textColor="#android:color/white"
android:text="Remove" />
On my API 22 test device the ripple effect works perfectly, but i'm coding for API 11 and unfortunately backgroundTint needs API >= 21. How can i set the ripple effect to Buttons on older API versions?
Just use app:backgroundTint instead of android:backgroundTint, the tint will take effect below Lollipop. The reason is AppCompatActivity AppCompatDelegateImplV7 use AppCompatViewInflater to auto change Button or TextView to AppCompatButton or AppCompatTextView, then app:backgroundTint take effect.
Ripples are not available as a build in functionality on Android <21. This is due to performance issues: devices with the new API can use the RenderThread which is not available to older devices.
See also: http://android-developers.blogspot.de/2014/10/appcompat-v21-material-design-for-pre.html
Why are there no ripples on pre-Lollipop?
A lot of what allows RippleDrawable to run smoothly is Android 5.0’s new RenderThread. To optimize for performance on previous versions of Android, we've left RippleDrawable out for now.
To support ripple functionality below API 21 you may have to add a drawable in the background of your button:
<android.support.v7.widget.AppCompatButton
android:id="#+id/add_remove_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/button_ripple"
android:backgroundTint="#color/primary"
android:textColor="#android:color/white"
android:text="Remove" />
Then you have to add your xmls with the same name in both drawable and drawable-v21 directories (if you don't have them you may create and they will be automatically linked).
/res/drawable-v21/button_ripple.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/white">
<item>
<shape>
<solid android:color="#color/white" />
</shape>
</item>
</ripple>
/res/drawable/button_ripple.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#color/white" />
</shape>
</item>
</selector>
I am sharing as my use case: it was with ImageView:
app:backgroundTint was not taking effect because I used android:src tag for the background image in that Imageview.
when I changed it to android:background for Imageview then app:backgroundTint worked perfectly.
2nd Use case as mentioned by different answers one should use
androidx.appcompat.widget.AppCompatImageView
instead of ImageView.
I have an ImageButton with a background image that has some transparency. By default, the button gets a grey background where the transparency pixels are - due to the Holo.Light theme. I tried setting the background color of the button to transparent via the setBackgroundColor(Color.TRANSPARENT) method. That works just fine and does what I need except now my button no longer has the light blue color when focused/pressed and looks rather flat (no borders around it, so it looks like an image).
I googled and saw that you can assign selectors as explained here but that would mean that I have to specify an image per button state and I don't want to do that. I want to inherit the focuses/pressed colors from the theme but overwrite the normal button background (when not pressed/focused) to transparent instead of grey. How can I achieve that?? Please provide a working example as I have tried many different combinations with no success.
Edit
Thank you all for helping. I figured out how to make this work without having to recreate the same image with the focused and pressed states for each button!
Here is my solution:
My button is defined as:
<ImageButton
android:id="#+id/ImageButton05"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#drawable/button" />
And my background XML file (titled button.xml) is defined as follows:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<layer-list>
<item android:drawable="#drawable/btn_default_pressed_holo_light"></item>
<item android:drawable="#drawable/network_wifi"></item>
</layer-list>
</item>
<item android:state_focused="true">
<layer-list>
<item android:drawable="#drawable/btn_default_focused_holo_light"></item>
<item android:drawable="#drawable/network_wifi"></item>
</layer-list>
</item>
<item android:state_hovered="true">
<layer-list>
<item android:drawable="#drawable/btn_default_focused_holo_light"></item>
<item android:drawable="#drawable/network_wifi"></item>
</layer-list>
</item>
<item>
<layer-list>
<item android:drawable="#drawable/btn_default_normal_holo_light"></item>
<item android:drawable="#drawable/network_wifi"></item>
</layer-list>
</item>
</selector>
You can put something into an xml file, for example, custom_button.xml and then set background="#drawable/custom_button" in the button view.
Please refer to this link as there is an xml example: Standard Android Button with a different color
I used it in my code and it worked just the way I wanted.
Reference:
Standard Android Button with a different color
Edited:
If you would rather use
Maybe you should try to set a border.
For example (Reference: Android - border for button ):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:startColor="#FFFFFF"
android:endColor="#00FF00"
android:angle="270" />
<corners android:radius="3dp" />
<stroke android:width="5px" android:color="#000000" />
</shape>
OR,
You could try to set the style/theme for the button. (But it would be in a separate file)
The style/theme contains the color attributes for various states of button such as focused / enabled / disabled/ etc.
For setting background color/image and having click highlight effect,
Here is an example (Reference: How to programmatically setting style attribute in a view)
<?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>
You can then apply this selector to a Button by setting the property android:background="#drawable/my_button".
I want to inherit the focuses/pressed colors from the theme but overwrite the normal button background (when not pressed/focused) to transparent instead of grey. How can I achieve that??
AFAIK you can't because the focus/pressed colors are built in to the same image resources that contain the grey background.
If you want to keep the system focus/pressed but remove the background you'll have to grab a copy of the image resources (which can be found in your SDK at /sdkroot/platforms/[version]/data/res/drawable-hdpi replace [version] with whatever api level you are after. And if needbe replace hdpi with another density) and edit out the grey button from them with a photo editor. Then make a selector that references your modified images and set that as the background for your button.
EDIT:
Here are the default holo button images for focused and pressed
You can use ImageView instead of ImageButton to solve your problem. Please set the android:background property of the ImageView to the background color of the parent.
You can write this in your xml file:
android:background="#null"
It worked for me.
if u don't need the default gray background and u need your ImageButton seems like an icon without no backgrounds just use android:background attribute and set it to
#android:color/transparent**
<ImageButton
android:id="#+id/ImageButton05"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#android:color/transparent"
android:background="#drawable/button" />
hope that help anybody