/
MaterialStepperRenderer.cs
147 lines (121 loc) · 3.71 KB
/
MaterialStepperRenderer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System;
using System.ComponentModel;
using CoreGraphics;
using MaterialComponents;
using UIKit;
using Xamarin.Forms.Platform.iOS;
using MButton = MaterialComponents.Button;
namespace Xamarin.Forms.Material.iOS
{
public class MaterialStepperRenderer : ViewRenderer<Stepper, MaterialStepper>
{
ButtonScheme _buttonScheme;
protected override void Dispose(bool disposing)
{
if (Control is MaterialStepper control)
{
control.DecrementButton.TouchUpInside -= OnStep;
control.IncrementButton.TouchUpInside -= OnStep;
}
_buttonScheme?.Dispose();
_buttonScheme = null;
base.Dispose(disposing);
}
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
{
_buttonScheme?.Dispose();
_buttonScheme = CreateButtonScheme();
base.OnElementChanged(e);
if (e.NewElement != null)
{
if (Control == null)
{
var stepper = CreateNativeControl();
stepper.DecrementButton.TouchUpInside += OnStep;
stepper.IncrementButton.TouchUpInside += OnStep;
SetNativeControl(stepper);
}
UpdateButtons();
ApplyTheme();
}
}
protected virtual ButtonScheme CreateButtonScheme()
{
return new ButtonScheme
{
ColorScheme = MaterialColors.Light.CreateColorScheme(),
ShapeScheme = new ShapeScheme(),
TypographyScheme = new TypographyScheme(),
};
}
protected virtual void ApplyTheme()
{
OutlinedButtonThemer.ApplyScheme(_buttonScheme, Control.DecrementButton);
OutlinedButtonThemer.ApplyScheme(_buttonScheme, Control.IncrementButton);
}
protected override MaterialStepper CreateNativeControl()
{
return new MaterialStepper();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.IsOneOf(Stepper.MinimumProperty, Stepper.MaximumProperty, Stepper.ValueProperty, VisualElement.IsEnabledProperty))
{
UpdateButtons();
}
}
protected override void SetBackgroundColor(Color color)
{
// don't call base
}
void UpdateButtons()
{
if (Element is Stepper stepper && Control is MaterialStepper control)
{
control.DecrementButton.Enabled = stepper.IsEnabled && stepper.Value > stepper.Minimum;
control.IncrementButton.Enabled = stepper.IsEnabled && stepper.Value < stepper.Maximum;
}
}
void OnStep(object sender, EventArgs e)
{
if (Element is Stepper stepper && sender is MButton button)
{
var increment = stepper.Increment;
if (button == Control.DecrementButton)
increment = -increment;
stepper.SetValueFromRenderer(Stepper.ValueProperty, stepper.Value + increment);
}
}
}
public class MaterialStepper : UIView
{
const int DefaultButtonSpacing = 4;
public MaterialStepper()
{
DecrementButton = new MButton();
DecrementButton.SetTitle("-", UIControlState.Normal);
IncrementButton = new MButton();
IncrementButton.SetTitle("+", UIControlState.Normal);
AddSubviews(DecrementButton, IncrementButton);
}
public MButton DecrementButton { get; }
public MButton IncrementButton { get; }
public override CGSize SizeThatFits(CGSize size)
{
var dec = DecrementButton.SizeThatFits(CGSize.Empty);
var inc = IncrementButton.SizeThatFits(CGSize.Empty);
var btn = new CGSize(
Math.Max(dec.Width, inc.Width),
Math.Max(dec.Height, inc.Height));
return new CGSize(btn.Width * 2 + DefaultButtonSpacing, btn.Height);
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
var btn = new CGSize((Bounds.Width - DefaultButtonSpacing) / 2, Bounds.Height);
DecrementButton.Frame = new CGRect(0, 0, btn.Width, btn.Height);
IncrementButton.Frame = new CGRect(btn.Width + DefaultButtonSpacing, 0, btn.Width, btn.Height);
}
}
}