Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

[iOS, Android, UWP] Added padding to Button control #2426

Merged
merged 1 commit into from
May 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using System;
using System.Linq;
using System.Threading;
using System.Collections.Generic;

namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 1702, "[Enhancement] Padding on Buttons", PlatformAffected.All)]
public class GitHub1702 : TestContentPage
{
bool animation = false;

protected override void Init()
{
StackLayout layout = new StackLayout()
{
Children =
{
new Button()
{
Image = "coffee.png",
BackgroundColor = Color.GreenYellow,
Text = "No padding? Height 100",
HeightRequest = 100,
},
new Button()
{
Image = "coffee.png",
BackgroundColor = Color.Green,
Padding = new Thickness(100, 0, 0, 0),
Text = "Do I have left padding? I should have left padding.",
},
new Button()
{
Image = "coffee.png",
BackgroundColor = Color.LawnGreen,
Padding = new Thickness(0, 30, 0, 0),
Text = "Do I have top padding? I should have top padding."
},
new Button()
{
Image = "coffee.png",
BackgroundColor = Color.LightGreen,
Padding = new Thickness(0, 0, 100, 0),
Text = "Do I have right padding? I should have right padding."
},
new Button()
{
Image = "coffee.png",
BackgroundColor = Color.ForestGreen,
Padding = new Thickness(0, 0, 0, 30),
Text = "Do I have bottom padding? I should have bottom padding."
}
}
};

var buttons = layout.Children.OfType<Button>();
layout.Children.Insert(0, ActionGrid(buttons.ToList()));
PaddingAnimation(buttons).Start();

Content = layout;
}

Grid ActionGrid(List<Button> buttons)
{
Button firstButton = buttons.FirstOrDefault();
Grid actionGrid = new Grid();
actionGrid.AddChild(new Button()
{
Text = "Reset text",
Command = new Command(() =>
{
buttons.ForEach(b => b.Text = string.Empty);
})
}, 0, 0);
actionGrid.AddChild(new Button()
{
Text = "Reset padding",
Command = new Command(() =>
{
buttons.ForEach(b => b.Padding = new Thickness(0, 0, 0, 0));
})
}, 0, 1);
actionGrid.AddChild(new Button()
{
Text = "Set text",
Command = new Command(() =>
{
buttons.ForEach(b => b.Text = "Some text");
})
}, 1, 0);
actionGrid.AddChild(new Button()
{
Text = "Animation",
Command = new Command(() => animation = !animation)
}, 1, 1);
actionGrid.AddChild(new Button()
{
Text = "Add Top",
Command = new Command(() =>
{
var button = firstButton;
button.Padding = new Thickness(0, button.Padding.Top + 10, 0, button.Padding.Bottom);
if (!String.IsNullOrWhiteSpace(button.Text))
button.Text = $"Top: {button.Padding.Top} Bottom: {button.Padding.Bottom}";
})
}, 2, 0);
actionGrid.AddChild(new Button()
{
Text = "Add Bottom",
Command = new Command(() =>
{
var button = firstButton;
button.Padding = new Thickness(0, button.Padding.Top, 0, button.Padding.Bottom + 10);
if (!String.IsNullOrWhiteSpace(button.Text))
button.Text = $"Top: {button.Padding.Top} Bottom: {button.Padding.Bottom}";
})
}, 2, 1);
return actionGrid;
}

Thread PaddingAnimation(IEnumerable<Button> buttons)
{
return new Thread(() =>
{
int increment = 1;
int current = 0;
int max = 15;
int FPS = 30;
int sleep = 1000 / FPS;

while (true)
{
Thread.Sleep(sleep);

if (!animation)
continue;

current += increment;
if (current > max || current < 0)
{
increment *= -1;
current += increment * 2;
}

Device.BeginInvokeOnMainThread(() =>
{
foreach (var button in buttons)
{
var padding = button.Padding;
button.Padding = padding = new Thickness(
padding.Left + increment,
padding.Top + increment,
padding.Right + increment,
padding.Bottom + increment);
}
});
}
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla59580.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Effects\AttachedStateEffect.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Effects\AttachedStateEffectList.cs" />
<Compile Include="$(MSBuildThisFileDirectory)GitHub1702.cs" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to Issue1702.cs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that in Issue#### classes some other github number is specified and different description.
For example Issue1461.cs created almost 2 years ago

[Issue (IssueTracker.Github, 1461, "1461 - (Popover in Portrait and Landscape)", PlatformAffected.iOS)]
public class Issue1461 : TestContentPage

And Github1461.cs created a couple of months ago
[Issue(IssueTracker.Github, 1461, "Cannot change TimePicker format", PlatformAffected.Android)]
public class Github1461 : TestContentPage // or TestMasterDetailPage, etc ...

Github1461.cs is correct for this repository #1461

I was confused. Is renaming to Issue#### still valid?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea :-/ Right now there's a mix of numbers that relate to the old github repo before the project went public. For now we're still just creating the Issues as Issue#### when there isn't a number collision

<Compile Include="$(MSBuildThisFileDirectory)GitHub2598.cs" />
<Compile Include="$(MSBuildThisFileDirectory)GitHub1878.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue1677.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ protected override void Build (StackLayout stackLayout)
}
);

var paddingContainer = new ViewContainer<Button> (Test.Button.Padding,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be added into the enum

new Button {
Text = "Padding", BackgroundColor = Color.Red, Padding = new Thickness (20, 30, 60, 15)
}
);

Add (borderButtonContainer);
Add (borderRadiusContainer);
Add (borderWidthContainer);
Expand All @@ -102,6 +108,7 @@ protected override void Build (StackLayout stackLayout)
Add (imageContainer);
Add (textContainer);
Add (textColorContainer);
Add (paddingContainer);
//stackLayout.Children.Add (textColorContainer);
}
}
Expand Down
20 changes: 19 additions & 1 deletion Xamarin.Forms.Core/Button.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace Xamarin.Forms
{
[RenderWith(typeof(_ButtonRenderer))]
public class Button : View, IFontElement, ITextElement, IBorderElement, IButtonController, IElementConfiguration<Button>
public class Button : View, IFontElement, ITextElement, IBorderElement, IButtonController, IElementConfiguration<Button>, IPaddingElement
{
const double DefaultSpacing = 10;
const int DefaultBorderRadius = 5;
Expand Down Expand Up @@ -50,6 +50,24 @@ public class Button : View, IFontElement, ITextElement, IBorderElement, IButtonC
propertyChanging: (bindable, oldvalue, newvalue) => ((Button)bindable).OnSourcePropertyChanging((ImageSource)oldvalue, (ImageSource)newvalue),
propertyChanged: (bindable, oldvalue, newvalue) => ((Button)bindable).OnSourcePropertyChanged((ImageSource)oldvalue, (ImageSource)newvalue));

public static readonly BindableProperty PaddingProperty = PaddingElement.PaddingProperty;

public Thickness Padding
{
get { return (Thickness)GetValue (PaddingElement.PaddingProperty); }
set { SetValue (PaddingElement.PaddingProperty, value); }
}

Thickness IPaddingElement.PaddingDefaultValueCreator ()
{
return default (Thickness);
}

void IPaddingElement.OnPaddingPropertyChanged (Thickness oldValue, Thickness newValue)
{
InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
}

readonly Lazy<PlatformConfigurationRegistry<Button>> _platformConfigurationRegistry;

public Color BorderColor
Expand Down
1 change: 1 addition & 0 deletions Xamarin.Forms.CustomAttributes/TestAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ public enum Button
BorderColor,
BorderRadius,
Image,
Padding
}

public enum VisualElement
Expand Down
30 changes: 27 additions & 3 deletions Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class ButtonRenderer : ViewRenderer<Button, AppCompatButton>, AView.IOnAt
Typeface _defaultTypeface;
bool _isDisposed;
int _imageHeight = -1;
Thickness _paddingDeltaPix = new Thickness();

public ButtonRenderer(Context context) : base(context)
{
Expand Down Expand Up @@ -58,9 +59,13 @@ protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
// We've got an image (and no text); it's already centered horizontally,
// we just need to adjust the padding so it centers vertically
var diff = (b - t - _imageHeight) / 2;
var diff = ((b - Context.ToPixels(Element.Padding.Bottom + Element.Padding.Top)) - t - _imageHeight) / 2;
diff = Math.Max(diff, 0);
Control?.SetPadding(0, diff, 0, -diff);
UpdateContentEdge(new Thickness(0, diff, 0, -diff));
}
else
{
UpdateContentEdge();
}

base.OnLayout(changed, l, t, r, b);
Expand Down Expand Up @@ -142,6 +147,8 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE
UpdateBitmap();
else if (e.PropertyName == VisualElement.IsVisibleProperty.PropertyName)
UpdateText();
else if (e.PropertyName == Button.PaddingProperty.PropertyName)
UpdatePadding();

base.OnElementPropertyChanged(sender, e);
}
Expand All @@ -163,6 +170,7 @@ void UpdateAll()
UpdateEnabled();
UpdateBackgroundColor();
UpdateDrawable();
UpdatePadding();
}

void UpdateDrawable()
Expand Down Expand Up @@ -195,7 +203,7 @@ void UpdateBitmap()
// to handle the vertical centering

// Clear any previous padding and set the image as top/center
Control.SetPadding(0, 0, 0, 0);
UpdateContentEdge();
Control.SetCompoundDrawablesWithIntrinsicBounds(null, image, null, null);

// Keep track of the image height so we can use it in OnLayout
Expand Down Expand Up @@ -277,6 +285,22 @@ void UpdateTextColor()
_textColorSwitcher?.UpdateTextColor(Control, Element.TextColor);
}

void UpdatePadding()
{
Control?.SetPadding(
(int)(Context.ToPixels(Element.Padding.Left) + _paddingDeltaPix.Left),
(int)(Context.ToPixels(Element.Padding.Top) + _paddingDeltaPix.Top),
(int)(Context.ToPixels(Element.Padding.Right) + _paddingDeltaPix.Right),
(int)(Context.ToPixels(Element.Padding.Bottom) + _paddingDeltaPix.Bottom)
);
}

void UpdateContentEdge (Thickness? delta = null)
{
_paddingDeltaPix = delta ?? new Thickness ();
UpdatePadding();
}

class ButtonClickListener : Object, AView.IOnClickListener
{
#region Statics
Expand Down
32 changes: 29 additions & 3 deletions Xamarin.Forms.Platform.Android/FastRenderers/ButtonRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ internal sealed class ButtonRenderer : AppCompatButton, IVisualElementRenderer,
readonly EffectControlProvider _effectControlProvider;
VisualElementTracker _tracker;
ButtonBackgroundTracker _backgroundTracker;
Thickness _paddingDeltaPix = new Thickness();

public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
public event EventHandler<PropertyChangedEventArgs> ElementPropertyChanged;
Expand Down Expand Up @@ -245,6 +246,7 @@ void OnElementChanged(ElementChangedEventArgs<Button> e)
UpdateInputTransparent();
UpdateBackgroundColor();
UpdateDrawable();
UpdatePadding();

ElevationHelper.SetElevation(this, e.NewElement);
}
Expand Down Expand Up @@ -282,6 +284,10 @@ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
UpdateInputTransparent();
}
else if (e.PropertyName == Button.PaddingProperty.PropertyName)
{
UpdatePadding();
}

ElementPropertyChanged?.Invoke(this, e);
}
Expand All @@ -297,9 +303,13 @@ protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
// We've got an image (and no text); it's already centered horizontally,
// we just need to adjust the padding so it centers vertically
int diff = (b - t - _imageHeight) / 2;
var diff = ((b - Context.ToPixels(Button.Padding.Bottom + Button.Padding.Top)) - t - _imageHeight) / 2;
diff = Math.Max(diff, 0);
SetPadding(0, diff, 0, -diff);
UpdateContentEdge(new Thickness(0, diff, 0, -diff));
}
else
{
UpdateContentEdge();
}

base.OnLayout(changed, l, t, r, b);
Expand Down Expand Up @@ -362,7 +372,7 @@ void UpdateBitmap()
// to handle the vertical centering

// Clear any previous padding and set the image as top/center
SetPadding(0, 0, 0, 0);
UpdateContentEdge();
SetCompoundDrawablesWithIntrinsicBounds(null, image, null, null);

// Keep track of the image height so we can use it in OnLayout
Expand Down Expand Up @@ -475,6 +485,22 @@ void UpdateTextColor()
_textColorSwitcher.Value.UpdateTextColor(this, Button.TextColor);
}

void UpdatePadding ()
{
SetPadding(
(int)(Context.ToPixels(Button.Padding.Left) + _paddingDeltaPix.Left),
(int)(Context.ToPixels(Button.Padding.Top) + _paddingDeltaPix.Top),
(int)(Context.ToPixels(Button.Padding.Right) + _paddingDeltaPix.Right),
(int)(Context.ToPixels(Button.Padding.Bottom) + _paddingDeltaPix.Bottom)
);
}

void UpdateContentEdge (Thickness? delta = null)
{
_paddingDeltaPix = delta ?? new Thickness ();
UpdatePadding ();
}

void UpdateDrawable()
{
_backgroundTracker?.UpdateDrawable();
Expand Down
Loading