fixed progress bar on iOS, merged Horizonal and Vertical into one

This commit is contained in:
bmclane 2023-03-07 17:15:14 -05:00
Родитель aa77989678
Коммит 7139bff917
7 изменённых файлов: 356 добавлений и 270 удалений

Просмотреть файл

@ -154,20 +154,19 @@
TextChanged="OnProgressEndColorEntryTextChanged" />
</StackLayout>
</StackLayout>
<Grid
Grid.Row="3"
ColumnDefinitions="Auto, Auto"
HorizontalOptions="Center"
VerticalOptions="Center">
<controls:ProgressBar
IsVertical="False"
WidthRequest="120"
HeightRequest="18"
x:Name="HorizontalProgressBar"
Margin="12"
HorizontalOptions="Center"
Progress="{Binding Source={x:Reference ValueSlider}, Path=Value}"
Value="{Binding Source={x:Reference ValueSlider}, Path=Value}"
VerticalOptions="Center" />
<controls:ProgressBar
WidthRequest="18"
@ -177,7 +176,7 @@
Grid.Column="1"
Margin="12"
HorizontalOptions="Center"
Progress="{Binding Source={x:Reference ValueSlider}, Path=Value}"
Value="{Binding Source={x:Reference ValueSlider}, Path=Value}"
VerticalOptions="Center" />
</Grid>
</Grid>

Просмотреть файл

@ -32,48 +32,62 @@ public partial class ProgressBarView : ContentPage
}
void UpdateBrushes()
{
var backgroundStartColor = GetColorFromString(BackgroundStartColorEntry.Text);
var backgroundEndColor = GetColorFromString(BackgroundEndColorEntry.Text);
{
var backgroundStartColor = GetColorFromString(BackgroundStartColorEntry.Text);
var backgroundEndColor = GetColorFromString(BackgroundEndColorEntry.Text);
if (backgroundStartColor != null && backgroundEndColor != null)
{
BackgroundStartColorEntry.BackgroundColor = backgroundStartColor;
BackgroundEndColorEntry.BackgroundColor = backgroundEndColor;
if (backgroundStartColor != null && backgroundEndColor != null)
{
HorizontalProgressBar.StrokeBrush = VerticalProgressBar.StrokeBrush = new LinearGradientBrush
{
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 0),
GradientStops = new GradientStopCollection
{
new Microsoft.Maui.Controls.GradientStop { Color = backgroundStartColor, Offset = 0 },
new Microsoft.Maui.Controls.GradientStop { Color = backgroundEndColor, Offset = 1 }
}
};
}
var progressStartColor = GetColorFromString(ProgressStartEntry.Text);
var progressEndColor = GetColorFromString(ProgressEndEntry.Text);
HorizontalProgressBar.Background = VerticalProgressBar.Background = new LinearGradientBrush
{
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 0),
GradientStops = new GradientStopCollection
{
new Microsoft.Maui.Controls.GradientStop { Color = backgroundStartColor, Offset = 0 },
new Microsoft.Maui.Controls.GradientStop { Color = backgroundEndColor, Offset = 1 }
}
};
}
var progressStartColor = GetColorFromString(ProgressStartEntry.Text);
var progressEndColor = GetColorFromString(ProgressEndEntry.Text);
if (progressStartColor != null && progressEndColor != null)
{
HorizontalProgressBar.ProgressBrush = VerticalProgressBar.ProgressBrush = new LinearGradientBrush
{
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 0),
GradientStops = new GradientStopCollection
{
new Microsoft.Maui.Controls.GradientStop { Color = progressStartColor, Offset = 0 },
new Microsoft.Maui.Controls.GradientStop { Color = progressEndColor, Offset = 1 }
}
};
}
if (progressStartColor != null && progressEndColor != null)
{
ProgressStartEntry.BackgroundColor = progressStartColor;
ProgressEndEntry.BackgroundColor = progressEndColor;
HorizontalProgressBar.ProgressBrush = VerticalProgressBar.ProgressBrush = new LinearGradientBrush
{
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 0),
GradientStops = new GradientStopCollection
{
new Microsoft.Maui.Controls.GradientStop { Color = progressStartColor, Offset = 0 },
new Microsoft.Maui.Controls.GradientStop { Color = progressEndColor, Offset = 1 }
}
};
}
}
Color GetColorFromString(string value)
/*
var backgroundColor = Colors.Gray;
if (backgroundColor != null)
{
HorizontalProgressBar.BackgroundColor = backgroundColor;
VerticalProgressBar.BackgroundColor = backgroundColor;
}
var progressColor = Colors.Red;
if (progressColor != null)
{
HorizontalProgressBar.ProgressColor = progressColor;
VerticalProgressBar.ProgressColor = progressColor;
}*/
}
Color GetColorFromString(string value)
{
if (string.IsNullOrEmpty(value))
return null;
@ -91,14 +105,14 @@ public partial class ProgressBarView : ContentPage
private void stylePicker_SelectedIndexChanged(object sender, EventArgs e)
{
var selectedItem = (sender as Picker).SelectedItem as string;
HorizontalProgressBar.RoundCorners = selectedItem == "Rounded" ? true : false;
VerticalProgressBar.RoundCorners = selectedItem == "Rounded" ? true : false;
}
HorizontalProgressBar.RoundCorners = selectedItem == "Rounded" ? true : false;
VerticalProgressBar.RoundCorners = selectedItem == "Rounded" ? true : false;
}
private void CheckAnimate_CheckedChanged(object sender, CheckedChangedEventArgs e)
{
var isChecked = (sender as CheckBox).IsChecked;
HorizontalProgressBar.EnableAnimations = isChecked;
VerticalProgressBar.EnableAnimations = isChecked;
}
HorizontalProgressBar.EnableAnimations = isChecked;
VerticalProgressBar.EnableAnimations = isChecked;
}
}

Просмотреть файл

@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AlohaKit.Controls
{
public abstract class BaseProgressBarDrawable : IDrawable
{
public Paint BackgroundPaint { get; set; }
public Paint ProgressPaint { get; set; }
public double Progress { get; set; }
public float CornerRadius { get; set; } = 6f;
public ProgressBarStyle Style { get; set; }
public abstract void DrawChart(ICanvas canvas, RectF dirtyRect);
public void Draw(ICanvas canvas, RectF dirtyRect)
{
DrawChart(canvas, dirtyRect);
}
}
}

Просмотреть файл

@ -1,57 +0,0 @@

namespace AlohaKit.Controls
{
public class HorizontalProgressBarDrawable : BaseProgressBarDrawable
{
public override void DrawChart(ICanvas canvas, RectF dirtyRect)
{
canvas.Antialias = true;
DrawTrack(canvas, dirtyRect);
DrawProgress(canvas, dirtyRect);
}
public virtual void DrawTrack(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
canvas.SetFillPaint(BackgroundPaint, dirtyRect);
var x = dirtyRect.X;
var y = (float)(dirtyRect.Height / 2);
var width = dirtyRect.Width;
var height = dirtyRect.Height;
if (Style == ProgressBarStyle.Square)
canvas.FillRectangle(x, y, width, height);
else
canvas.FillRoundedRectangle(x, y, width, height, CornerRadius);
canvas.RestoreState();
}
public virtual void DrawProgress(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
canvas.SetFillPaint(ProgressPaint, dirtyRect);
var x = dirtyRect.X;
var y = (float)(dirtyRect.Height / 2);
var width = dirtyRect.Width;
var height = dirtyRect.Height;
if (Style == ProgressBarStyle.Square)
canvas.FillRectangle(x, y, (float)(width * Progress), height);
else
canvas.FillRoundedRectangle(x, y, (float)(width * Progress), height, CornerRadius);
canvas.RestoreState();
}
}
}

Просмотреть файл

@ -0,0 +1,171 @@

namespace AlohaKit.Controls
{
public class ProgressBarDrawable : IDrawable
{
public Paint StrokePaint { get; set; }
public Paint ProgressPaint { get; set; }
public double Progress { get; set; }
public CornerRadius CornerRadius { get; set; } = 6f;
public ProgressBarStyle Style { get; set; }
public bool IsAnimating { get; set; }
public bool IsVertical { get; set; }
public void DrawChart(ICanvas canvas, RectF dirtyRect)
{
canvas.Antialias = true;
DrawTrack(canvas, dirtyRect);
DrawProgress(canvas, dirtyRect);
}
public void Draw(ICanvas canvas, RectF dirtyRect)
{
DrawChart(canvas, dirtyRect);
}
public virtual void DrawTrack(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
canvas.SetFillPaint(StrokePaint, dirtyRect);
if (Style == ProgressBarStyle.Square)
canvas.FillRectangle(dirtyRect);
else
canvas.FillRoundedRectangle(dirtyRect,
CornerRadius.TopLeft,
CornerRadius.TopRight,
CornerRadius.BottomLeft,
CornerRadius.BottomRight);
canvas.RestoreState();
}
public virtual void DrawProgress(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
RectF rect;
if (IsVertical)
{
var progressHeight = dirtyRect.Height * Progress;
var progressY = dirtyRect.Y + dirtyRect.Height - progressHeight;
rect = new Rect(
dirtyRect.X,
progressY,
dirtyRect.Width,
progressHeight);
}
else
{
rect = new Rect(
dirtyRect.X,
dirtyRect.Y,
dirtyRect.Width * Progress,
dirtyRect.Height);
}
canvas.SetFillPaint(ProgressPaint, dirtyRect);
if (Style == ProgressBarStyle.Square)
canvas.FillRectangle(rect);
else
canvas.FillRoundedRectangle(rect,
CornerRadius.TopLeft,
CornerRadius.TopRight,
CornerRadius.BottomLeft,
CornerRadius.BottomRight);
canvas.RestoreState();
}
/*
public virtual void DrawTrack(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
//canvas.FillColor = StrokeColor;
canvas.SetFillPaint(StrokePaint, dirtyRect);
float x;
float y;
float width;
float height;
if (IsVertical)
{
x = (float)(dirtyRect.Width / 2);
y = dirtyRect.Y;
width = (float)(dirtyRect.Width / 2);
height = dirtyRect.Height;
}
else
{
x = dirtyRect.X;
y = (float)(dirtyRect.Height / 2);
width = dirtyRect.Width;
height = (float)(dirtyRect.Height / 2);
}
if (Style == ProgressBarStyle.Square)
canvas.FillRectangle(x, y, width, height);
else
canvas.FillRoundedRectangle(x, y, width, height, CornerRadius);
canvas.RestoreState();
}
public virtual void DrawProgress(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
//canvas.FillColor = ProgressColor;
float x;
float y;
float width;
float height;
if (IsVertical)
{
x = (float)(dirtyRect.Width / 2);
y = dirtyRect.Y + dirtyRect.Height;
width = (float)(dirtyRect.Width / 2);
height = dirtyRect.Height;
RectF barRect = new RectF(x, y, width, -(float)(height * Progress));
canvas.SetFillPaint(ProgressPaint, barRect);
if (Style == ProgressBarStyle.Square)
canvas.FillRectangle(x, y, width, -(float)(height * Progress));
else
canvas.FillRoundedRectangle(x, y, width, -(float)(height * Progress), CornerRadius);
}
else
{
x = dirtyRect.X;
y = (float)(dirtyRect.Height / 2);
width = dirtyRect.Width;
height = dirtyRect.Height / 2;
canvas.SetFillPaint(ProgressPaint, dirtyRect);
if (Style == ProgressBarStyle.Square)
canvas.FillRectangle(x, y, (float)(width * Progress), height);
else
canvas.FillRoundedRectangle(x, y, (float)(width * Progress), height, CornerRadius);
}
canvas.RestoreState();
}*/
}
}

Просмотреть файл

@ -1,55 +0,0 @@

namespace AlohaKit.Controls
{
public class VerticalProgressBarDrawable : BaseProgressBarDrawable
{
public override void DrawChart(ICanvas canvas, RectF dirtyRect)
{
canvas.Antialias = true;
DrawTrack(canvas, dirtyRect);
DrawProgress(canvas, dirtyRect);
}
public virtual void DrawTrack(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
canvas.SetFillPaint(BackgroundPaint, dirtyRect);
var x = (float)(dirtyRect.Width / 2);
var y = dirtyRect.Y;
var width = dirtyRect.Width;
var height = dirtyRect.Height;
if (Style == ProgressBarStyle.Square)
canvas.FillRectangle(x, y, width, height);
else
canvas.FillRoundedRectangle(x, y, width, height, CornerRadius);
canvas.RestoreState();
}
public virtual void DrawProgress(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
canvas.SetFillPaint(ProgressPaint, dirtyRect);
var x = (float)(dirtyRect.Width / 2);
var y = dirtyRect.Y + dirtyRect.Height;
var width = dirtyRect.Width;
var height = dirtyRect.Height;
if (Style == ProgressBarStyle.Square)
canvas.FillRectangle(x, y, width, -(float)(height * Progress));
else
canvas.FillRoundedRectangle(x, y, width, -(float)(height * Progress), CornerRadius);
canvas.RestoreState();
}
}
}

Просмотреть файл

@ -8,42 +8,44 @@ namespace AlohaKit.Controls
{
public class ProgressBar : GraphicsView
{
protected BaseProgressBarDrawable ProgressBarDrawable { get; set; }
protected ProgressBarDrawable ProgressBarDrawable { get; set; }
private bool IsInitialized = false;
public ProgressBar()
{
if (IsVertical)
{
Drawable = ProgressBarDrawable = new VerticalProgressBarDrawable();
}
}
public ProgressBar()
{
Opacity = 0;
Drawable = ProgressBarDrawable = new ProgressBarDrawable();
Loaded += ProgressBar_Loaded;
public static readonly BindableProperty IsVerticalProperty = BindableProperty.Create(nameof(IsVertical), typeof(bool), typeof(ProgressBar), true,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is ProgressBar progressBar)
{
if ((bool)newValue)
{
progressBar.Drawable = progressBar.ProgressBarDrawable = new VerticalProgressBarDrawable();
}
else
{
progressBar.Drawable = progressBar.ProgressBarDrawable = new HorizontalProgressBarDrawable();
}
}
private void ProgressBar_Loaded(object sender, EventArgs e)
{
ProgressBarDrawable.IsAnimating = true;
IsInitialized = true;
this.FadeTo(1, 1000, Easing.SinIn);
AnimateProgress(Value);
}
progressBar.Invalidate();
}
});
public static readonly BindableProperty IsVerticalProperty = BindableProperty.Create(nameof(IsVertical), typeof(bool), typeof(ProgressBar), false,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is ProgressBar progressBar)
{
progressBar.UpdateIsVertical();
progressBar.Invalidate();
}
});
public bool IsVertical
{
get => (bool)GetValue(IsVerticalProperty);
set => SetValue(IsVerticalProperty, value);
}
public bool IsVertical
{
get => (bool)GetValue(IsVerticalProperty);
set => SetValue(IsVerticalProperty, value);
}
public static readonly BindableProperty EasingProperty = BindableProperty.Create(nameof(Easing), typeof(Easing), typeof(ProgressBar), Easing.BounceOut);
public Easing Easing
public static readonly BindableProperty EasingProperty = BindableProperty.Create(nameof(Easing), typeof(Easing), typeof(ProgressBar), Easing.BounceOut);
public Easing Easing
{
get => (Easing)GetValue(EasingProperty);
set => SetValue(EasingProperty, value);
@ -81,7 +83,7 @@ namespace AlohaKit.Controls
}
public static readonly BindableProperty CornerRadiusProperty =
BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(ProgressBar), 6f,
BindableProperty.Create(nameof(CornerRadius), typeof(CornerRadius), typeof(ProgressBar), new CornerRadius(6f),
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is ProgressBar progressBar)
@ -90,53 +92,74 @@ namespace AlohaKit.Controls
}
});
public float CornerRadius
public CornerRadius CornerRadius
{
get { return (float)GetValue(CornerRadiusProperty); }
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
public static readonly BindableProperty ProgressBrushProperty =
BindableProperty.Create(nameof(ProgressBrush), typeof(Brush), typeof(ProgressBar), new SolidColorBrush(Colors.Blue),
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is ProgressBar progressBar)
{
progressBar.UpdateBrush();
}
});
public static readonly BindableProperty ProgressBrushProperty =
BindableProperty.Create(nameof(ProgressBrush), typeof(Brush), typeof(ProgressBar), new SolidColorBrush(Colors.Blue),
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is ProgressBar progressBar)
{
progressBar.UpdateProgressBrush();
}
});
public Brush ProgressBrush
{
get { return (Brush)GetValue(ProgressBrushProperty); }
set { SetValue(ProgressBrushProperty, value); }
}
public Brush ProgressBrush
{
get { return (Brush)GetValue(ProgressBrushProperty); }
set { SetValue(ProgressBrushProperty, value); }
}
public static readonly BindableProperty ProgressProperty =
BindableProperty.Create(nameof(Progress), typeof(double), typeof(ProgressBar), 0d,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is ProgressBar progressBar)
{
progressBar.UpdateProgress();
}
});
public static readonly BindableProperty StrokeBrushProperty =
BindableProperty.Create(nameof(StrokeBrush), typeof(Brush), typeof(ProgressBar), new SolidColorBrush(Colors.Gray),
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is ProgressBar progressBar)
{
progressBar.UpdateStrokeBrush();
}
});
public double Progress
{
get { return (double)GetValue(ProgressProperty); }
set { SetValue(ProgressProperty, value); }
}
public Brush StrokeBrush
{
get { return (Brush)GetValue(StrokeBrushProperty); }
set { SetValue(StrokeBrushProperty, value); }
}
void AnimateProgress(double progress)
public static readonly BindableProperty ValueProperty =
BindableProperty.Create(nameof(Value), typeof(double), typeof(ProgressBar), 0.0, BindingMode.TwoWay,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is ProgressBar progressBar)
{
progressBar.UpdateValue();
progressBar.ValueChanged?.Invoke(progressBar, new ValueChangedEventArgs((double)oldValue, (double)newValue));
}
});
public double Value
{
get => (double)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
public event EventHandler<ValueChangedEventArgs> ValueChanged;
void AnimateProgress(double progress)
{
var animation = new Animation(v =>
{
ProgressBarDrawable.Progress = v;
Invalidate();
}, 0, progress, easing: Easing);
Invalidate();
animation.Commit(this, "Progress", length: (uint)EasingInterval);
ProgressBarDrawable.IsAnimating = false;
}, 0, progress, easing: Easing);
animation.Commit(this, "Progress", length: (uint)250);
}
protected override void OnParentChanged()
@ -144,24 +167,41 @@ namespace AlohaKit.Controls
base.OnParentChanged();
if (Parent != null)
{
UpdateBrush();
UpdateProgress();
}
{
UpdateIsVertical();
UpdateStrokeBrush();
UpdateProgressBrush();
UpdateValue();
}
}
protected void UpdateBrush()
{
if (ProgressBarDrawable == null)
return;
void UpdateIsVertical()
{
if (ProgressBarDrawable == null)
return;
ProgressBarDrawable.BackgroundPaint = Background;
ProgressBarDrawable.ProgressPaint = ProgressBrush;
ProgressBarDrawable.IsVertical = IsVertical;
Invalidate();
}
Invalidate();
}
void UpdateStrokeBrush()
{
if (ProgressBarDrawable == null)
return;
protected void UpdateCornerRadius()
ProgressBarDrawable.StrokePaint = StrokeBrush;
Invalidate();
}
void UpdateProgressBrush()
{
if (ProgressBarDrawable == null)
return;
ProgressBarDrawable.ProgressPaint = ProgressBrush;
Invalidate();
}
protected void UpdateCornerRadius()
{
if (ProgressBarDrawable == null)
return;
@ -180,19 +220,16 @@ namespace AlohaKit.Controls
Invalidate();
}
protected void UpdateProgress()
protected void UpdateValue()
{
if (ProgressBarDrawable == null)
return;
if (EnableAnimations)
AnimateProgress(Progress);
else
{
ProgressBarDrawable.Progress = Progress;
Invalidate();
}
}
ProgressBarDrawable.Progress = Value;
if (!ProgressBarDrawable.IsAnimating && IsInitialized)
AnimateProgress(Value);
}
}
}