@@ -489,6 +489,19 @@ public partial class SfBottomSheet : SfView, IParentThemeElement
489
489
BindingMode . Default
490
490
) ;
491
491
492
+ /// <summary>
493
+ /// Identifies the <see cref="AnimationDuration"/> bindable property.
494
+ /// </summary>
495
+ /// <value>
496
+ /// The identifier for <see cref="AnimationDuration"/> bindable property.
497
+ /// </value>
498
+ public static readonly BindableProperty AnimationDurationProperty = BindableProperty . Create (
499
+ nameof ( AnimationDuration ) ,
500
+ typeof ( double ) ,
501
+ typeof ( SfBottomSheet ) ,
502
+ 150d ,
503
+ BindingMode . Default ) ;
504
+
492
505
#endregion
493
506
494
507
#region Internal Bindable Properties
@@ -1183,6 +1196,19 @@ public bool CollapseOnOverlayTap
1183
1196
set => SetValue ( CollapseOnOverlayTapProperty , value ) ;
1184
1197
}
1185
1198
1199
+ /// <summary>
1200
+ /// Gets or sets the duration, in milliseconds, for the opening and closing animations.
1201
+ /// </summary>
1202
+ /// <value>
1203
+ /// It accepts double values, and the default value is 150ms.
1204
+ /// </value>
1205
+
1206
+ public double AnimationDuration
1207
+ {
1208
+ get => ( double ) GetValue ( AnimationDurationProperty ) ;
1209
+ set => SetValue ( AnimationDurationProperty , value ) ;
1210
+ }
1211
+
1186
1212
#endregion
1187
1213
1188
1214
#region Internal Properties
@@ -1256,6 +1282,17 @@ public void Close()
1256
1282
}
1257
1283
}
1258
1284
1285
+ /// <summary>
1286
+ /// Returns the value of <c>AnimationDuration</c>, ensuring it is clamped to a non-negative integer.
1287
+ /// This method is useful when passing the duration to animation APIs that require a <c>uint</c> value,
1288
+ /// preventing issues caused by negative durations.
1289
+ /// </summary>
1290
+ /// <returns>A non-negative integer representing the animation duration.</returns>
1291
+ int GetClampedAnimationDuration ( )
1292
+ {
1293
+ return ( int ) Math . Max ( 0 , AnimationDuration ) ;
1294
+ }
1295
+
1259
1296
#endregion
1260
1297
1261
1298
#region Internal Methods
@@ -2093,13 +2130,13 @@ void AnimateBottomSheet(double targetPosition, Action? onFinish = null)
2093
2130
_overlayGrid . AbortAnimation ( "overlayGridAnimation" ) ;
2094
2131
}
2095
2132
2096
- const int animationDuration = 150 ;
2097
- const int topPadding = 2 ;
2133
+ int animationDuration = this . GetClampedAnimationDuration ( ) ;
2134
+ const int topPadding = 2 ;
2098
2135
_isSheetOpen = true ;
2099
2136
if ( _bottomSheet is not null )
2100
2137
{
2101
2138
var bottomSheetAnimation = new Animation ( d => _bottomSheet . TranslationY = d , _bottomSheet . TranslationY , targetPosition + topPadding ) ;
2102
- _bottomSheet ? . Animate ( "bottomSheetAnimation" , bottomSheetAnimation , length : animationDuration , easing : Easing . Linear , finished : ( v , e ) =>
2139
+ _bottomSheet ? . Animate ( "bottomSheetAnimation" , bottomSheetAnimation , length : ( uint ) animationDuration , easing : Easing . Linear , finished : ( v , e ) =>
2103
2140
{
2104
2141
UpdateBottomSheetHeight ( ) ;
2105
2142
onFinish ? . Invoke ( ) ;
@@ -2133,7 +2170,15 @@ void AnimateOverlay(int animationDuration)
2133
2170
endValue = DefaultOverlayOpacity ;
2134
2171
}
2135
2172
2136
- var overlayGridAnimation = new Animation ( d => _overlayGrid . Opacity = d , startValue , endValue ) ;
2173
+ var overlayGridAnimation = new Animation ( d =>
2174
+ {
2175
+ // Ensure the opacity is only updated with valid numeric values to avoid rendering issues.
2176
+ if ( ! double . IsNaN ( d ) )
2177
+ {
2178
+ _overlayGrid . Opacity = d ;
2179
+ }
2180
+ }
2181
+ , startValue , endValue ) ;
2137
2182
_overlayGrid . Animate ( "overlayGridAnimation" , overlayGridAnimation ,
2138
2183
length : ( uint ) animationDuration ,
2139
2184
easing : Easing . Linear ,
0 commit comments