Button is not filling parent container height [duplicate] - android

Currently, I have the following bottom log in button.
When button is not being pressed
When button is being pressed
The XML looks like this
<LinearLayout
android:background="?attr/welcomeBottomNavBarBackground"
android:orientation="horizontal"
android:id="#+id/sign_in_bottom_nav_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
style="?android:attr/buttonBarButtonStyle"
android:id="#+id/sign_in_button"
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="1.0"
android:layout_height="48dp"
android:gravity="center"
android:layout_gravity="center"
android:enabled="true"
android:textAllCaps="true"
android:text="#string/log_in" />
</LinearLayout>
I would like to remove the padding (Or should I call it margin? Please refer to my bottom most p/s section) around button when it is being pressed.
I look at How to remove padding around buttons in Android?
I had tried
<Button
...
...
android:minHeight="0dp"
android:minWidth="0dp" />
It doesn't work and has no effect.
I further try
<Button
...
...
android:background="#null"
android:minHeight="0dp"
android:minWidth="0dp" />
No more padding when pressed. However, the material designed pressed visual effect will gone too.
May I know what is the best way to remove button padding during pressed, yet retain the material designed pressed visual effect?
P/S
I don't really know whether I should call it padding or margin. What I wish to achieve is that, when we press on the bottom region, press visual effect change should be covered entire 100% bottom bar region (#+id/sign_in_bottom_nav_bar), instead of current 95% bottom bar region.

A standard button is not supposed to be used at full width which is why you experience this.
Background
If you have a look at the Material Design - Button Style you will see that a button has a 48dp height click area, but will be displayed as 36dp of height for...some reason.
This is the background outline you see, which will not cover the whole area of the button itself.
It has rounded corners and some padding and is supposed to be clickable by itself, wrap its content, and not span the whole width at the bottom of your screen.
Solution
As mentioned above, what you want is a different background. Not a standard button, but a background for a selectable item with this nice ripple effect.
For this use case there is the ?selectableItemBackground theme attribute which you can use for your backgrounds (especially in lists).
It will add a platform standard ripple (or some color state list on < 21) and will use your current theme colors.
For your usecase you might just use the following:
<Button
android:id="#+id/sign_in_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Login"
android:background="?attr/selectableItemBackground" />
<!-- /\ that's all -->
There is also no need to add layout weights if your view is the only one and spans the whole screen
If you have some different idea on what your background should look like you have to create a custom drawable yourself, and manage color and state there.

As simple, use the inset property like:
android:insetTop="0dp"
android:insetBottom="0dp"
android:insetRight="0dp"
android:insetLeft="0dp"

In styles.xml
<style name="MyButtonStyle" parent="Base.Widget.AppCompat.Button">
<item name="android:background">#drawable/selector</item>
<item name="android:textColor">#android:color/black</item>
</style>
In values/drawable:
my_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="2dp" />
<!-- specify your desired color here -->
<solid android:color="#9e9b99" />
</shape>
selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:drawable="#drawable/my_drawable"/>
<item android:state_pressed="true" android:drawable="#drawable/my_drawable"/>
<item android:drawable="#android:color/transparent"/>
</selector>
In values/drawable-v21:
my_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
android:tint="?attr/colorButtonNormal"
xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="2dp" />
<solid android:color="#android:color/white" />
</shape>
selector.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:id="#android:id/mask"
android:drawable="#drawable/my_drawable" />
</ripple>
In layout:
<Button
android:id="#+id/button"
style="#style/MyButtonStyle"
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="Test"/>
Result on API 19:
Result on API 21:
Source code

I think the best solution to solve that is create your own Ripple Effect. The padding when you press the button is respecting the default Ripple Effect of the component.
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:drawable="?attr/colorPrimary"/>
</ripple>
Or you can try change the style of your button to style="?android:textAppearanceSmall"
Remember: This effect is only shown on Android Lollipop (API 21) or higher.

I have been through what you are going through. Long story short, you just cannot do it cleanly with a <Button> tag alone, while ensuring backwards compatibility.
The simplest and the most widely practiced method is to use a <RelativeLayout> underlay, around a <Button>.
Button Code:
<RelativeLayout
android:id="#+id/myButtonUnderlay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:visibility="visible">
<Button
android:id="#+id/myButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:text="I am as cute as a Button"/>
</RelativeLayout>
Wherever you need to use a button, you use this complete code.
Here is the breakdown:
OnClick events will be hooked to myButton.
Control dimensions of your button, by changing attributes of myButtonUnderlay.
In myButton, android:background="?attr/selectableItemBackgroundBorderless". This will make it a transparent button with just the text, and backwards compatible ripples.
In myButtonUnderlay, you will do all the other background applications, like setting the color of the button, margins, paddings, borders, gradients, and shadows etc.
If manipulation of the button's visibility (programmatic or not) is wish, you do it on myButtonUnderlay.
Note: To ensure backwards compatibility, make sure that you use
android:background="?attr/selectableItemBackgroundBorderless", and NOT
android:background="?android:attr/selectableItemBackgroundBorderless"

As #David Medenjak answer you can read the Google Material design Button-style to its developer site. Use button style as #David Medenjak explained in his answer. You can also do by the following way also
It is not a padding or margin but it is actually background effect of button.
If you want to remove that then you can do as following.
Option 1:
Step 1: Put the below code in styles.xml
<style name="myColoredButton">
<item name="android:textColor">#FF3E96</item>
<item name="android:padding">0dp</item>
<item name="android:minWidth">88dp</item>
<item name="android:minHeight">36dp</item>
<item name="android:elevation">1dp</item>
<item name="android:translationZ">1dp</item>
<item name="android:background">#FF0000</item>
</style>
Step 2:Create a new XML file under drawables folder and add the following code: I named my XML file as button_prime.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/colorPrimary">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="1dp" />
<solid android:color="#8B8386" />
</shape>
</item>
</ripple>
Step 3: Use the style and drawable in your Button as follows.
<Button
style="#style/myColoredButton"
android:layout_width="250dp"
android:layout_height="50dp"
android:text="Cancel"
android:gravity="center"
android:background="#drawable/button_prime"
android:colorButtonNormal="#3578A9" />
Option 2:
With the Support Library v7, all the styles are actually already defined and ready to use, for the standard buttons, all of these styles are available.So you can set your button style like this
<Button
style="#style/Widget.AppCompat.Button.Borderless"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="BUTTON"
android:gravity="center"
android:minHeight="0dp"
android:minWidth="0dp"
android:background="#color/colorAccent"/>
For more detail of Button style please check this answer
I think you will check this answer also. I hope you will get your solution.

The padding and margin may be a result of the original resources used in the button.
So you could try to change the resources used, using a selector:
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/btn_action_hover" />
<item android:state_selected="true" android:drawable="#drawable/btn_action_hover" />
<item android:state_focused="true" android:drawable="#drawable/btn_action_hover" />
<item android:drawable="#drawable/btn_action_normal" />
</selector>
That would change the default images/shapes for your buttons, so you could try using drawables and set every item to a drawable. The drawable being either a bitmap, or a .xml file(style file) defining the look of the button in its current state. I assume there still are some native styles included even though you have set the button-style yourself. This may be because you aren't using a custom theme. So the issue may also be solved by defing
theme="#style/myNewTheme"
where myNewTheme is your theme, and it should have any parents(parent="" should not be defined).
Take any given theme(designed by Google/Android, for an instance Theme.AppCompat.[name]), it does also come with a buttonStyle. This is a part of Theme.Holo.Light:
<!-- Button styles -->
<item name="buttonStyle">#style/Widget.Holo.Light.Button</item>
<item name="buttonStyleSmall">#style/Widget.Holo.Light.Button.Small</item>
<item name="buttonStyleInset">#style/Widget.Holo.Light.Button.Inset</item>
<item name="buttonStyleToggle">#style/Widget.Holo.Light.Button.Toggle</item>
<item name="switchStyle">#style/Widget.Holo.Light.CompoundButton.Switch</item>
<item name="mediaRouteButtonStyle">#style/Widget.Holo.Light.MediaRouteButton</item>
<item name="selectableItemBackground">#drawable/item_background_holo_light</item>
<item name="selectableItemBackgroundBorderless">?attr/selectableItemBackground</item>
<item name="borderlessButtonStyle">#style/Widget.Holo.Light.Button.Borderless</item>
<item name="homeAsUpIndicator">#drawable/ic_ab_back_holo_light</item>
As you see, this theme defines how your buttons will look/work in basic features. You can override parts of it, but you haven't overridden the important parts(being buttonStyle and similar). So if you create a new theme yourself and style it to your liking and set the theme(using theme="themename") and that theme does not inherit any theme, you should be able to style your buttons to your liking without having to worry about the default styles in the theme
Basically:
calling padding/margin="0dp" will not help. The default drawable defined by the theme has this in the button drawable, meaning you cannot change it. So you have to either change the button style, or change the theme completely. Make sure that theme does not have any parents, because many themes define the button style. You do not want the button style defined by the theme.

The best solution these days is just to use MaterialButton in place of Button.
Note: MaterialButton is visually different from Button and AppCompatButton. One of the main differences is that AppCompatButton has a 4dp inset on the left and right sides, whereas MaterialButton does not. To add an inset to match AppCompatButton, set android:insetLeft and android:insetRight on the button to 4dp, or change the spacing on the button’s parent layout.
When replacing buttons in your app with MaterialButton, you should inspect these changes for sizing and spacing differences.
Source: https://material.io/develop/android/components/material-button/

I'd suggest you taking a look at this just in case before all.
Then, if not working i'd suggest you to create your own style (like azizbekian suggest)using android xml drawables, and drawable states to differentiate pressed/notpressed.
I think using your own style may be the best answer as it will further give you more control on how your app is displaying, but using android default themes and styles also allows the user to have custom styles which is a good idea. However, you cannot test every custom style so you cannot check that your app will display correctly on ALL custom styles, and therefore may encounter problems with some.

Set the Button background as android:background="?selectableItemBackground"
<LinearLayout
android:background="?attr/welcomeBottomNavBarBackground"
android:orientation="horizontal"
android:id="#+id/sign_in_bottom_nav_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
style="?android:attr/buttonBarButtonStyle"
android:background="?selectableItemBackground"
android:id="#+id/sign_in_button"
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="1.0"
android:layout_height="48dp"
android:gravity="center"
android:layout_gravity="center"
android:enabled="true"
android:textAllCaps="true"
android:text="#string/log_in" />
</LinearLayout>

After trying lots of solution, Finally I came to a conclusion that with tag alone we can't achieve this. to remove this unwanted space around button my solution is as below:
<RelativeLayout
android:id="#+id/myButtonUnderlay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:visibility="visible">
<Button
android:id="#+id/save_button"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="-5dp"
android:layout_marginBottom="-5dp"
android:layout_above="#+id/content_scrollview"
android:layout_gravity="bottom"
android:background="#drawable/ripple_theme"
android:enabled="true"
android:text="SetUp Store"
android:textColor="#fff"
android:textSize="18sp"
android:visibility="gone"
tools:visibility="visible"
style="#style/MediumFontTextView" />
</RelativeLayout>

1.add a drawable resource file named maybe button_background.xml
<?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="#ff0000"/>
<stroke android:width="5dp" android:color="#00ff00"/>
</shape>
</item>
<item>
<shape>
<solid android:color="#00ff00"/>
</shape>
</item>
</selector>
2.Use the button_background.xml as the button background, done!
github
blog

I don't really know whether I should call it padding or margin.
The button is enacting surface elevation for providing visual feedback in response to touch. It is one of two feedbacks used for surface reaction; the first one being the ripple effect. For example, a raised button has resting state elevation of 2dp and pressed state elevation of 8dp (See raised button under Shadows). The button meets the finger as it touches the surface.
May I know what is the best way to remove button padding during pressed, yet retain the material designed pressed visual effect?
Having answered the first part, I do not believe you are having all of the material design if you wish to remove the surface elevation effect.
Anyways, here is how to remove surface elevation visual feedback:
Add animator file button_raise.xml to animator directory under res directory having the following code:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_enabled="true"
android:state_pressed="true">
<objectAnimator
android:duration="#android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueTo="0dp"
android:valueType="floatType" />
</item>
</selector>
Refer newly created animator in the button using stateListAnimator property:
<Button
...
android:stateListAnimator="#animator/button_raise"
... />
Hope this helps.

Related

Customise Android SwitchCompat

In my Android app, I have a list with a SwitchCompat to filter the list data. The default theme can't serve my purpose what I need is a iOS like switch. I have no idea how can I customize it to look exactly like the iOS switch. Thanks for reading.
<androidx.appcompat.widget.SwitchCompat
android:id="#+id/switch_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#xml/custom_switch_background_main"
android:theme="#style/AppTheme.SwitchOverlay"/>
This is what I have archived so far
custom_switch_background_main.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false" android:drawable="#xml/custom_switch_background" />
<item android:state_checked="true" android:drawable="#xml/custom_switch_background" />
</selector>
custom_switch_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="50dp" />
<solid android:color="#color/transparent" />
<stroke
android:width="1dp"
android:color="#color/hello" />
</shape>
This is what I want
You can achieve something like:
with the standard MaterialButtonToggleGroup:
<com.google.android.material.button.MaterialButtonToggleGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:selectionRequired="true"
app:singleSelection="true">
<com.google.android.material.button.MaterialButton
app:shapeAppearanceOverlay="#style/ShapeAppearanceOverlay.App.rounded"
style="?attr/materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ITEM1"/>
<com.google.android.material.button.MaterialButton
app:shapeAppearanceOverlay="#style/ShapeAppearanceOverlay.App.rounded"
style="?attr/materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ITEM2"/>
</com.google.android.material.button.MaterialButtonToggleGroup>
with:
<style name="ShapeAppearanceOverlay.App.rounded" parent="">
<item name="cornerSize">50%</item>
</style>
If you want the border you can wrap the MaterialButtonToggleGroup in a container (LinearLayout, CardView....) applying a stroke a small padding.
If you want the button with rounded corners on both side you can check something like this question.
I think you should use sliding tab layout instead of switchcompat to fulfill your requirement. I have found one third party library that's looks like same switch as you want.
Click Here to Use This Library
I achieved the design by using a custom vector (and the text inside was a mask) which was replacement for the switch’s state indicator. then I changed the switch compat background vector with a custom border design as well to achieve the border. I’ll update this answer again soon.

Android app - basic icon button without text

How do I make a basic icon button without text or background? For example, just a simple vector image from #drawables that, when clicked, shows that circular response thing around it. I don't want the icon to have any background color to it. Just an icon that can be clicked, that's literally it.
I can only figure out how to do it by creating a menu and setting the icon as an item with app:showAsAction="always". It seems like there must be a better way to do this.
Edit: Here's an example of what I want to achieve. It's very basic. Just a clickable icon with responsive feedback when touched. https://material-ui.com/components/buttons/#icon-buttons
It's exactly the same as creating the following. I just thought there was likely an easier way to do this without having to create and load a menu just for one single icon:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.mycompany.myapp.MainActivity">
<item
android:id="#+id/action_contacts"
android:icon="#drawable/ic_contacts_24"
android:title="#string/action_contacts"
app:iconTint="#android:color/white"
app:showAsAction="always" />
</menu>
First create a vector drawable and then add to the ImageView like
this:
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
app:srcCompat="#drawable/ic_delete" />
You can use a MaterialButton, ImageButton and even an ImageView for this. Here's an example of how you'd do it with an ImageView...
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:src="#drawable/your_icon" />
All you need to do is set the selectableItemBackground, this will use your theme's primary color (or maybe the secondary color, I can't remember).
Now if you want a different color for ripple effect, for example a grey ripple, then you can create the drawable yourself...
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#dddddd">
<item android:id="#android:id/mask">
<color android:color="#dddddd" />
</item>
</ripple>
and set the view background below..
android:background="?attr/selectableItemBackground"
it'll work with any view provided the view is clickable
Yes, you can use ImageView if you like, but if you want to generate the complete image (including frame/borders) yourself you don't have to go that far. You could practically use plain View (except that you'd have to supply android:layout_width/height explicitly). Just use Button and have the android:background specify a selector which will select between images.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/clear1" android:state_pressed="true"/>
<item android:drawable="#drawable/clear0"/>
</selector>

How to Style Button

I am looking for a way to style my button like an example from an older question (How to create standard Borderless buttons (like in the design guidline mentioned)?) but some things were left out from the answer.
How can I add more than one value to an XML element, particularly android:background ="";?
I figured out how to make my buttons borderless, but I want them to have a really thin border, and a different background color. I have seen lots of tips online, but I can't find a way to put all my items together properly in code. Below is a copy pasted image with the top part representing the layout I want to achieve with the button name and a thumbnail image on the right hand side on the button with the button being a different color then the background of the app, and below that is a copy pasted image of the border style I'm trying to achieve, thin, touching borders between buttons. I have looked everywhere and tried many ideas but none seem to work properly, or some require me to have
android:background="?android:attr/selectableItemBackground"
but this interacts with
android:background="#22272D"
I need to keep the text in the button because my app is going to translate the buttons text to the language of the users phone, so I can't make the whole button just an image. Below is my XML and the output, any recommendations to how I should change it would be of massive help!
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="6"
tools:context="com.aid.travelers.myapplication.Transportation">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/transportation_page"
android:textSize="40sp"
android:textColor="#000000"/>
<Button
android:layout_width="match_parent"
android:text="#string/airport"
android:id="#+id/AirportButton"
android:layout_height="60dp"
android:layout_weight="1"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:background="?android:attr/selectableItemBackground"/>
<Button
android:layout_width="match_parent"
android:text="#string/bicycle"
android:id="#+id/BicycleButton"
android:layout_height="60dp"
android:layout_weight="1"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:background="?android:attr/selectableItemBackground"/>
I'm not sure that I get your question, but I guess you want to custom the background of your button, and have a touch effect when you press it.
Have a look at this answer :
https://stackoverflow.com/a/7176006/5446285
You should create your own resource file background.xml (for example) that you create in your drawable folder.
The code should be like :
<?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/background_selected"/> <!-- pressed -->
<item android:drawable="#drawable/background_unselected" /> <!-- default -->
</selector>
You should now create 2 other files in your drawable folder : background_selected.xml, and background_unselected.xml.
To do so, I advise you something like this if you want a thin border :
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#7c7c7c" />
</shape>
</item>
<item android:bottom="2dp" android:top="2dp" android:right="2dp" android:left="2dp">
<shape android:shape="rectangle" >
<solid android:color="#a0a0a0" />
</shape>
</item>
Then you set the background of your button in your xml :
android:background="#drawable/background"

How do I set a "pressed" imagebutton in Android Studio?

I have an ImageButton:
<ImageButton
android:layout_width="60dp"
android:layout_height="60dp"
android:id="#+id/btn_70s"
android:src="#drawable/btn_70s"
android:background="#null" /* Sets transparent BG for button image(PNG) */
/>
The image is "btn_70s", how do I set a "pressed" version of the image for when the ImageButton is tapped?
The documentation states to create an XML file and place it in the drawable directory:
<?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/button_pressed" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="#drawable/button_focused" /> <!-- focused -->
<item android:drawable="#drawable/button_normal" /> <!-- default -->
</selector>
This to me says it would affect all the ImageButtons rather than an individual one. Would I save it as an individual XML for each button for example (btn_70s_custom.xml), and then use it like:
<ImageButton
android:layout_width="60dp"
android:layout_height="60dp"
android:id="#+id/btn_70s"
android:src="#drawable/btn_70s"
android:android:background="#drawable/btn_70s_custom"
/>
Only issue with this, I can't use #null to allow transparency. Any assistance is appreciate.
Have a look over there for a (possible) solution to your problem : Make button background transparent using selector
And for the record,
This to me says it would affect all the ImageButtons rather than an individual one. Would I save it as an individual XML for each button for example (btn_70s_custom.xml), and then use it like:
No, it won't set this theme for all the buttons, but only for the ones where you specify to use this selector.
Hope this helps!
You can try selectableItemBackground
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"/>

Android Material Design Button Styles

I'm confused on button styles for material design. I'd like to get colorful raised buttons like in the attached link., like the "force stop" and "uninstall" buttons seen under the usage section. Are there available styles or do I need to define them?
http://www.google.com/design/spec/components/buttons.html#buttons-usage
I couldn't find the default button styles.
Example:
<Button style="#style/PrimaryButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Calculate"
android:id="#+id/button3"
android:layout_below="#+id/editText5"
android:layout_alignEnd="#+id/editText5"
android:enabled="true" />
If I try to change the background color of the button by adding
android:background="#color/primary"
all of the styles go away, such as the touch animation, shadow, rounded corner, etc.
I will add my answer since I don't use any of the other answers provided.
With the Support Library v7, all the styles are actually already defined and ready to use, for the standard buttons, all of these styles are available:
style="#style/Widget.AppCompat.Button"
style="#style/Widget.AppCompat.Button.Colored"
style="#style/Widget.AppCompat.Button.Borderless"
style="#style/Widget.AppCompat.Button.Borderless.Colored"
Widget.AppCompat.Button:
Widget.AppCompat.Button.Colored:
Widget.AppCompat.Button.Borderless
Widget.AppCompat.Button.Borderless.Colored:
To answer the question, the style to use is therefore
<Button style="#style/Widget.AppCompat.Button.Colored"
.......
.......
.......
android:text="Button"/>
How to change the color
For the whole app:
The color of all the UI controls (not only buttons, but also floating action buttons, checkboxes etc.) is managed by the attribute colorAccent as explained here.
You can modify this style and apply your own color in your theme definition:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
...
<item name="colorAccent">#color/Orange</item>
</style>
For a specific button:
If you need to change the style of a specific button, you can define a new style, inheriting one of the parent styles described above. In the example below I just changed the background and font colors:
<style name="AppTheme.Button" parent="Widget.AppCompat.Button.Colored">
<item name="colorButtonNormal">#color/Red</item>
<item name="android:textColor">#color/White</item>
</style>
Then you just need to apply this new style on the button with:
android:theme="#style/AppTheme.Button"
To set a default button design in a layout, add this line to the styles.xml theme:
<item name="buttonStyle">#style/btn</item>
where #style/btn is your button theme. This sets the button style for all the buttons in a layout with a specific theme
Simplest Solution
Step 1: Use the latest support library
compile 'com.android.support:appcompat-v7:25.2.0'
Step 2: Use AppCompatActivity as your parent Activity class
public class MainActivity extends AppCompatActivity
Step 3: Use app namespace in your layout XML file
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
Step 4: Use AppCompatButton instead of Button
<android.support.v7.widget.AppCompatButton
android:id="#+id/buttonAwesome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Awesome Button"
android:textColor="#color/whatever_text_color_you_want"
app:backgroundTint="#color/whatever_background_color_you_want"/>
If I understand you correctly, you want to do something like this:
In such case, it should be just enough to use:
<item name="android:colorButtonNormal">#2196f3</item>
Or for API less than 21:
<item name="colorButtonNormal">#2196f3</item>
In addition to Using Material Theme Tutorial.
Animated variant is here.
You can use the
Material Component library.
Add the dependency to your build.gradle:
dependencies { implementation ‘com.google.android.material:material:1.3.0’ }
Then add the MaterialButton to your layout:
<com.google.android.material.button.MaterialButton
style="#style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
app:strokeColor="#color/colorAccent"
app:strokeWidth="6dp"
app:layout_constraintStart_toStartOf="parent"
app:shapeAppearance="#style/MyShapeAppearance"
/>
You can check the full documentation here and API here.
To change the background color you have 2 options.
Using the backgroundTint attribute.
Something like:
<style name="MyButtonStyle"
parent="Widget.MaterialComponents.Button">
<item name="backgroundTint">#color/button_selector</item>
//..
</style>
It will be the best option in my opinion. If you want to override some theme attributes from a default style then you can use new materialThemeOverlay attribute.
Something like:
<style name="MyButtonStyle"
parent="Widget.MaterialComponents.Button">
<item name=“materialThemeOverlay”>#style/GreenButtonThemeOverlay</item>
</style>
<style name="GreenButtonThemeOverlay">
<!-- For filled buttons, your theme's colorPrimary provides the default background color of the component -->
<item name="colorPrimary">#color/green</item>
</style>
The option#2 requires at least the version 1.1.0.
You can use one of these styles:
Filled Button (default): style="#style/Widget.MaterialComponents.Button
Text Button: style="#style/Widget.MaterialComponents.Button.TextButton"
OutlinedButton: style="#style/Widget.MaterialComponents.Button.OutlinedButton"
OLD Support Library:
With the new Support Library 28.0.0, the Design Library now contains the MaterialButton.
You can add this button to our layout file with:
<android.support.design.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="YOUR TEXT"
android:textSize="18sp"
app:icon="#drawable/ic_android_white_24dp" />
By default this class will use the accent colour of your theme for the buttons filled background colour along with white for the buttons text colour.
You can customize the button with these attributes:
app:rippleColor: The colour to be used for the button ripple effect
app:backgroundTint: Used to apply a tint to the background of the button. If you wish to change the background color of the button, use this attribute instead of background.
app:strokeColor: The color to be used for the button stroke
app:strokeWidth: The width to be used for the button stroke
app:cornerRadius: Used to define the radius used for the corners of the button
Here is how I got what I wanted.
First, made a button (in styles.xml):
<style name="Button">
<item name="android:textColor">#color/white</item>
<item name="android:padding">0dp</item>
<item name="android:minWidth">88dp</item>
<item name="android:minHeight">36dp</item>
<item name="android:layout_margin">3dp</item>
<item name="android:elevation">1dp</item>
<item name="android:translationZ">1dp</item>
<item name="android:background">#drawable/primary_round</item>
</style>
The ripple and background for the button, as a drawable primary_round.xml:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/primary_600">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="1dp" />
<solid android:color="#color/primary" />
</shape>
</item>
</ripple>
This added the ripple effect I was looking for.
Beside android.support.design.button.MaterialButton (which mentioned by Gabriele Mariotti),
There is also another Button widget called com.google.android.material.button.MaterialButton which has different styles and extends from AppCompatButton:
style="#style/Widget.MaterialComponents.Button"
style="#style/Widget.MaterialComponents.Button.UnelevatedButton"
style="#style/Widget.MaterialComponents.Button.TextButton"
style="#style/Widget.MaterialComponents.Button.Icon"
style="#style/Widget.MaterialComponents.Button.TextButton.Icon"
Filled, elevated Button (default):
style="#style/Widget.MaterialComponents.Button"
Filled, unelevated Button:
style="#style/Widget.MaterialComponents.Button.UnelevatedButton"
Text Button:
style="#style/Widget.MaterialComponents.Button.TextButton"
Icon Button:
style="#style/Widget.MaterialComponents.Button.Icon"
app:icon="#drawable/icon_24px" // Icons can be added from this
A text Button with an icon::
Read: https://material.io/develop/android/components/material-button/
A convenience class for creating a new Material button.
This class supplies updated Material styles for the button in the
constructor. The widget will display the correct default Material
styles without the use of the style flag.
Here is a sample that will help in applying button style consistently across your app.
Here is a sample Theme I used with the specific styles..
<style name="MyTheme" parent="#style/Theme.AppCompat.Light">
<item name="colorPrimary">#color/primary</item>
<item name="colorPrimaryDark">#color/primary_dark</item>
<item name="colorAccent">#color/accent</item>
<item name="android:buttonStyle">#style/ButtonAppTheme</item>
</style>
<style name="ButtonAppTheme" parent="android:Widget.Material.Button">
<item name="android:background">#drawable/material_button</item>
</style>
This is how I defined the button shape & effects inside res/drawable-v21 folder...
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="2dp" />
<solid android:color="#color/primary" />
</shape>
</item>
</ripple>
2dp corners are to keep it consistent with Material theme.
I tried a lot of answer & third party libs, but none was keeping the border and raised effect on pre-lollipop while having the ripple effect on lollipop without drawback. Here is my final solution combining several answers (border/raised are not well rendered on gifs due to grayscale color depth) :
Lollipop
Pre-lollipop
build.gradle
compile 'com.android.support:cardview-v7:23.1.1'
layout.xml
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card"
card_view:cardElevation="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardMaxElevation="8dp"
android:layout_margin="6dp"
>
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="0dp"
android:background="#drawable/btn_bg"
android:text="My button"/>
</android.support.v7.widget.CardView>
drawable-v21/btn_bg.xml
<?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>
drawable/btn_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/colorPrimaryDark" android:state_pressed="true"/>
<item android:drawable="#color/colorPrimaryDark" android:state_focused="true"/>
<item android:drawable="#color/colorPrimary"/>
</selector>
Activity's onCreate
final CardView cardView = (CardView) findViewById(R.id.card);
final Button button = (Button) findViewById(R.id.button);
button.setOnTouchListener(new View.OnTouchListener() {
ObjectAnimator o1 = ObjectAnimator.ofFloat(cardView, "cardElevation", 2, 8)
.setDuration
(80);
ObjectAnimator o2 = ObjectAnimator.ofFloat(cardView, "cardElevation", 8, 2)
.setDuration
(80);
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
o1.start();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
o2.start();
break;
}
return false;
}
});
1) You can create rounded corner button by defining xml drawable and you can increase or decrease radius to increase or decrease roundness of button corner.
Set this xml drawable as background of button.
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="4dp"
android:insetTop="6dp"
android:insetRight="4dp"
android:insetBottom="6dp">
<ripple android:color="?attr/colorControlHighlight">
<item>
<shape android:shape="rectangle"
android:tint="#0091ea">
<corners android:radius="10dp" />
<solid android:color="#1a237e" />
<padding android:bottom="6dp" />
</shape>
</item>
</ripple>
</inset>
2) To change default shadow and shadow transition animation between button states, you need to define selector and apply it to button using android:stateListAnimator property. For complete button customization reference : http://www.zoftino.com/android-button
I've just created an android library, that allows you to easily modify the button color and the ripple color
https://github.com/xgc1986/RippleButton
<com.xgc1986.ripplebutton.widget.RippleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn"
android:text="Android button modified in layout"
android:textColor="#android:color/white"
app:buttonColor="#android:color/black"
app:rippleColor="#android:color/white"/>
You don't need to create an style for every button you want wit a different color, allowing you to customize the colors randomly
// here is the custom button style
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:angle="45"
android:centerColor="#color/colorPrimary"
android:startColor="#color/colorPrimaryDark"
android:endColor="#color/colorAccent"
>
</gradient>
<corners
android:topLeftRadius="10dp"
android:topRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp"
>
</corners>
<stroke
android:width="2dp"
android:color="#color/colorWhite"
>
</stroke>
</shape>
</item>
</selector>
you can give aviation to the view by adding z axis to it and can have default shadow to it. this feature was provided in L preview and will be available after it release. For now you can simply add a image the gives this look for button background

Categories

Resources