5

The button views on Xamarin Forms seem to get extra padding applied when deployed to Android. I have set Resources/values/styles.xml under my Android project to have all spacing, padding, and margins be 0 by default, yet there is still extra padding being applied:

<item name="android:radius">0.0px</item>
<item name="android:shadowRadius">0.0</item>
<item name="android:spacing">0.0px</item>
<item name="android:padding">0.0px</item>
<item name="android:layout_margin">0.0px</item>

Please look at the following comparison to see what I'm talking about (iOS on the left, Android on the right). Notice how views are flush with one another in iOS (as they should be), while there are unwanted extra gaps in Android. The displays consist of a combination of Absolute and Stack layouts, several buttons, and one label (the long one). Don't worry about things not being sized and lined up perfectly in the iOS example; it was intentional. The iOS display is exactly how I want them both to look.

App display in iOS App display in Android

Ideally, I'd like an Android style or a simple one-size-fits-all code snippet that I can use to get rid of Android's opinionated spacing. Margins, spacing, and padding are being set programmatically on the Views identically on both devices, so that shouldn't be the source of the problem.

Note that I'm using C# with Xamarin Forms - not XAML. So please provide answers that either apply to both, or at least work from a purely programmatic implementation of Xamarin Forms.

Here is another example (iOS on left, Android on right). The outer-most layout is a grid, containing six non-layout views (two buttons, two labels, and two entries) as well as a stack layout at the bottom (which again contains one button, one label, and one entry). You can see from the difference of coloring that everything lines up correctly, except for buttons. The alignment is only being set with view margins; default spacing and padding are all zeroed out (from the Android style, see above).

Alternate app display in iOSAlternate app display in Android

nbrosz
  • 874
  • 12
  • 18
  • 1
    The views with the "extra padding" are buttons right? – pinedax Jun 16 '17 at 20:39
  • Please provide some codes, so that we can reproduce this issue. – Elvis Xia - MSFT Jun 19 '17 at 00:51
  • @apineda This is an excellent point that I hadn't noticed until now; it **does** only apply to buttons. – nbrosz Jun 19 '17 at 13:33
  • @nbrosz check this answer: https://stackoverflow.com/a/44578111/1771254 – pinedax Jun 19 '17 at 15:08
  • @apineda You are correct - it is a mysterious space being added to the Android buttons. My examples above already demonstrate that Android buttons get extra space. But that doesn't answer the question; how do I remove that space? – nbrosz Jun 20 '17 at 17:00
  • @ElvisXia-MSFT Since the form controls are being created in C# code across multiple classes, I can't easily provide code examples. The screenshots comparing iOS to Android would be enough to demonstrate that the spacing issues exist, I would think, and I've explained some of my attempts to remove the spacing: padding, margins, and spacing are set to 0 in Android styles and only Margins are being set in code (and they are set identically between devices). – nbrosz Jun 20 '17 at 17:07
  • 1
    This "problem" is happening in Android not in your Xamarin.Forms code so you will need to fix it from the Android Project. For this you will have to create a CustomRenderer for your buttons and change the default style to your own style. Note: this is the default behaviour in Android. – pinedax Jun 20 '17 at 18:22
  • @apineda I was afraid that would be the answer. I was hoping that buttons wouldn't require custom renderers to get rid of unwanted spacing, but apparently not. Thanks. – nbrosz Jun 20 '17 at 18:43

3 Answers3

5

Try this:

In your Android Project open your Styles.xml

Inside the MyTheme.Base style (I am assuming is called like this based on the default Xamarin.Forms template) add the following line:

<item name="android:buttonStyle">@style/MyButton</item>

Create a new style with name MyButton

<style name="MyButton" parent="android:Widget.Material.Button">
  <item name="android:layout_margin">0dip</item>
  <item name="android:background">@drawable/button_ripple</item>
 </style>   

In the Drawable folder add a new XML file called button_ripple.xml and paste the following code:

<?xml version="1.0" encoding="utf-8"?>
<!-- in drawable folder-->
<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:colorControlHighlight">

    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="?android:colorAccent" />
        </shape>
    </item>

    <item>
        <shape android:shape="rectangle">
            <solid android:color="#ff0000" />
        </shape>
    </item>
</ripple>

This file is necessary because when the background of a button in Android is changed the ripple effect (the effect when tapping on it) is lost.

If you don't care about the effect go back to the style file and the MyButton style can be just something like this:

<style name="MyButton" parent="android:Widget.Material.Button">
  <item name="android:layout_margin">0dip</item>
  <item name="android:background">#ff0000</item>
 </style>

This might help you without CustomRenderers.-

pinedax
  • 9,246
  • 2
  • 23
  • 30
  • That would work very well, thank you! It looks like magic to me, though. I don't see how these rectangles pick up the Button's color in C#, or how it gets the "ripple" effect in place. But that wasn't the question either. This solved my problem. Thanks! – nbrosz Jun 21 '17 at 20:31
2

The Xamarin button now includes a Padding property that can be set to a Thickness.

Button button = new Button();
button.Text = "Button";
button.Clicked += OnClicked;
button.Padding = new Thickness(0, 0, 0, 0);
user9220597
  • 157
  • 1
  • 2
0

Well you can use the Device.Runtime platform, described on this link.

Basically you can choose the type of margin depending on the operating system.

if(Device.RuntimePlatform == Device.Android)
    button.margin = new Thickness(0);

Is this what you were looking for?

  • No, margins are already being either zeroed or set to what I need them to be. Padding and spacing is also being cancelled out. The problem is that there's additional spacing on Android buttons that I can't account for and don't know how to remove. – nbrosz Jun 19 '17 at 14:17
  • What Xamarin.Forms version are you using? But in any case @apineda 's answer seems it might be what you are looking for. – Tiago Alexandre De Noronha Jun 19 '17 at 22:42
  • So far as I see, his/her answer doesn't provide any solutions for removing the spacing; he/she just points out that the spacing exists (which I already knew from the screenshots presented in the OP). I'm using Xamarin version 4.5.0.476, Xamarin.Android version 7.3.1.2, and Xamarin.iOS version 10.10.0.35 – nbrosz Jun 20 '17 at 17:02