I am relatively new to android styling techniques and I am trying to wrap my head around reusable components. My app has many buttons scattered throughout its' view hierarchy and they are all almost exactly the same (variable font color and button color). Is it possible to define one button drawable that can then have different styles applied to it such that, a button has one drawable definition that is applied as a background to a Button xml attribute like so <Button> android:background="#drawable/basic_btn"</Button> and then customize lets say the button color through styling, something like
<Button
style="#style/Button.Green"
android:background="#drawable/basic_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
then if I want a blue button using the same drawable I can set something like:
<Button
style="#style/Button.Blue"
android:background="#drawable/basic_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
is this possible? I currently do not get the result I want when trying this.
Edit with answer:
Looking back on my post, I don't believe I described my initial issue well enough and I appreciate everyone who has responded in between. My initial problem was attempting to apply different <styles> to a drawable to achieve different background colors, was not in fact changing the background color. My solution that I went with goes like this.
Define the drawable shape:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffffff"/>
<corners android:radius="3dp" />
Next, assign the drawable as a background
<Button style="#style/Button.basic
android:background="#drawable/btn_basic"
/>
Now for the heart of the trick:
<Button style="#style/Button.basic
android:background="#drawable/btn_basic"
android:backgroundTint="#color/seafoam"
/>
backgroundTint by default seems to add the color tint on top of the drawable. This allowed me to define one shape but apply any color to it when used in an xml file. backgroundTint
Use TextView Like This:-
<TextView
android:id="#+id/reviewsTitleTxt"
style="#style/txt_style_16sp_white_color_ffffff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="true"
android:gravity="center"
android:text="#string/reviews_txt"
android:layout_gravity="center_vertical"/>
Where Style file is:-
Define style in style file
<style name="txt_style_16sp_white_color_ffffff">
<item name="android:textSize">#dimen/txt_size_16sp</item>
<item name="android:textColor">#color/white_color_ffffff</item>
</style>
Since we were commenting and you weren't able to solve this via the posted answer I'm going to try to help you out.
First, you should define all the common attributes on a #style/ .xml
Secondly, define a #drawable/ as your background for each button:
Background drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="#dimen/button_round_radius"/>
<solid android:color="#color/background_color"/>
</shape>
The bad thing about this is you'll have to create a new drawable with somewhat the same properties just to change the color.
Also look into the already created themes/style that might help you on the reference of this answer.
Now on your button's XML declaration:
<Button
style="#style/YourCommonAttributesStyling"
android:background="#drawable/a_drawable_shape_like_the_above"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Reference: Android Material Design Button Styles
Related
I want to applying drawable to my android button.
But, background drawable is not working.
This is my drawable code.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#FFEF1D1D" />
</shape>
</item>
</layer-list>
and This is my layout code
<Button
android:id="#+id/booking"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="6.5"
android:text="bokking"
android:textStyle="bold"
android:textColor="#color/white"
android:background="#drawable/booking_btn"
android:layout_marginRight="10dp"/>
Drawable is not applied to Button, but drawable is applied to AppCompatButton. I wonder why too.
When I applied this code, Only backgroundTint applies to buttons.
I spent a week on this issue, but I couldn't solve it.
plz help me
You can't apply the background on the material button.
If you are using Theme.MaterialComponents.*, then the normal button also used as the material button forcefully.
You have two options.
change it to any AppCompat theme.
Still If you need a material theme for some components, then use any material theme with a bridge. like Theme.MaterialComponents.*.Bridge
So, If you will go with option 2, you can use material button as per your need.
use com.google.android.material.button.MaterialButton for material button else use your normal button.
Looks like there is a problem with the Theme since Android Studio 4.1, try changing the base Theme from Theme.MaterialComponents.DayNight.DarkActionBar to Theme.AppCompat.DayNight.DarkActionBar, it works for me.
There is only one chance for that.I think you are using material theme.That's why the background property is not applying for button.If you want use that,change the theme to appcompat varaint.
You didn't use the selector in your XML. Use Selector instead of Layer-List
I have this button:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:theme="#style/AppTheme.Button.Toolbar"/>
And this style:
<style name="AppTheme.Button.Toolbar" parent="Widget.AppCompat.Button.Borderless">
<item name="colorButtonNormal">#color/main</item>
<item name="android:textColor">#color/secondary</item>
</style>
Even though the style inherits from Widget.AppCompat.Button.Borderless, the button still has a border.
Changing Button to android.support.v7.widget.AppCompatButton did not help.
How to remove the border then?
Edit:
Setting background of the button is not an option - by doing so the animation of ripple effect is lost.
Edit 2:
Things become even more interesting.
Tried to change android:theme to style as #cadet suggested.
When button is defined this way:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:theme="#style/ToolbarButton"/>
That's what I get:
The colors apply, but there is distinct border.
If I just change theme to style:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
style="#style/ToolbarButton"/>
I get this:
There is no border, and the style is applied only partially (text is colored, button is not)
Edit 3:
Friends, I'm looking for a way to get borderless, styled button with ripple effects using styling approach. Hacking each and every button separately in layout files might work, but that's not the point.
Try this, hope out of this one may help you
<Button
android:id="#+id/btn_photo_lib"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startPhotoLibAction"
android:src="#drawable/library_blau_2"
style="?android:attr/borderlessButtonStyle"/>
or
android:background="#null"
set background #null. or set own created background
android:background="#null"
You can use a different View instead of Button
<LinearLayout
android:id="#+id/btn_action_alternative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:clickable="true" />
I found a better solution, you'll wanna create a custom drawable and depending on the min version your app supports, you'll need to create two, one for Android versions pre-21(Lollipop) and another for post 21(Lollipop). The two files will need to be named identically so Android can find them and match them appropriatly based on the API level. But in the file drawable file for API 21 and above your file should look like such:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:drawable="#drawable/button_normal"/>
</ripple>
This Drawable file is wrapping another Drawable that is your preferred background image or color with a ripple whose color is defined using "?android:colorControlHighlight", which is simple a reference to a default color from what ever theme the current activity is using.
If you need to support pre-21(Lollipop), your drawable file would simply be a selector, with the preferred drawable. Your preferred drawable should be the same background color, or even a transparent color to make sure you can see your parent layouts background color. Similar to this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/button_normal"/>
</selector>
You can combine this with a style in order to apply the borderless style to all buttons it to all buttons in a layout... I recommend you use a transparent drawable so you can use this style with all buttons regardless if their parent has a different color background. This will prevent you from making several themes with different backgrounds.
To handle versioning support, or even config support if you'd like custom drawables based on various device configurations, you would just create several drawable folders with a configuration specific suffix. So, for example, drawables only for version 21 and above you'd create a folder called 'drawable-21'.
I found a website that better explains what I'm talking about.
I have a AppCompatButton defined in a XML layout, and I have set a theme for it like this:
android:theme="#style/CustomAccentOverlay"
And I have set:
android:stateListAnimator="#null"
to remove the shadow. I have two problems with this.
The height of the button is deducted the height of the shadow, even though the shadow is not shown. Should I remove the shadow in some other way, or how do I fix this?
The button has rounded corners, and I want the corners to be sharp. I can not set a background on the button, because I want to keep the standard ripple effect and that goes away if I set a background (at least I don't know how to keep it if I set a background). I have tried setting
<item name="android:bottomLeftRadius">0dp</item>
and all the other corners to the CustomAccentOverlay theme and also its corresponding style, but it does not work. How can I set the corner radius to zero on my button?
Thank you
Søren
Use the following code for the Button.
<android.support.v7.widget.AppCompatButton
android:layout_width="200dp"
android:layout_height="200dp"
android:text="Button"
android:stateListAnimator="#null"
android:elevation="0dp"
android:background="#android:color/darker_gray"
android:foreground="?attr/selectableItemBackground"
/>
I will explain the attributes.
android:elevation="0dp" and android:stateListAnimator="#null". No shadow for the button.
android:background . Set the desired color as background. It removes the rounded corners.
android:foreground="?attr/selectableItemBackground" . It gives the ripple effect when the button is pressed.
Update 1:
It seems like android:foreground attribute for View works from API 23. For below APIs, create a drawable with ripple in drawable-v21 folder and set it as background to the button,
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="NewApi"
android:color="#color/ripple_color">
<item android:drawable="#color/normal_state_button_background_color"/>
</ripple>
For pre Lollipop versions, create a drawable with selector in drawable folder with the same name.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/pressed_color"
android:state_pressed="true" />
<item android:drawable="#drawable/focused_color"
android:state_focused="true" />
<item android:drawable="#drawable/normal_color" />
</selector>
First question:How to remove shadow of a button?
Here is the answer:
Just add this attribute to your button
android:stateListAnimator="#null"
Second question: How to make the corner of button sharp without losing the standard ripple effect.
Here is the answer: But first you have to make two drawble file with same name but one for below api 21 and one for api > 21 because the ripple is only available only api > 21.So now I am showing how to create that.Read the following text carefully
Right click on the drawble folder and choose new and "Drawble resource file" and hit next then name the drawble whatever you like and press ok.Then again right click on the drawble folder and choose new and "Drawble resource file" and hit next and name the drawble exactly what you named the previous drawble folder but this time at the bottom you can see a section called "available qualifiers".Go to this section and at the very bottom you can see "Version",click it and then you can see a arrow icon at the right,click it then in the "Platform api level" add 21 and then press ok.And now if you expand drawble folder you can see two file of your created drawble file.Once for api that is below 21 and once for upper 21.Open drawble file that you have created and make sure you open that have "(v21)" at the last.Now delete everything from there and add the following code
<?xml version="1.0" encoding="utf-8"?>
<ripple android:color="?attr/colorControlHighlight" xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<corners android:radius="0dp"/>
<solid android:color="#D6D7D7"/>
</shape>
</item>
</ripple>
And add this attribute to your button
android:background="#drawable/youdrawblefilethatyouhavecreated"
And now if you run your application you can see that there is no shadow and your button has sharp corner and if you click the ripple shows up.
Lastly,your button look something like this
<android.support.v7.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button 1"
android:background="#drawable/yourcreatddrawblefile"
android:stateListAnimator="#null"/>
Hope this help!
It really sounds like you want to use a clickable TextView rather than a Button. TextView by default will not have shadow and has sharp corners and you can attach a click listener to it. Remember, Button is just a fancy TextView with a lot of visual add-ons to it, and it sounds like you want to remove a lot of it.
If you want to keep the ripple on the TextView and define your own background, set android:foreground="?attr/selectableItemBackground"
EDIT: Even though the other answer was marked accepted, I would still argue that the OP should use a TextView with a click listener and applying the ripple effects to that than using a Button. Clickable TextViews in this manner are exactly how the Google I/O app implements all of their flat buttons that meet Material Design spec.
Use this code
<android.support.v7.widget.AppCompatButton
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#color/colorAccent"
android:text="#string/button" />
I need to create buttons and headers using colors and styles similar to play store UI.
How can i create a button using colors alone without using drawables?
When i fill red or green color to the button not getting such effect like in play store app
Here's a quick example for the buttons showing what you can do using xml only:
<Button
android:background="#drawable/button_red_round_corners"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:drawableLeft="#drawable/abc_ic_menu_paste_mtrl_am_alpha"
android:drawableStart="#drawable/abc_ic_menu_paste_mtrl_am_alpha"
android:paddingLeft="8dp"
android:drawablePadding="8dp"
android:textAllCaps="true"
android:gravity="left|center_vertical"
android:textColor="#android:color/white"
android:text="Clipboard" />
where button_red_round_corners is defined in your drawable folder as
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#EE0000" />
<corners android:radius="4dp" />
Result:
The only problem is that there's no touch feedback if you use the android:background attribute :-(
There should be a way using Drawable Selectors though.
android:drawableLeft="#drawable/abc_ic_menu_paste_mtrl_am_alpha"
android:drawableStart="#drawable/abc_ic_menu_paste_mtrl_am_alpha"
you can add this in your button
<Button ...
....
/>
whatever drawable u want to use ,you can put there
I have two buttons, one of them has default style, another has custom background drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="#color/green" />
</shape>
In the end buttons look like this:
So default button is somehow smaller than button with custom background, though they have same properties:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/bg_button_rounded_green"
android:text="Positive"
android:textColor="#color/white"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Negative"/>
It seems that custom background changes minHeight. How can I make this buttons look the same?
btn_default_normal.9.png is the default Image set to default Button widget in Android from any specific platform. Find this file in you SDK installation and copy to your res folder.
Path to find android-sdk\platforms\android-APILEVEL\data\res
Default button have default 9-patch background with own margins, shadows, etc (different for different Android versions). You have to use custom background for both buttons or take one of the default 9-patch background and create similar bg for positive button.
The default Holo Android button graphic is a PNG which purposely contains padding. If you press and hold, you'll notice a glow around the button appears...which takes up that spacing.
The default 9 patch image for the button uses drawable padding. In order to mimic it in your own drawable you can use insets. Something like:
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#drawable/bg_button_rounded_green" android:insetBottom="10dip"
android:insetLeft="10dip" android:insetRight="10dip" android:insetTop="10dip" />
I'll let you figure out what the values should be.