Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
KeyboardInsetsPaddingBehavior.cs
1using System;
2using Microsoft.Maui.Controls;
3using Microsoft.Maui.Controls.Shapes;
6using ControlsVisualElement = Microsoft.Maui.Controls.VisualElement;
7
9{
13 public class KeyboardInsetsPaddingBehavior : Behavior<ControlsVisualElement>
14 {
15 private Thickness originalPadding;
16 private IKeyboardInsetsService? keyboardInsetsService;
17 private ControlsVisualElement? associatedView;
18
22 public static readonly BindableProperty AnimateProperty =
23 BindableProperty.Create(nameof(Animate), typeof(bool), typeof(KeyboardInsetsPaddingBehavior), true);
24
28 public static readonly BindableProperty AdditionalBottomPaddingProperty =
29 BindableProperty.Create(nameof(AdditionalBottomPadding), typeof(double), typeof(KeyboardInsetsPaddingBehavior), 0d);
30
34 public bool Animate
35 {
36 get => (bool)this.GetValue(AnimateProperty);
37 set => this.SetValue(AnimateProperty, value);
38 }
39
44 {
45 get => (double)this.GetValue(AdditionalBottomPaddingProperty);
46 set => this.SetValue(AdditionalBottomPaddingProperty, value);
47 }
48
50 protected override void OnAttachedTo(ControlsVisualElement bindable)
51 {
52 base.OnAttachedTo(bindable);
53 this.associatedView = bindable;
54 this.originalPadding = GetPadding(bindable);
55 this.keyboardInsetsService = ServiceRef.KeyboardInsetsService;
56 this.keyboardInsetsService.KeyboardInsetChanged += this.OnKeyboardInsetChanged;
57 this.ApplyPadding(bindable, this.keyboardInsetsService.KeyboardHeight, false);
58 }
59
61 protected override void OnDetachingFrom(ControlsVisualElement bindable)
62 {
63 base.OnDetachingFrom(bindable);
64 if (this.keyboardInsetsService is not null)
65 this.keyboardInsetsService.KeyboardInsetChanged -= this.OnKeyboardInsetChanged;
66 SetPadding(bindable, this.originalPadding);
67 this.keyboardInsetsService = null;
68 this.associatedView = null;
69 }
70
71 private void OnKeyboardInsetChanged(object? sender, KeyboardInsetChangedEventArgs e)
72 {
73 if (this.associatedView is not ControlsVisualElement view)
74 return;
75
76 this.ApplyPadding(view, e.KeyboardHeight, this.Animate);
77 }
78
79 private void ApplyPadding(ControlsVisualElement view, double keyboardHeight, bool animate)
80 {
81 double totalBottom = this.originalPadding.Bottom + keyboardHeight + this.AdditionalBottomPadding;
82 Thickness targetPadding = new Thickness(
83 this.originalPadding.Left,
84 this.originalPadding.Top,
85 this.originalPadding.Right,
86 totalBottom);
87
88 if (!animate)
89 {
90 SetPadding(view, targetPadding);
91 return;
92 }
93
94 Thickness currentPadding = GetPadding(view);
95 if (this.AreThicknessClose(currentPadding, targetPadding))
96 {
97 SetPadding(view, targetPadding);
98 return;
99 }
100
101 const uint duration = 180;
102 Microsoft.Maui.Controls.ViewExtensions.CancelAnimations(view);
103 view.Animate(
104 "KeyboardInsetsPadding",
105 progress => SetPadding(view, this.InterpolateThickness(currentPadding, targetPadding, progress)),
106 rate: 16,
107 length: duration,
108 easing: Easing.CubicInOut,
109 finished: (v, cancelled) => SetPadding(view, targetPadding));
110 }
111
112 private static void SetPadding(ControlsVisualElement element, Thickness padding)
113 {
114 switch (element)
115 {
116 case Layout layout:
117 layout.Padding = padding;
118 break;
119 case ContentView contentView:
120 contentView.Padding = padding;
121 break;
122 case TemplatedView templatedView:
123 templatedView.Padding = padding;
124 break;
125 case Border border:
126 border.Padding = padding;
127 break;
128 }
129 }
130
131 private static Thickness GetPadding(ControlsVisualElement element)
132 {
133 return element switch
134 {
135 Layout layout => layout.Padding,
136 ContentView contentView => contentView.Padding,
137 TemplatedView templatedView => templatedView.Padding,
138 Border border => border.Padding,
139 _ => new Thickness(0)
140 };
141 }
142
143 private bool AreThicknessClose(Thickness a, Thickness b)
144 {
145 return Math.Abs(a.Left - b.Left) < 0.5 &&
146 Math.Abs(a.Top - b.Top) < 0.5 &&
147 Math.Abs(a.Right - b.Right) < 0.5 &&
148 Math.Abs(a.Bottom - b.Bottom) < 0.5;
149 }
150
151 private Thickness InterpolateThickness(Thickness from, Thickness to, double progress)
152 {
153 return new Thickness(
154 this.InterpolateDouble(from.Left, to.Left, progress),
155 this.InterpolateDouble(from.Top, to.Top, progress),
156 this.InterpolateDouble(from.Right, to.Right, progress),
157 this.InterpolateDouble(from.Bottom, to.Bottom, progress));
158 }
159
160 private double InterpolateDouble(double from, double to, double progress)
161 {
162 return from + ((to - from) * progress);
163 }
164 }
165}
Base class that references services in the app.
Definition: ServiceRef.cs:43
static IKeyboardInsetsService KeyboardInsetsService
Provides the current keyboard inset state.
Definition: ServiceRef.cs:166
Event data describing an update to the keyboard inset height.
double KeyboardHeight
Gets the keyboard height measured in device-independent units.
Applies the current keyboard inset to the padding of the associated view.
static readonly BindableProperty AnimateProperty
Identifies the Animate bindable property.
bool Animate
Gets or sets a value indicating whether padding changes should be animated.
override void OnDetachingFrom(ControlsVisualElement bindable)
double AdditionalBottomPadding
Gets or sets an additional bottom padding offset that is always added to the keyboard height.
static readonly BindableProperty AdditionalBottomPaddingProperty
Identifies the AdditionalBottomPadding bindable property.
Provides normalized keyboard inset information for UI components.
double KeyboardHeight
Gets the current keyboard height in device-independent units.
Definition: ImplTypes.g.cs:58