diff --git a/Billing.Shared/Billing.Shared.projitems b/Billing.Shared/Billing.Shared.projitems index 7572722..ddb5bab 100644 --- a/Billing.Shared/Billing.Shared.projitems +++ b/Billing.Shared/Billing.Shared.projitems @@ -51,6 +51,10 @@ BillPage.xaml + + IconSelectPage.xaml + Code + SettingPage.xaml @@ -86,4 +90,9 @@ MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + \ No newline at end of file diff --git a/Billing.Shared/Languages/en.xml b/Billing.Shared/Languages/en.xml index 8d63e7d..bbabe70 100644 --- a/Billing.Shared/Languages/en.xml +++ b/Billing.Shared/Languages/en.xml @@ -31,4 +31,5 @@ Credit Card Debit Card Electronic Account + Icon Selection \ No newline at end of file diff --git a/Billing.Shared/Languages/zh-CN.xml b/Billing.Shared/Languages/zh-CN.xml index f0ce9f2..5441ff3 100644 --- a/Billing.Shared/Languages/zh-CN.xml +++ b/Billing.Shared/Languages/zh-CN.xml @@ -31,4 +31,5 @@ 信用卡 储蓄卡 电子账户 + 图标选择 \ No newline at end of file diff --git a/Billing.Shared/Themes/BaseTheme.cs b/Billing.Shared/Themes/BaseTheme.cs index c82218b..f19568f 100644 --- a/Billing.Shared/Themes/BaseTheme.cs +++ b/Billing.Shared/Themes/BaseTheme.cs @@ -9,6 +9,7 @@ namespace Billing.Themes public const string CascadiaFontBold = nameof(CascadiaFontBold); public const string RobotoCondensedFontRegular = nameof(RobotoCondensedFontRegular); public const string RobotoCondensedFontBold = nameof(RobotoCondensedFontBold); + public const string BrandsFontRegular = nameof(BrandsFontRegular); public const string WindowBackgroundColor = nameof(WindowBackgroundColor); public const string OptionTintColor = nameof(OptionTintColor); @@ -33,6 +34,7 @@ namespace Billing.Themes Add(CascadiaFontBold, Definition.GetCascadiaBoldFontFamily()); Add(RobotoCondensedFontRegular, Definition.GetRobotoCondensedRegularFontFamily()); Add(RobotoCondensedFontBold, Definition.GetRobotoCondensedBoldFontFamily()); + Add(BrandsFontRegular, Definition.GetBrandsFontFamily()); Add(PrimaryColor, PrimaryMauiColor); Add(SecondaryColor, SecondaryMauiColor); diff --git a/Billing.Shared/UI/Converters.cs b/Billing.Shared/UI/Converters.cs index 0712086..6202e8b 100644 --- a/Billing.Shared/UI/Converters.cs +++ b/Billing.Shared/UI/Converters.cs @@ -1,6 +1,7 @@ using Billing.Languages; using Billing.Models; using System; +using System.Collections.Generic; using System.Globalization; using Xamarin.Forms; @@ -95,4 +96,62 @@ namespace Billing.UI return value; } } + + public class IconConverter : IValueConverter + { + public static readonly Dictionary IconPreset = new() + { + { "alipay", "\uf642" }, + { "appstore", "\uf370" }, + { "apple-pay", "\uf416" }, + { "btc", "\uf15a" }, + { "jcb", "\uf24b" }, + { "master-card", "\uf1f1" }, + { "visa", "\uf1f0" }, + { "g-pay", "\ue079" }, + { "paypal", "\uf1ed" }, + { "qq", "\uf1d6" }, + { "steam", "\uf1b6" }, + { "uber", "\uf402" }, + { "weixin", "\uf1d7" }, + { "youtube", "\uf167" } + }; + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is ImageSource source) + { + return source; + } + if (value is string name) + { + if (name.StartsWith("#brand#")) + { + var key = name[7..]; + if (!IconPreset.TryGetValue(key, out var glyph)) + { + if (!int.TryParse(key, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int i)) + { + return ImageSource.FromFile(BaseModel.ICON_DEFAULT); + } + glyph = char.ConvertFromUtf32(i); + } + return new FontImageSource + { + FontFamily = Definition.GetBrandsFontFamily(), + Size = 20, + Glyph = glyph, + Color = Color.Black + }; + } + return ImageSource.FromFile(name); + } + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return value; + } + } } \ No newline at end of file diff --git a/Billing.Shared/UI/Definition.cs b/Billing.Shared/UI/Definition.cs index 29bc40a..2c5695b 100644 --- a/Billing.Shared/UI/Definition.cs +++ b/Billing.Shared/UI/Definition.cs @@ -9,6 +9,7 @@ namespace Billing.UI public static partial string GetCascadiaBoldFontFamily(); public static partial string GetRobotoCondensedRegularFontFamily(); public static partial string GetRobotoCondensedBoldFontFamily(); + public static partial string GetBrandsFontFamily(); } public static class ExtensionHelper diff --git a/Billing.Shared/UI/GroupStackLayout.cs b/Billing.Shared/UI/GroupStackLayout.cs index 0ae2020..90e4eaf 100644 --- a/Billing.Shared/UI/GroupStackLayout.cs +++ b/Billing.Shared/UI/GroupStackLayout.cs @@ -12,6 +12,8 @@ namespace Billing.UI public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(nameof(ItemTemplate), typeof(DataTemplate), typeof(GroupStackLayout)); public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(GroupStackLayout), propertyChanged: OnItemsSourcePropertyChanged); public static readonly BindableProperty SpacingProperty = BindableProperty.Create(nameof(Spacing), typeof(double), typeof(GroupStackLayout), defaultValue: 4d); + public static readonly BindableProperty RowHeightProperty = BindableProperty.Create(nameof(RowHeight), typeof(double), typeof(GroupStackLayout), defaultValue: 32d); + public static readonly BindableProperty GroupHeightProperty = BindableProperty.Create(nameof(GroupHeight), typeof(double), typeof(GroupStackLayout), defaultValue: 24d); public DataTemplate GroupHeaderTemplate { @@ -33,6 +35,16 @@ namespace Billing.UI get => (double)GetValue(SpacingProperty); set => SetValue(SpacingProperty, value); } + public double RowHeight + { + get => (double)GetValue(RowHeightProperty); + set => SetValue(RowHeightProperty, value); + } + public double GroupHeight + { + get => (double)GetValue(GroupHeightProperty); + set => SetValue(GroupHeightProperty, value); + } private static void OnItemsSourcePropertyChanged(BindableObject obj, object old, object @new) { @@ -40,14 +52,14 @@ namespace Billing.UI stack.lastWidth = -1; if (@new == null) { - stack.cachedLayout.Clear(); + //stack.cachedLayout.Clear(); stack.Children.Clear(); stack.InvalidateLayout(); } else if (@new is IList list) { stack.freezed = true; - stack.cachedLayout.Clear(); + //stack.cachedLayout.Clear(); stack.Children.Clear(); var groupTemplate = stack.GroupHeaderTemplate; var itemTemplate = stack.ItemTemplate; @@ -91,7 +103,7 @@ namespace Billing.UI } } - private readonly Dictionary cachedLayout = new(); + //private readonly Dictionary cachedLayout = new(); private bool freezed; private double lastWidth = -1; @@ -114,27 +126,40 @@ namespace Billing.UI return; } var spacing = Spacing; - var lastHeight = 0.0; + var lastHeight = 0d; + var rowHeight = RowHeight; + var groupHeight = GroupHeight; foreach (var item in Children) { - var measured = item.Measure(width, height, MeasureFlags.IncludeMargins); - var rect = new Rectangle( - 0, lastHeight, width, - measured.Request.Height); - if (cachedLayout.TryGetValue(item, out var v)) + //var measured = item.Measure(width, height, MeasureFlags.IncludeMargins); + //var rect = new Rectangle( + // 0, lastHeight, width, + // measured.Request.Height); + //if (cachedLayout.TryGetValue(item, out var v)) + //{ + // if (v != rect) + // { + // cachedLayout[item] = rect; + // item.Layout(rect); + // } + //} + //else + //{ + // cachedLayout.Add(item, rect); + // item.Layout(rect); + //} + double itemHeight; + if (item.BindingContext is IList) { - if (v != rect) - { - cachedLayout[item] = rect; - item.Layout(rect); - } + itemHeight = groupHeight; } else { - cachedLayout.Add(item, rect); - item.Layout(rect); + itemHeight = rowHeight; } - lastHeight += rect.Height + spacing; + var rect = new Rectangle(0, lastHeight, width, itemHeight); + item.Layout(rect); + lastHeight += itemHeight + spacing; } } @@ -146,11 +171,21 @@ namespace Billing.UI } lastWidth = widthConstraint; var spacing = Spacing; - var lastHeight = 0.0; + var lastHeight = 0d; + var rowHeight = RowHeight; + var groupHeight = GroupHeight; foreach (var item in Children) { - var measured = item.Measure(widthConstraint, heightConstraint, MeasureFlags.IncludeMargins); - lastHeight += measured.Request.Height + spacing; + //var measured = item.Measure(widthConstraint, heightConstraint, MeasureFlags.IncludeMargins); + //lastHeight += measured.Request.Height + spacing; + if (item.BindingContext is IList) + { + lastHeight += groupHeight + spacing; + } + else + { + lastHeight = rowHeight + spacing; + } } lastSizeRequest = new SizeRequest(new Size(widthConstraint, lastHeight)); return lastSizeRequest; diff --git a/Billing.Shared/UI/ItemSelectPage.cs b/Billing.Shared/UI/ItemSelectPage.cs index 52d86f3..32ba843 100644 --- a/Billing.Shared/UI/ItemSelectPage.cs +++ b/Billing.Shared/UI/ItemSelectPage.cs @@ -1,6 +1,5 @@ using Billing.Themes; using System; -using System.Collections; using System.Collections.Generic; using Xamarin.Forms; @@ -24,7 +23,7 @@ namespace Billing.UI Spacing = 10, Children = { - new Image + new TintImage { WidthRequest = 22, HeightRequest = 22, diff --git a/Billing.Shared/UI/OptionsCells.cs b/Billing.Shared/UI/OptionsCells.cs index 10a664c..b9f1a1a 100644 --- a/Billing.Shared/UI/OptionsCells.cs +++ b/Billing.Shared/UI/OptionsCells.cs @@ -203,8 +203,9 @@ namespace Billing.UI HorizontalOptions = LayoutOptions.End, Children = { - new Image + new TintImage { + WidthRequest = 26, HeightRequest = 20, HorizontalOptions = LayoutOptions.End, VerticalOptions = LayoutOptions.Center, diff --git a/Billing.Shared/UI/WrapLayout.cs b/Billing.Shared/UI/WrapLayout.cs index 20ef995..fa51728 100644 --- a/Billing.Shared/UI/WrapLayout.cs +++ b/Billing.Shared/UI/WrapLayout.cs @@ -8,8 +8,8 @@ namespace Billing.UI public class WrapLayout : Layout { public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(WrapLayout), propertyChanged: OnItemsSourcePropertyChanged); - public static readonly BindableProperty ColumnSpacingProperty = BindableProperty.Create(nameof(ColumnSpacing), typeof(double), typeof(WrapLayout), defaultValue: 5.0, propertyChanged: (obj, _, _) => ((WrapLayout)obj).InvalidateLayout()); - public static readonly BindableProperty RowSpacingProperty = BindableProperty.Create(nameof(RowSpacing), typeof(double), typeof(WrapLayout), defaultValue: 5.0, propertyChanged: (obj, _, _) => ((WrapLayout)obj).InvalidateLayout()); + public static readonly BindableProperty ColumnSpacingProperty = BindableProperty.Create(nameof(ColumnSpacing), typeof(double), typeof(WrapLayout), defaultValue: 4d, propertyChanged: (obj, _, _) => ((WrapLayout)obj).InvalidateLayout()); + public static readonly BindableProperty RowSpacingProperty = BindableProperty.Create(nameof(RowSpacing), typeof(double), typeof(WrapLayout), defaultValue: 4d, propertyChanged: (obj, _, _) => ((WrapLayout)obj).InvalidateLayout()); private static void OnItemsSourcePropertyChanged(BindableObject obj, object old, object @new) { @@ -177,14 +177,14 @@ namespace Billing.UI { cellSize.Width = (width - columnSpacing * (columns - 1)) / columns; } - if (double.IsPositiveInfinity(height)) + //if (double.IsPositiveInfinity(height)) { cellSize.Height = maxChildSize.Height; } - else - { - cellSize.Height = (height - RowSpacing * (rows - 1)) / rows; - } + //else + //{ + // cellSize.Height = (height - RowSpacing * (rows - 1)) / rows; + //} layoutData = new LayoutData(visibleChildrenCount, cellSize, rows, columns); } else diff --git a/Billing.Shared/Views/AccountPage.xaml b/Billing.Shared/Views/AccountPage.xaml index 268e29a..c615b84 100644 --- a/Billing.Shared/Views/AccountPage.xaml +++ b/Billing.Shared/Views/AccountPage.xaml @@ -14,6 +14,7 @@ + @@ -55,7 +56,8 @@ - +