-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[Material] + [Android, iOS] Refactored and fixed lots of button layout issues #4967
Conversation
@@ -19,7 +19,8 @@ public class Button : View, IFontElement, ITextElement, IBorderElement, IButtonC | |||
public static readonly BindableProperty CommandParameterProperty = ButtonElement.CommandParameterProperty; | |||
|
|||
public static readonly BindableProperty ContentLayoutProperty = | |||
BindableProperty.Create("ContentLayout", typeof(ButtonContentLayout), typeof(Button), new ButtonContentLayout(ButtonContentLayout.ImagePosition.Left, DefaultSpacing)); | |||
BindableProperty.Create("ContentLayout", typeof(ButtonContentLayout), typeof(Button), new ButtonContentLayout(ButtonContentLayout.ImagePosition.Left, DefaultSpacing), | |||
propertyChanged: (bindable, oldVal, newVal) => ((Button)bindable).InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added to actually update the layout when the image is moved.
|
||
namespace Xamarin.Forms.Platform.Android | ||
{ | ||
// TODO: Currently the drawable is reloaded if the text or the layout changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The image is reloaded too often, but no more than currently. We can optimize!
if (view.TransformationMethod != null) | ||
buttonText = view.TransformationMethod.GetTransformationFormatted(buttonText, view); | ||
|
||
var measuredTextWidth = view.Paint.MeasureText(buttonText, 0, buttonText.Length()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We measure the text manually here so we can get the best position. This is "hidden" behind a flag (_alignIconWithText
) for the old buttons (non-material) to preserve backwards compatibility.
|
||
Thickness padding = _element.Padding; | ||
|
||
// TODO: The padding options here are both wrong. Need to sort this out. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The button padding needs discussion. But, this is just to make it look pretty. The old way is commented out below.
return; | ||
} | ||
|
||
using (var image = Context.GetDrawable(imageFile)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where the image is loaded, too often. We probably want to optimize before we release...
Button _element; | ||
bool _alignIconWithText; | ||
|
||
public ButtonLayoutManager(IButtonLayoutRenderer renderer, bool alignIconWithText = false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The alignIconWithText
parameter basically either positions the image at the edge of the button (old school), or next to the text (new, pretty school).
is it possible for ButtonLayoutManager to be static and just methods that are called into? like this one |
What happens if you change the background color? What happens if you just change the CornerRadius? |
Let me test and add some screenshots. But, that should not have changed as this just handles the text, padding and image properties. the border and background are still in the renderer. |
This has been an exciting few days... I think I got the general layout bits working, but I need to fix a few things that I spotted. But, before we talk bugs, the state. There are 4 buttons for Android, the original, the AppCompat, the Fast and the Material. I have decided not to touch the original, as that should not be used in new apps. I have done a bit of refactoring and managed to get the AppCompat and Fast working the same. They technically are the same native control, but one is in a view. The Material one is new and should be similar to the Fast - as MaterialButton is AppCompatButton with a few style changes. For iOS, there is just the classic and the Material. Now, bugs... The start of this PR fixed a majority of the Android layout issues (does not affect background, border, corners). But as I started testing all the various combinations, I found a few issues:
|
I also spotted another thing on iOS - when setting the Spacing to say 20, there is also a padding of 10 (basically half) applied to the button. I am not sure if this is a bug or a feature, but do we want to reproduce this for vertical? Consistency says yes, but my heart says bug. This can be "undone" with a negative padding, and I am sure changing this is going to break everyone. It is just weird and only in the direction of the layout. Also, you can see that the horizontal padding is also inconsistent when left/right vs top/bottom. Not sure yet what is causing that, but is that a feature, bug or something that we can't change? (probably the last one) Here are some pictures 😺
|
I figured out what was causing the weird horizontal padding when top/bottom. It is that the button is measured in the default state: [image|text] Then, we go ahead and move things. For material, I probably am going to be consistent with Android and remove this padding. But on Material and Buttons. Android has a minimum size - both horizontally and vertically. iOS... well that just has a minimum height (0 width buttons are valid). And, not just that, Android has significant padding - in the ranges of 20-30 pixels. iOS just has a minimum height. To be consistent, we might want to also add a base padding on iOS... |
Tell me this PR negates the need for #3251 🙏 |
@samhouts sadly not :( this PR just works with the layout of the elements above the background - text, image and padding. |
So, I think I am getting there. There are a few things that need investigating:
|
@mattleibow You removed the "fixes" keyword from the PR body. Was that intentional? |
build |
@samhouts nope. all magical now. |
build |
build |
Hey, first of all, thanks for the PR! I installed the latest preview and there are some things that are not behaving correctly (or so I believe at least).
Before https://i.imgur.com/yPJvFup.png I cannot verify this on a physical device right now, so I do hope it's not just a weird emulator bug.
4.0-pre4 + Material Visual https://i.imgur.com/HHxXmS5.png A workaround is to set negative spacing in |
Description of Change
Fixed ALL button issues 😝 (I am going to try and see if this PR will finally clinch all the issues). For all iOS/Android buttons (except the classic, non-AppCompat button), I have refactored the layout logic into a layout manager so that all the fixes get applied to all the buttons. There are some "feature flags" that you set on the manager to more finely control the appearance.
Issues Resolved
API Changes
Platforms Affected
Behavioral/Visual Changes
Button layout should be good 🤞
Before/After Screenshots
This is what the buttons look like with AppCompatButton via FastRenderers in this PR:
This is what it looks like on iOS:
This is what it looks like on Android with Material:
This is what it looks like on iOS with Material:
Testing Procedure
Play around in the galleries:
PR Checklist