如何在.NET MAUI中实现支持半星的滑动评分条
实现跨平台可滑动评分控件(支持半星)
核心思路
- 用
PanGestureRecognizer捕获滑动手势,将滑动距离转换为0-5分的评分值(支持0.5步长) - 每个星星根据当前评分判断自身状态:全满、半满、空
- 实时更新星星显示状态,对外暴露可绑定的评分属性供业务层获取输入值
具体实现步骤
1. 定义星星状态与基础控件
先创建星星状态枚举,区分三种显示状态:
public enum StarFillState { Empty, Half, Full }
编写可复用的星星控件(StarView),根据状态切换对应图片:
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="YourNamespace.StarView"> <ContentView.Content> <Image x:Name="StarImage" Aspect="AspectFit" /> </ContentView.Content> </ContentView>
后台代码绑定状态属性,自动切换图片:
public partial class StarView : ContentView { public static readonly BindableProperty StateProperty = BindableProperty.Create(nameof(State), typeof(StarFillState), typeof(StarView), StarFillState.Empty, propertyChanged: OnStateChanged); public StarFillState State { get => (StarFillState)GetValue(StateProperty); set => SetValue(StateProperty, value); } private static void OnStateChanged(BindableObject bindable, object oldValue, object newValue) { var starView = (StarView)bindable; switch ((StarFillState)newValue) { case StarFillState.Empty: starView.StarImage.Source = "star_empty.png"; break; case StarFillState.Half: starView.StarImage.Source = "star_half.png"; break; case StarFillState.Full: starView.StarImage.Source = "star_full.png"; break; } } public StarView() { InitializeComponent(); } }
2. 构建滑动评分容器
用HorizontalStackLayout承载星星控件,添加滑动手势识别器:
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:YourNamespace" x:Class="YourNamespace.SwipeRatingControl"> <ContentView.Content> <HorizontalStackLayout x:Name="StarsContainer" Spacing="4"> <HorizontalStackLayout.GestureRecognizers> <PanGestureRecognizer PanUpdated="OnPanUpdated" /> </HorizontalStackLayout.GestureRecognizers> <local:StarView x:Name="Star1" /> <local:StarView x:Name="Star2" /> <local:StarView x:Name="Star3" /> <local:StarView x:Name="Star4" /> <local:StarView x:Name="Star5" /> </HorizontalStackLayout> </ContentView.Content> </ContentView>
3. 处理滑动逻辑与状态更新
后台代码计算滑动位置对应的评分,实时更新每个星星的状态:
public partial class SwipeRatingControl : ContentView { public static readonly BindableProperty RatingProperty = BindableProperty.Create(nameof(Rating), typeof(double), typeof(SwipeRatingControl), 0.0, BindingMode.TwoWay); public double Rating { get => (double)GetValue(RatingProperty); set => SetValue(RatingProperty, value); } private double _totalWidth; private List<StarView> _stars; public SwipeRatingControl() { InitializeComponent(); _stars = new List<StarView> { Star1, Star2, Star3, Star4, Star5 }; SizeChanged += OnSizeChanged; } private void OnSizeChanged(object sender, EventArgs e) { _totalWidth = StarsContainer.Width; } private void OnPanUpdated(object sender, PanUpdatedEventArgs e) { if (_totalWidth <= 0) return; switch (e.StatusType) { case GestureStatus.Running: var relativeX = Math.Clamp(e.TotalX / _totalWidth, 0, 1); Rating = Math.Round(relativeX * 5 * 2) / 2; // 强制保留0.5步长 UpdateStars(); break; } } private void UpdateStars() { for (int i = 0; i < _stars.Count; i++) { var starRank = i + 1; if (Rating >= starRank) { _stars[i].State = StarFillState.Full; } else if (Rating >= starRank - 0.5) { _stars[i].State = StarFillState.Half; } else { _stars[i].State = StarFillState.Empty; } } } }
4. 业务层使用控件
在页面中直接引用控件,通过绑定获取用户输入的评分:
<local:SwipeRatingControl Rating="{Binding UserSelectedRating}" />
平台适配注意事项
- 确保星星图片(star_empty.png、star_half.png、star_full.png)已正确放置在Android和iOS的资源目录中
- iOS上可通过调整
PanGestureRecognizer.MinimumDistance属性,避免滑动误触 - Android上需确保
HorizontalStackLayout.InputTransparent为false,保证手势能被正常捕获
内容的提问来源于stack exchange,提问作者Alexander Petrov
相关产品推荐
相关产品推荐

