【MAUI】自定义块状进度控件

发布于:2025-04-15 ⋅ 阅读:(38) ⋅ 点赞:(0)

文章目录


在这里插入图片描述

XAML

    <VerticalStackLayout>
        <Label x:Name="ProgressLable" TextColor="#A6FFFFFF" FontSize="14" Margin="26,0"></Label>
        <Grid x:Name="ProgressGrid" HorizontalOptions="Center" VerticalOptions="Center" Padding="0" BackgroundColor="Transparent">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <!-- 动态生成列定义 -->
            </Grid.ColumnDefinitions>
            <CollectionView x:Name="Items" ItemsLayout="HorizontalList" Margin="0,4,0,32" >
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <BoxView  CornerRadius="1" Grid.Row="0" Grid.Column="{Binding ColumnIndex}"
                             WidthRequest="{Binding BlockWidth}"
                             HeightRequest="{Binding BlockHeight}"
                             HorizontalOptions="Center" VerticalOptions="Center"
                             BackgroundColor="{Binding Color}" />
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </Grid>
    </VerticalStackLayout>

.CS

public partial class LumpProgressIndicator : ContentViewBase<LumpProgressIndicatorViewModel>
{
    public List<BlockItem> BlockItems { get; set; }
    public static double BlockWidth { get; set; }
    public static double BlockHeight { get; set; } = 6;
    public static double BlockSpacing { get; set; } = 5;

    public static double screenWidth { get; set; }
    public static double screenHeight { get; set; }
    public static double progressBarWidth { get; set; }

    public static int curIndexTemp { get; set; }
    #region 可绑定属性

    /// <summary>
    /// 当前进度
    /// </summary>
    public static readonly BindableProperty CurIndexProperty =
        BindableProperty.Create(
            propertyName: nameof(CurIndex),
            returnType: typeof(int),
            declaringType: typeof(LumpProgressIndicator),
            defaultBindingMode: BindingMode.TwoWay,
            propertyChanged: CurIndexPropertyChanged);

    public int CurIndex
    {
        get { return (int)base.GetValue(CurIndexProperty); }
        set { base.SetValue(CurIndexProperty, value); }
    }

    private static void CurIndexPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        ReDraw((LumpProgressIndicator)bindable, oldValue, newValue, false);
    }

    /// <summary>
    /// 总数
    /// </summary>
    public static readonly BindableProperty CountProperty =
    BindableProperty.Create(
        propertyName: nameof(Count),
        returnType: typeof(int),
        declaringType: typeof(LumpProgressIndicator),
        defaultBindingMode: BindingMode.TwoWay,
        propertyChanged: CountPropertyChanged);

    public int Count
    {
        get { return (int)base.GetValue(CountProperty); }
        set { base.SetValue(CountProperty, value); }
    }

    private static void CountPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        ReDraw((LumpProgressIndicator)bindable, oldValue, newValue, true);
    }
    #endregion
    private int currentQuestionIndex = 0;
    private int totalQuestions = 5;
    private List<BoxView> blockItems = new List<BoxView>();
    public LumpProgressIndicator()
    {
        CalculateBlockDimensions();
        InitializeComponent();
        //this.WhenActivated(d =>
        //{
        //    //this.OneWayBind(ViewModel, vm => vm.ReportVM, v => v.ReportPage.ViewModel).DisposeWith(d);
        //});

    }
    private void CalculateBlockDimensions()
    {
        // 计算每个块的宽度和高度
        screenWidth = App.Current.MainPage.Width;
        screenHeight = App.Current.MainPage.Height;
        // 假设进度条总宽度为屏幕宽度的 85%
        progressBarWidth = screenWidth * 0.85;
        // 设置块的高度
        BlockHeight = 6;
        BlockSpacing = 5;
    }
    public class BlockItem
    {
        public int ColumnIndex { get; set; }
        public double BlockWidth { get; set; }
        public double BlockHeight { get; set; }
        public string Color { get; set; }
    }
    public static int size = 1;
    private static void ReDraw(LumpProgressIndicator lumpProgressIndicator, object oldValue, object newValue, bool last)
    {
        //CurIndexPropertyChanged先执行CountPropertyChanged后执行
        if (!last)
        {
            curIndexTemp = (int)newValue;
        }
        else
        {
            LumpProgressIndicator.size = (int)newValue;
        }
        var value_new = (int)newValue;
        lumpProgressIndicator.ProgressLable.Text = $"当前进度({curIndexTemp.ToString()}/{LumpProgressIndicator.size.ToString()})";
        lumpProgressIndicator.ProgressLable.Margin = new Thickness(left: progressBarWidth * 0.07 - BlockSpacing, top: 0, right: 0, bottom: 5);
        // 每个块的宽度为进度条总宽度减去所有间隔后除以块的数量 
        BlockWidth = (progressBarWidth -  BlockSpacing) / LumpProgressIndicator.size;
        int size = LumpProgressIndicator.size * 2 - 1;
        for (int i = 0; i < size; i++)
        {
            lumpProgressIndicator.ProgressGrid.ColumnDefinitions.Add(
                            new ColumnDefinition { Width = GridLength.Auto }
                );
        }

        List<BlockItem> BlockItems = new List<BlockItem>();
        int loop = LumpProgressIndicator.size * 2 - 1;
        for (int i = 1; i <= loop; i++)
        {
            BlockItem temp = new BlockItem();
            temp.ColumnIndex = i - 1;
            temp.BlockHeight = BlockHeight;

            if (i % 2 == 0)
            {
                temp.BlockWidth = BlockSpacing;
                temp.Color = "Transparent";
            }
            else
            {
                int index_temp = curIndexTemp * 2 - 1;
                if (i > index_temp)
                {
                    temp.BlockWidth = BlockWidth;
                    temp.Color = "#FF3C3E58";
                }
                else
                {
                    temp.BlockWidth = BlockWidth;
                    temp.Color = "#FF6E73FF";
                }
            }
            BlockItems.Add(temp);
        }
        lumpProgressIndicator.Items.ItemsSource = BlockItems;
    }
}

使用

<view:LumpProgressIndicator CurIndex="1" x:Name="lumpProgressIndicator" Count="6" Margin="0,20,0,8"></view:LumpProgressIndicator>