rename from Pixiview to Gallery
This commit is contained in:
193
Gallery/UI/AdaptedPage.cs
Normal file
193
Gallery/UI/AdaptedPage.cs
Normal file
@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using Gallery.UI.Theme;
|
||||
using Gallery.Utils;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI
|
||||
{
|
||||
public class AdaptedPage : ContentPage
|
||||
{
|
||||
public static readonly BindableProperty PageTopMarginProperty = BindableProperty.Create(
|
||||
nameof(PageTopMargin), typeof(Thickness), typeof(AdaptedPage));
|
||||
public static readonly BindableProperty PanelTopMarginProperty = BindableProperty.Create(
|
||||
nameof(PanelTopMargin), typeof(Thickness), typeof(AdaptedPage));
|
||||
|
||||
public Thickness PageTopMargin
|
||||
{
|
||||
get => (Thickness)GetValue(PageTopMarginProperty);
|
||||
protected set => SetValue(PageTopMarginProperty, value);
|
||||
}
|
||||
public Thickness PanelTopMargin
|
||||
{
|
||||
get => (Thickness)GetValue(PanelTopMarginProperty);
|
||||
protected set => SetValue(PanelTopMarginProperty, value);
|
||||
}
|
||||
|
||||
public event EventHandler Load;
|
||||
public event EventHandler Unload;
|
||||
|
||||
protected static readonly bool isPhone = DeviceInfo.Idiom == DeviceIdiom.Phone;
|
||||
|
||||
public AdaptedPage()
|
||||
{
|
||||
SetDynamicResource(Screen.StatusBarStyleProperty, ThemeBase.StatusBarStyle);
|
||||
Shell.SetNavBarHasShadow(this, true);
|
||||
}
|
||||
|
||||
public virtual void OnLoad()
|
||||
{
|
||||
Load?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public virtual void OnUnload()
|
||||
{
|
||||
Unload?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#if __IOS__
|
||||
public virtual void OnOrientationChanged(bool landscape)
|
||||
{
|
||||
var oldMargin = PageTopMargin;
|
||||
var oldPanelMargin = PanelTopMargin;
|
||||
Thickness newMargin;
|
||||
Thickness newPanelMargin;
|
||||
if (StyleDefinition.IsFullscreenDevice)
|
||||
{
|
||||
var iPhone12 =
|
||||
#if DEBUG
|
||||
DeviceInfo.Name.StartsWith("iPhone 12") ||
|
||||
#endif
|
||||
DeviceInfo.Model.StartsWith("iPhone13,");
|
||||
|
||||
newMargin = landscape ?
|
||||
AppShell.NavigationBarOffset :
|
||||
AppShell.TotalBarOffset;
|
||||
newPanelMargin = landscape ?
|
||||
AppShell.HalfNavigationBarOffset :
|
||||
AppShell.NavigationBarOffset;
|
||||
}
|
||||
else if (isPhone)
|
||||
{
|
||||
newMargin = landscape ?
|
||||
StyleDefinition.TopOffset32 :
|
||||
AppShell.TotalBarOffset;
|
||||
newPanelMargin = landscape ?
|
||||
StyleDefinition.TopOffset16 :
|
||||
StyleDefinition.TopOffset32;
|
||||
}
|
||||
else
|
||||
{
|
||||
// iPad
|
||||
newMargin = AppShell.TotalBarOffset;
|
||||
newPanelMargin = StyleDefinition.TopOffset37;
|
||||
}
|
||||
if (oldMargin != newMargin)
|
||||
{
|
||||
PageTopMargin = newMargin;
|
||||
OnPageTopMarginChanged(oldMargin, newMargin);
|
||||
}
|
||||
if (oldPanelMargin != newPanelMargin)
|
||||
{
|
||||
PanelTopMargin = newPanelMargin;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnPageTopMarginChanged(Thickness old, Thickness @new) { }
|
||||
|
||||
protected override void OnSizeAllocated(double width, double height)
|
||||
{
|
||||
base.OnSizeAllocated(width, height);
|
||||
OnOrientationChanged(width > height);
|
||||
}
|
||||
|
||||
protected void AnimateToMargin(View element, Thickness margin, bool animate = true)
|
||||
{
|
||||
var m = margin;
|
||||
var start = element.Margin.Top - m.Top;
|
||||
#if DEBUG
|
||||
if (start != 0)
|
||||
{
|
||||
App.DebugPrint($"{element.GetType()}, margin-top from {element.Margin.Top} to {margin.Top}");
|
||||
}
|
||||
#endif
|
||||
element.Margin = m;
|
||||
if (start > 0 && animate)
|
||||
{
|
||||
ViewExtensions.CancelAnimations(element);
|
||||
element.Animate("margin", top =>
|
||||
{
|
||||
element.TranslationY = top;
|
||||
},
|
||||
start, 0,
|
||||
#if DEBUG
|
||||
length: 500,
|
||||
#else
|
||||
length: 300,
|
||||
#endif
|
||||
easing: Easing.SinInOut,
|
||||
finished: (v, r) =>
|
||||
{
|
||||
element.TranslationY = 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
protected void Start(Action action)
|
||||
{
|
||||
if (Tap.IsBusy)
|
||||
{
|
||||
#if LOG
|
||||
App.DebugPrint("gesture recognizer is now busy...");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
using (Tap.Start())
|
||||
{
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
private class Tap : IDisposable
|
||||
{
|
||||
public static bool IsBusy
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (sync)
|
||||
{
|
||||
return _instance?.isBusy == true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly object sync = new object();
|
||||
private static readonly Tap _instance = new Tap();
|
||||
|
||||
private Tap() { }
|
||||
|
||||
public static Tap Start()
|
||||
{
|
||||
lock (sync)
|
||||
{
|
||||
_instance.isBusy = true;
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
private bool isBusy = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
isBusy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ThicknessEventArgs : EventArgs
|
||||
{
|
||||
public Thickness OldMargin { get; set; }
|
||||
public Thickness NewMargin { get; set; }
|
||||
}
|
||||
}
|
8
Gallery/UI/BlurryPanel.cs
Executable file
8
Gallery/UI/BlurryPanel.cs
Executable file
@ -0,0 +1,8 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI
|
||||
{
|
||||
public class BlurryPanel : ContentView
|
||||
{
|
||||
}
|
||||
}
|
57
Gallery/UI/CardView.cs
Executable file
57
Gallery/UI/CardView.cs
Executable file
@ -0,0 +1,57 @@
|
||||
using Gallery.Illust;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI
|
||||
{
|
||||
public class CardView : ContentView
|
||||
{
|
||||
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(
|
||||
nameof(CornerRadius), typeof(float), typeof(CardView));
|
||||
public static readonly BindableProperty ShadowColorProperty = BindableProperty.Create(
|
||||
nameof(ShadowColor), typeof(Color), typeof(CardView));
|
||||
public static readonly BindableProperty ShadowRadiusProperty = BindableProperty.Create(
|
||||
nameof(ShadowRadius), typeof(float), typeof(CardView), 3f);
|
||||
public static readonly BindableProperty ShadowOffsetProperty = BindableProperty.Create(
|
||||
nameof(ShadowOffset), typeof(Size), typeof(CardView));
|
||||
public static readonly BindableProperty RankProperty = BindableProperty.Create(
|
||||
nameof(Rank), typeof(int), typeof(CardView));
|
||||
|
||||
public float CornerRadius
|
||||
{
|
||||
get => (float)GetValue(CornerRadiusProperty);
|
||||
set => SetValue(CornerRadiusProperty, value);
|
||||
}
|
||||
public Color ShadowColor
|
||||
{
|
||||
get => (Color)GetValue(ShadowColorProperty);
|
||||
set => SetValue(ShadowColorProperty, value);
|
||||
}
|
||||
public float ShadowRadius
|
||||
{
|
||||
get => (float)GetValue(ShadowRadiusProperty);
|
||||
set => SetValue(ShadowRadiusProperty, value);
|
||||
}
|
||||
public Size ShadowOffset
|
||||
{
|
||||
get => (Size)GetValue(ShadowOffsetProperty);
|
||||
set => SetValue(ShadowOffsetProperty, value);
|
||||
}
|
||||
public int Rank
|
||||
{
|
||||
get => (int)GetValue(RankProperty);
|
||||
set => SetValue(RankProperty, value);
|
||||
}
|
||||
|
||||
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
if (BindingContext is IllustItem illust &&
|
||||
illust.Width > 0 &&
|
||||
illust.ImageHeight.IsAuto)
|
||||
{
|
||||
illust.ImageHeight = widthConstraint * illust.Height / illust.Width;
|
||||
}
|
||||
return base.OnMeasure(widthConstraint, heightConstraint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
68
Gallery/UI/CircleUIs.cs
Executable file
68
Gallery/UI/CircleUIs.cs
Executable file
@ -0,0 +1,68 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI
|
||||
{
|
||||
public class CircleImage : Image { }
|
||||
|
||||
public class RoundImage : Image
|
||||
{
|
||||
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(
|
||||
nameof(CornerRadius), typeof(float), typeof(RoundImage));
|
||||
public static readonly BindableProperty CornerMasksProperty = BindableProperty.Create(
|
||||
nameof(CornerMasks), typeof(CornerMask), typeof(RoundImage));
|
||||
|
||||
public float CornerRadius
|
||||
{
|
||||
get => (float)GetValue(CornerRadiusProperty);
|
||||
set => SetValue(CornerRadiusProperty, value);
|
||||
}
|
||||
public CornerMask CornerMasks
|
||||
{
|
||||
get => (CornerMask)GetValue(CornerMasksProperty);
|
||||
set => SetValue(CornerMasksProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public enum CornerMask
|
||||
{
|
||||
None = 0,
|
||||
|
||||
LeftTop = 1,
|
||||
RightTop = 2,
|
||||
LeftBottom = 4,
|
||||
RightBottom = 8,
|
||||
|
||||
Top = LeftTop | RightTop, // 3
|
||||
Left = LeftTop | LeftBottom, // 5
|
||||
Slash = RightTop | LeftBottom, // 6
|
||||
BackSlash = LeftTop | RightBottom, // 9
|
||||
Right = RightTop | RightBottom, // 10
|
||||
Bottom = LeftBottom | RightBottom, // 12
|
||||
|
||||
ExceptRightBottom = LeftTop | RightTop | LeftBottom, // 7
|
||||
ExceptLeftBottom = LeftTop | RightTop | RightBottom, // 11
|
||||
ExceptRightTop = LeftTop | LeftBottom | RightBottom, // 13
|
||||
ExceptLeftTop = RightTop | LeftBottom | RightBottom, // 14
|
||||
|
||||
All = LeftTop | RightTop | LeftBottom | RightBottom // 15
|
||||
}
|
||||
|
||||
public class RoundLabel : Label
|
||||
{
|
||||
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(
|
||||
nameof(CornerRadius), typeof(float), typeof(RoundLabel));
|
||||
public static new readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(
|
||||
nameof(BackgroundColor), typeof(Color), typeof(RoundLabel), Color.Transparent);
|
||||
|
||||
public float CornerRadius
|
||||
{
|
||||
get => (float)GetValue(CornerRadiusProperty);
|
||||
set => SetValue(CornerRadiusProperty, value);
|
||||
}
|
||||
public new Color BackgroundColor
|
||||
{
|
||||
get => (Color)GetValue(BackgroundColorProperty);
|
||||
set => SetValue(BackgroundColorProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
269
Gallery/UI/FlowLayout.cs
Executable file
269
Gallery/UI/FlowLayout.cs
Executable file
@ -0,0 +1,269 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI
|
||||
{
|
||||
public class FlowLayout : Layout<View>
|
||||
{
|
||||
public static readonly BindableProperty ColumnProperty = BindableProperty.Create(
|
||||
nameof(Column), typeof(int), typeof(FlowLayout), 2, propertyChanged: OnColumnPropertyChanged);
|
||||
public static readonly BindableProperty RowSpacingProperty = BindableProperty.Create(
|
||||
nameof(RowSpacing), typeof(double), typeof(FlowLayout), 10.0);
|
||||
public static readonly BindableProperty ColumnSpacingProperty = BindableProperty.Create(
|
||||
nameof(ColumnSpacing), typeof(double), typeof(FlowLayout), 10.0);
|
||||
|
||||
private static void OnColumnPropertyChanged(BindableObject obj, object oldValue, object newValue)
|
||||
{
|
||||
var flowLayout = (FlowLayout)obj;
|
||||
if (oldValue is int column && column != flowLayout.Column)
|
||||
{
|
||||
flowLayout.UpdateChildrenLayout();
|
||||
flowLayout.InvalidateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public int Column
|
||||
{
|
||||
get => (int)GetValue(ColumnProperty);
|
||||
set => SetValue(ColumnProperty, value);
|
||||
}
|
||||
public double RowSpacing
|
||||
{
|
||||
get => (double)GetValue(RowSpacingProperty);
|
||||
set => SetValue(RowSpacingProperty, value);
|
||||
}
|
||||
public double ColumnSpacing
|
||||
{
|
||||
get => (double)GetValue(ColumnSpacingProperty);
|
||||
set => SetValue(ColumnSpacingProperty, value);
|
||||
}
|
||||
|
||||
public event EventHandler<HeightEventArgs> MaxHeightChanged;
|
||||
|
||||
public double ColumnWidth { get; private set; }
|
||||
|
||||
private bool freezed;
|
||||
private double maximumHeight;
|
||||
private readonly Dictionary<View, Rectangle> cachedLayout = new Dictionary<View, Rectangle>();
|
||||
|
||||
protected override void LayoutChildren(double x, double y, double width, double height)
|
||||
{
|
||||
if (freezed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var column = Column;
|
||||
if (column <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var source = ItemsSource;
|
||||
if (source == null || source.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var columnSpacing = ColumnSpacing;
|
||||
var rowSpacing = RowSpacing;
|
||||
|
||||
var columnHeights = new double[column];
|
||||
var columnSpacingTotal = columnSpacing * (column - 1);
|
||||
var columnWidth = (width - columnSpacingTotal) / column;
|
||||
ColumnWidth = columnWidth;
|
||||
|
||||
foreach (var item in Children)
|
||||
{
|
||||
var measured = item.Measure(columnWidth, height, MeasureFlags.IncludeMargins);
|
||||
var col = 0;
|
||||
for (var i = 1; i < column; i++)
|
||||
{
|
||||
if (columnHeights[i] < columnHeights[col])
|
||||
{
|
||||
col = i;
|
||||
}
|
||||
}
|
||||
|
||||
var rect = new Rectangle(
|
||||
col * (columnWidth + columnSpacing),
|
||||
columnHeights[col],
|
||||
columnWidth,
|
||||
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);
|
||||
}
|
||||
columnHeights[col] += measured.Request.Height + rowSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
private double lastWidth = -1;
|
||||
private SizeRequest lastSizeRequest;
|
||||
|
||||
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
var column = Column;
|
||||
if (column <= 0)
|
||||
{
|
||||
return base.OnMeasure(widthConstraint, heightConstraint);
|
||||
}
|
||||
if (lastWidth == widthConstraint)
|
||||
{
|
||||
return lastSizeRequest;
|
||||
}
|
||||
lastWidth = widthConstraint;
|
||||
var columnSpacing = ColumnSpacing;
|
||||
var rowSpacing = RowSpacing;
|
||||
|
||||
var columnHeights = new double[column];
|
||||
var columnSpacingTotal = columnSpacing * (column - 1);
|
||||
var columnWidth = (widthConstraint - columnSpacingTotal) / column;
|
||||
ColumnWidth = columnWidth;
|
||||
|
||||
foreach (var item in Children)
|
||||
{
|
||||
var measured = item.Measure(columnWidth, heightConstraint, MeasureFlags.IncludeMargins);
|
||||
var col = 0;
|
||||
for (var i = 1; i < column; i++)
|
||||
{
|
||||
if (columnHeights[i] < columnHeights[col])
|
||||
{
|
||||
col = i;
|
||||
}
|
||||
}
|
||||
columnHeights[col] += measured.Request.Height + rowSpacing;
|
||||
}
|
||||
maximumHeight = columnHeights.Max();
|
||||
|
||||
if (maximumHeight > 0)
|
||||
{
|
||||
MaxHeightChanged?.Invoke(this, new HeightEventArgs { ContentHeight = maximumHeight });
|
||||
}
|
||||
|
||||
lastSizeRequest = new SizeRequest(new Size(widthConstraint, maximumHeight));
|
||||
return lastSizeRequest;
|
||||
}
|
||||
|
||||
public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(
|
||||
nameof(ItemTemplate), typeof(DataTemplate), typeof(FlowLayout));
|
||||
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
|
||||
nameof(ItemsSource), typeof(IList), typeof(FlowLayout), propertyChanged: OnItemsSourcePropertyChanged);
|
||||
|
||||
public DataTemplate ItemTemplate
|
||||
{
|
||||
get => (DataTemplate)GetValue(ItemTemplateProperty);
|
||||
set => SetValue(ItemTemplateProperty, value);
|
||||
}
|
||||
public IList ItemsSource
|
||||
{
|
||||
get => (IList)GetValue(ItemsSourceProperty);
|
||||
set => SetValue(ItemsSourceProperty, value);
|
||||
}
|
||||
|
||||
private static void OnItemsSourcePropertyChanged(BindableObject obj, object oldValue, object newValue)
|
||||
{
|
||||
var flowLayout = (FlowLayout)obj;
|
||||
if (oldValue is IIllustCollectionChanged oldNotify)
|
||||
{
|
||||
oldNotify.CollectionChanged -= flowLayout.OnCollectionChanged;
|
||||
}
|
||||
flowLayout.lastWidth = -1;
|
||||
if (newValue == null)
|
||||
{
|
||||
flowLayout.cachedLayout.Clear();
|
||||
flowLayout.Children.Clear();
|
||||
flowLayout.InvalidateLayout();
|
||||
}
|
||||
else if (newValue is IList newList)
|
||||
{
|
||||
flowLayout.freezed = true;
|
||||
flowLayout.cachedLayout.Clear();
|
||||
flowLayout.Children.Clear();
|
||||
for (var i = 0; i < newList.Count; i++)
|
||||
{
|
||||
var child = flowLayout.ItemTemplate.CreateContent();
|
||||
if (child is View view)
|
||||
{
|
||||
view.BindingContext = newList[i];
|
||||
flowLayout.Children.Add(view);
|
||||
}
|
||||
}
|
||||
|
||||
if (newValue is IIllustCollectionChanged newNotify)
|
||||
{
|
||||
newNotify.CollectionChanged += flowLayout.OnCollectionChanged;
|
||||
}
|
||||
flowLayout.freezed = false;
|
||||
|
||||
flowLayout.UpdateChildrenLayout();
|
||||
flowLayout.InvalidateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCollectionChanged(object sender, CollectionChangedEventArgs e)
|
||||
{
|
||||
lastWidth = -1;
|
||||
if (e.OldItems != null)
|
||||
{
|
||||
freezed = true;
|
||||
cachedLayout.Clear();
|
||||
var index = e.OldStartingIndex;
|
||||
for (var i = index + e.OldItems.Count - 1; i >= index; i--)
|
||||
{
|
||||
Children.RemoveAt(i);
|
||||
}
|
||||
freezed = false;
|
||||
UpdateChildrenLayout();
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
if (e.NewItems == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
freezed = true;
|
||||
var start = e.NewStartingIndex;
|
||||
for (var i = 0; i < e.NewItems.Count; i++)
|
||||
{
|
||||
var child = ItemTemplate.CreateContent();
|
||||
if (child is View view)
|
||||
{
|
||||
view.BindingContext = e.NewItems[i];
|
||||
Children.Insert(start + i, view);
|
||||
}
|
||||
}
|
||||
freezed = false;
|
||||
UpdateChildrenLayout();
|
||||
//InvalidateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public interface IIllustCollectionChanged
|
||||
{
|
||||
event EventHandler<CollectionChangedEventArgs> CollectionChanged;
|
||||
}
|
||||
|
||||
public class CollectionChangedEventArgs : EventArgs
|
||||
{
|
||||
public int OldStartingIndex { get; set; }
|
||||
public IList OldItems { get; set; }
|
||||
public int NewStartingIndex { get; set; }
|
||||
public IList NewItems { get; set; }
|
||||
}
|
||||
|
||||
public class HeightEventArgs : EventArgs
|
||||
{
|
||||
public double ContentHeight { get; set; }
|
||||
}
|
||||
}
|
159
Gallery/UI/OptionCell.cs
Executable file
159
Gallery/UI/OptionCell.cs
Executable file
@ -0,0 +1,159 @@
|
||||
using System.Collections;
|
||||
using Gallery.UI.Theme;
|
||||
using Gallery.Utils;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI
|
||||
{
|
||||
public class OptionEntry : Entry { }
|
||||
public class OptionPicker : Picker { }
|
||||
|
||||
public abstract class OptionCell : ViewCell
|
||||
{
|
||||
public static readonly BindableProperty TitleProperty = BindableProperty.Create(
|
||||
nameof(Title), typeof(string), typeof(OptionCell));
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => (string)GetValue(TitleProperty);
|
||||
set => SetValue(TitleProperty, value);
|
||||
}
|
||||
|
||||
protected abstract View Content { get; }
|
||||
|
||||
public OptionCell()
|
||||
{
|
||||
View = new Grid
|
||||
{
|
||||
BindingContext = this,
|
||||
Padding = new Thickness(20, 0),
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(.3, GridUnitType.Star) },
|
||||
new ColumnDefinition { Width = new GridLength(.7, GridUnitType.Star) }
|
||||
},
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.TailTruncation,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
}
|
||||
.Binding(Label.TextProperty, nameof(Title))
|
||||
.DynamicResource(Label.TextColorProperty, ThemeBase.TextColor),
|
||||
|
||||
Content.GridColumn(1)
|
||||
}
|
||||
}
|
||||
.DynamicResource(VisualElement.BackgroundColorProperty, ThemeBase.OptionTintColor);
|
||||
}
|
||||
}
|
||||
|
||||
public class OptionTextCell : OptionCell
|
||||
{
|
||||
public static readonly BindableProperty DetailProperty = BindableProperty.Create(
|
||||
nameof(Detail), typeof(string), typeof(OptionCell));
|
||||
|
||||
public string Detail
|
||||
{
|
||||
get => (string)GetValue(DetailProperty);
|
||||
set => SetValue(DetailProperty, value);
|
||||
}
|
||||
|
||||
protected override View Content => new Label
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
}
|
||||
.Binding(Label.TextProperty, nameof(Detail))
|
||||
.DynamicResource(Label.TextColorProperty, ThemeBase.SubTextColor);
|
||||
}
|
||||
|
||||
public class OptionSwitchCell : OptionCell
|
||||
{
|
||||
public static readonly BindableProperty IsToggledProperty = BindableProperty.Create(
|
||||
nameof(IsToggled), typeof(bool), typeof(OptionSwitchCell));
|
||||
|
||||
public bool IsToggled
|
||||
{
|
||||
get => (bool)GetValue(IsToggledProperty);
|
||||
set => SetValue(IsToggledProperty, value);
|
||||
}
|
||||
|
||||
protected override View Content => new Switch
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
}
|
||||
.Binding(Switch.IsToggledProperty, nameof(IsToggled), BindingMode.TwoWay);
|
||||
}
|
||||
|
||||
public class OptionDropCell : OptionCell
|
||||
{
|
||||
public static readonly BindableProperty ItemsProperty = BindableProperty.Create(
|
||||
nameof(Items), typeof(IList), typeof(OptionDropCell));
|
||||
public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create(
|
||||
nameof(SelectedIndex), typeof(int), typeof(OptionDropCell));
|
||||
|
||||
public IList Items
|
||||
{
|
||||
get => (IList)GetValue(ItemsProperty);
|
||||
set => SetValue(ItemsProperty, value);
|
||||
}
|
||||
public int SelectedIndex
|
||||
{
|
||||
get => (int)GetValue(SelectedIndexProperty);
|
||||
set => SetValue(SelectedIndexProperty, value);
|
||||
}
|
||||
|
||||
protected override View Content => new OptionPicker
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.Fill,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
}
|
||||
.Binding(Picker.ItemsSourceProperty, nameof(Items))
|
||||
.Binding(Picker.SelectedIndexProperty, nameof(SelectedIndex), BindingMode.TwoWay)
|
||||
.DynamicResource(Picker.TextColorProperty, ThemeBase.TextColor)
|
||||
.DynamicResource(VisualElement.BackgroundColorProperty, ThemeBase.OptionTintColor);
|
||||
}
|
||||
|
||||
public class OptionEntryCell : OptionCell
|
||||
{
|
||||
public static readonly BindableProperty TextProperty = BindableProperty.Create(
|
||||
nameof(Text), typeof(string), typeof(OptionSwitchCell));
|
||||
public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(
|
||||
nameof(Keyboard), typeof(Keyboard), typeof(OptionSwitchCell));
|
||||
public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(
|
||||
nameof(Placeholder), typeof(string), typeof(OptionSwitchCell));
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => (string)GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
public Keyboard Keyboard
|
||||
{
|
||||
get => (Keyboard)GetValue(KeyboardProperty);
|
||||
set => SetValue(KeyboardProperty, value);
|
||||
}
|
||||
public string Placeholder
|
||||
{
|
||||
get => (string)GetValue(PlaceholderProperty);
|
||||
set => SetValue(PlaceholderProperty, value);
|
||||
}
|
||||
|
||||
protected override View Content => new OptionEntry
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.Fill,
|
||||
HorizontalTextAlignment = TextAlignment.End,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
ReturnType = ReturnType.Next
|
||||
}
|
||||
.Binding(Entry.TextProperty, nameof(Text), BindingMode.TwoWay)
|
||||
.Binding(InputView.KeyboardProperty, nameof(Keyboard))
|
||||
.Binding(Entry.PlaceholderProperty, nameof(Placeholder))
|
||||
.DynamicResource(Entry.TextColorProperty, ThemeBase.TextColor)
|
||||
.DynamicResource(Entry.PlaceholderColorProperty, ThemeBase.SubTextColor)
|
||||
.DynamicResource(VisualElement.BackgroundColorProperty, ThemeBase.OptionTintColor);
|
||||
}
|
||||
}
|
75
Gallery/UI/SegmentedControl.cs
Executable file
75
Gallery/UI/SegmentedControl.cs
Executable file
@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI
|
||||
{
|
||||
public class SegmentedControl : View, IViewContainer<SegmentedControlOption>
|
||||
{
|
||||
public IList<SegmentedControlOption> Children { get; set; }
|
||||
|
||||
public SegmentedControl()
|
||||
{
|
||||
Children = new List<SegmentedControlOption>();
|
||||
}
|
||||
|
||||
public static readonly BindableProperty TintColorProperty = BindableProperty.Create(
|
||||
nameof(TintColor), typeof(Color), typeof(SegmentedControl));
|
||||
public static readonly BindableProperty DisabledColorProperty = BindableProperty.Create(
|
||||
nameof(DisabledColor), typeof(Color), typeof(SegmentedControl));
|
||||
public static readonly BindableProperty SelectedTextColorProperty = BindableProperty.Create(
|
||||
nameof(SelectedTextColor), typeof(Color), typeof(SegmentedControl));
|
||||
public static readonly BindableProperty SelectedSegmentIndexProperty = BindableProperty.Create(
|
||||
nameof(SelectedSegmentIndex), typeof(int), typeof(SegmentedControl));
|
||||
|
||||
public Color TintColor
|
||||
{
|
||||
get => (Color)GetValue(TintColorProperty);
|
||||
set => SetValue(TintColorProperty, value);
|
||||
}
|
||||
public Color DisabledColor
|
||||
{
|
||||
get => (Color)GetValue(DisabledColorProperty);
|
||||
set => SetValue(DisabledColorProperty, value);
|
||||
}
|
||||
public Color SelectedTextColor
|
||||
{
|
||||
get => (Color)GetValue(SelectedTextColorProperty);
|
||||
set => SetValue(SelectedTextColorProperty, value);
|
||||
}
|
||||
public int SelectedSegmentIndex
|
||||
{
|
||||
get => (int)GetValue(SelectedSegmentIndexProperty);
|
||||
set => SetValue(SelectedSegmentIndexProperty, value);
|
||||
}
|
||||
|
||||
public SegmentedControlOption SelectedSegment => Children[SelectedSegmentIndex];
|
||||
|
||||
public event EventHandler<ValueChangedEventArgs> ValueChanged;
|
||||
|
||||
//[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void SendValueChanged()
|
||||
{
|
||||
ValueChanged?.Invoke(this, new ValueChangedEventArgs { NewValue = SelectedSegmentIndex });
|
||||
}
|
||||
}
|
||||
|
||||
public class SegmentedControlOption : View
|
||||
{
|
||||
public static readonly BindableProperty TextProperty = BindableProperty.Create(
|
||||
nameof(Text), typeof(string), typeof(SegmentedControlOption));
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => (string)GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
|
||||
public object Value { get; set; }
|
||||
}
|
||||
|
||||
public class ValueChangedEventArgs : EventArgs
|
||||
{
|
||||
public int NewValue { get; set; }
|
||||
}
|
||||
}
|
149
Gallery/UI/StyleDefinition.cs
Normal file
149
Gallery/UI/StyleDefinition.cs
Normal file
@ -0,0 +1,149 @@
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI
|
||||
{
|
||||
public static class StyleDefinition
|
||||
{
|
||||
public const double FontSizeTitle = 18.0;
|
||||
|
||||
public static readonly Thickness ScreenBottomPadding;
|
||||
public static readonly Thickness TopOffset16 = new Thickness(0, 16, 0, 0);
|
||||
public static readonly Thickness TopOffset32 = new Thickness(0, 32, 0, 0);
|
||||
public static readonly Thickness TopOffset37 = new Thickness(0, 37, 0, 0);
|
||||
public static readonly Color ColorLightShadow = Color.FromRgba(0, 0, 0, 0x20);
|
||||
public static readonly Color ColorDeepShadow = Color.FromRgba(0, 0, 0, 0x50);
|
||||
public static readonly Color ColorRedBackground = Color.FromRgb(0xfd, 0x43, 0x63);
|
||||
public static readonly Color ColorDownloadBackground = Color.FromRgb(0xd7, 0xd9, 0xe0);
|
||||
public static readonly ImageSource DownloadBackground = ImageSource.FromFile("download.png");
|
||||
public static readonly ImageSource ProfileNone = ImageSource.FromFile("no_profile.png");
|
||||
public static readonly double FontSizeMicro = Device.GetNamedSize(NamedSize.Micro, typeof(Label));
|
||||
public static readonly double FontSizeSmall = Device.GetNamedSize(NamedSize.Small, typeof(Label));
|
||||
|
||||
#if __IOS__
|
||||
public const string IconLightFontFamily = "FontAwesome5Pro-Light";
|
||||
public const string IconRegularFontFamily = "FontAwesome5Pro-Regular";
|
||||
public const string IconSolidFontFamily = "FontAwesome5Pro-Solid";
|
||||
|
||||
public const string IconLeft = "\uf104";
|
||||
#elif __ANDROID__
|
||||
public const string IconLightFontFamily = "fa-light-300.ttf#FontAwesome5Pro-Light";
|
||||
public const string IconRegularFontFamily = "fa-regular-400.ttf#FontAwesome5Pro-Regular";
|
||||
public const string IconSolidFontFamily = "fa-solid-900.ttf#FontAwesome5Pro-Solid";
|
||||
|
||||
public const string IconLeft = "\uf053";
|
||||
#endif
|
||||
|
||||
public const string IconUser = "\uf007";
|
||||
public const string IconSparkles = "\uf890";
|
||||
public const string IconOrder = "\uf88f";
|
||||
public const string IconLayer = "\uf302";
|
||||
public const string IconRefresh = "\uf2f9";
|
||||
public const string IconLove = "\uf004";
|
||||
public const string IconCircleLove = "\uf4c7";
|
||||
public const string IconOption = "\uf013";
|
||||
public const string IconFavorite = "\uf02e";
|
||||
public const string IconShare = "\uf1e0";
|
||||
public const string IconCaretDown = "\uf0d7";
|
||||
//public const string IconCaretUp = "\uf0d8";
|
||||
public const string IconCircleCheck = "\uf058";
|
||||
public const string IconPlay = "\uf04b";
|
||||
public const string IconPause = "\uf04c";
|
||||
public const string IconMore = "\uf142";
|
||||
public const string IconCaretCircleLeft = "\uf32e";
|
||||
public const string IconCaretCircleRight = "\uf330";
|
||||
public const string IconCalendarDay = "\uf783";
|
||||
public const string IconClose = "\uf057";
|
||||
public const string IconCloudDownload = "\uf381";
|
||||
|
||||
static StyleDefinition()
|
||||
{
|
||||
_ = IsFullscreenDevice;
|
||||
if (_isBottomPadding)
|
||||
{
|
||||
if (DeviceInfo.Idiom == DeviceIdiom.Phone)
|
||||
{
|
||||
ScreenBottomPadding = new Thickness(0, 0, 0, 26);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScreenBottomPadding = new Thickness(0, 0, 0, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool _isBottomPadding;
|
||||
private static bool? _isFullscreenDevice;
|
||||
public static bool IsFullscreenDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_isFullscreenDevice != null)
|
||||
{
|
||||
return _isFullscreenDevice.Value;
|
||||
}
|
||||
#if __IOS__
|
||||
try
|
||||
{
|
||||
var model = DeviceInfo.Model;
|
||||
if (model == "iPhone10,3")
|
||||
{
|
||||
// iPhone X
|
||||
_isFullscreenDevice = true;
|
||||
_isBottomPadding = true;
|
||||
}
|
||||
else if (model.StartsWith("iPhone"))
|
||||
{
|
||||
var vs = model.Substring(6).Split(',');
|
||||
if (vs.Length == 2 && int.TryParse(vs[0], out int main) && int.TryParse(vs[1], out int sub))
|
||||
{
|
||||
// iPhone X/XS/XR or iPhone 11
|
||||
var flag = (main == 10 && sub >= 6) || (main > 10);
|
||||
_isFullscreenDevice = flag;
|
||||
_isBottomPadding = flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isFullscreenDevice = false;
|
||||
}
|
||||
}
|
||||
else if (model.StartsWith("iPad8,"))
|
||||
{
|
||||
// iPad 11-inch or 12.9-inch (3rd+)
|
||||
//_isFullscreenDevice = true;
|
||||
_isBottomPadding = true;
|
||||
}
|
||||
#if DEBUG
|
||||
else
|
||||
{
|
||||
// iPad or Simulator
|
||||
var name = DeviceInfo.Name;
|
||||
var flag = name.StartsWith("iPhone X")
|
||||
|| name.StartsWith("iPhone 11")
|
||||
|| name.StartsWith("iPhone 12");
|
||||
_isFullscreenDevice = flag;
|
||||
_isBottomPadding = flag
|
||||
|| name.StartsWith("iPad Pro (11-inch)")
|
||||
|| name.StartsWith("iPad Pro (12.9-inch) (3rd generation)")
|
||||
|| name.StartsWith("iPad Pro (12.9-inch) (4th generation)");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
App.DebugError("device.get", $"failed to get the device model. {ex.Message}");
|
||||
}
|
||||
#else
|
||||
// TODO:
|
||||
_isFullscreenDevice = false;
|
||||
_isBottomPadding = false;
|
||||
#endif
|
||||
if (_isFullscreenDevice == null)
|
||||
{
|
||||
_isFullscreenDevice = false;
|
||||
}
|
||||
return _isFullscreenDevice.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
43
Gallery/UI/Theme/DarkTheme.cs
Executable file
43
Gallery/UI/Theme/DarkTheme.cs
Executable file
@ -0,0 +1,43 @@
|
||||
using Gallery.Utils;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI.Theme
|
||||
{
|
||||
public class DarkTheme : ThemeBase
|
||||
{
|
||||
private static DarkTheme _instance;
|
||||
|
||||
public static DarkTheme Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new DarkTheme();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public DarkTheme()
|
||||
{
|
||||
InitColors();
|
||||
InitResources();
|
||||
}
|
||||
|
||||
private void InitColors()
|
||||
{
|
||||
Add(StatusBarStyle, StatusBarStyles.WhiteText);
|
||||
Add(WindowColor, Color.Black);
|
||||
Add(TintColor, Color.FromRgb(0x94, 0x95, 0x9a));
|
||||
Add(TextColor, Color.White);
|
||||
Add(SubTextColor, Color.LightGray);
|
||||
Add(CardBackgroundColor, Color.FromRgb(0x33, 0x33, 0x33));
|
||||
Add(MaskColor, Color.FromRgba(0xff, 0xff, 0xff, 0x64));
|
||||
Add(NavColor, Color.FromRgb(0x11, 0x11, 0x11));
|
||||
Add(NavSelectedColor, Color.FromRgb(0x22, 0x22, 0x22));
|
||||
Add(OptionBackColor, Color.Black);
|
||||
Add(OptionTintColor, Color.FromRgb(0x11, 0x11, 0x11));
|
||||
}
|
||||
}
|
||||
}
|
43
Gallery/UI/Theme/LightTheme.cs
Executable file
43
Gallery/UI/Theme/LightTheme.cs
Executable file
@ -0,0 +1,43 @@
|
||||
using Gallery.Utils;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI.Theme
|
||||
{
|
||||
public class LightTheme : ThemeBase
|
||||
{
|
||||
private static LightTheme _instance;
|
||||
|
||||
public static LightTheme Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new LightTheme();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public LightTheme()
|
||||
{
|
||||
InitColors();
|
||||
InitResources();
|
||||
}
|
||||
|
||||
private void InitColors()
|
||||
{
|
||||
Add(StatusBarStyle, StatusBarStyles.DarkText);
|
||||
Add(WindowColor, Color.White);
|
||||
Add(TintColor, Color.FromRgb(0x87, 0x87, 0x8b)); // 0x7f, 0x99, 0xc6
|
||||
Add(TextColor, Color.Black);
|
||||
Add(SubTextColor, Color.DimGray);
|
||||
Add(CardBackgroundColor, Color.FromRgb(0xf3, 0xf3, 0xf3));
|
||||
Add(MaskColor, Color.FromRgba(0, 0, 0, 0x64));
|
||||
Add(NavColor, Color.FromRgb(0xf0, 0xf0, 0xf0));
|
||||
Add(NavSelectedColor, Color.LightGray);
|
||||
Add(OptionBackColor, Color.FromRgb(0xf0, 0xf0, 0xf0));
|
||||
Add(OptionTintColor, Color.White);
|
||||
}
|
||||
}
|
||||
}
|
97
Gallery/UI/Theme/ThemeBase.cs
Executable file
97
Gallery/UI/Theme/ThemeBase.cs
Executable file
@ -0,0 +1,97 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.UI.Theme
|
||||
{
|
||||
public abstract class ThemeBase : ResourceDictionary
|
||||
{
|
||||
public const string FontIconUserFlyout = nameof(FontIconUserFlyout);
|
||||
public const string FontIconSparklesFlyout = nameof(FontIconSparklesFlyout);
|
||||
public const string FontIconOrderFlyout = nameof(FontIconOrderFlyout);
|
||||
public const string FontIconFavoriteFlyout = nameof(FontIconFavoriteFlyout);
|
||||
public const string FontIconRefresh = nameof(FontIconRefresh);
|
||||
public const string FontIconLove = nameof(FontIconLove);
|
||||
public const string FontIconNotLove = nameof(FontIconNotLove);
|
||||
public const string FontIconCircleLove = nameof(FontIconCircleLove);
|
||||
public const string FontIconOption = nameof(FontIconOption);
|
||||
public const string FontIconShare = nameof(FontIconShare);
|
||||
public const string FontIconMore = nameof(FontIconMore);
|
||||
public const string FontIconCaretCircleLeft = nameof(FontIconCaretCircleLeft);
|
||||
public const string FontIconCaretCircleRight = nameof(FontIconCaretCircleRight);
|
||||
public const string FontIconCalendarDay = nameof(FontIconCalendarDay);
|
||||
public const string FontIconCloudDownload = nameof(FontIconCloudDownload);
|
||||
public const string IconCircleCheck = nameof(IconCircleCheck);
|
||||
public const string IconCaretDown = nameof(IconCaretDown);
|
||||
public const string IconClose = nameof(IconClose);
|
||||
|
||||
public const string StatusBarStyle = nameof(StatusBarStyle);
|
||||
public const string WindowColor = nameof(WindowColor);
|
||||
public const string TintColor = nameof(TintColor);
|
||||
public const string TextColor = nameof(TextColor);
|
||||
public const string SubTextColor = nameof(SubTextColor);
|
||||
public const string CardBackgroundColor = nameof(CardBackgroundColor);
|
||||
public const string MaskColor = nameof(MaskColor);
|
||||
public const string NavColor = nameof(NavColor);
|
||||
public const string NavSelectedColor = nameof(NavSelectedColor);
|
||||
public const string OptionBackColor = nameof(OptionBackColor);
|
||||
public const string OptionTintColor = nameof(OptionTintColor);
|
||||
|
||||
public const string IconLightFontFamily = nameof(IconLightFontFamily);
|
||||
public const string IconRegularFontFamily = nameof(IconRegularFontFamily);
|
||||
public const string IconSolidFontFamily = nameof(IconSolidFontFamily);
|
||||
//public const string Horizon10 = nameof(Horizon10);
|
||||
public const string ScreenBottomPadding = nameof(ScreenBottomPadding);
|
||||
|
||||
protected void InitResources()
|
||||
{
|
||||
//Add(Horizon10, StyleDefinition.Horizon10);
|
||||
Add(ScreenBottomPadding, StyleDefinition.ScreenBottomPadding);
|
||||
|
||||
Add(IconLightFontFamily, StyleDefinition.IconLightFontFamily);
|
||||
Add(IconRegularFontFamily, StyleDefinition.IconRegularFontFamily);
|
||||
Add(IconSolidFontFamily, StyleDefinition.IconSolidFontFamily);
|
||||
|
||||
var regularFontFamily = StyleDefinition.IconRegularFontFamily;
|
||||
var solidFontFamily = StyleDefinition.IconSolidFontFamily;
|
||||
|
||||
#if __IOS__
|
||||
Add(FontIconUserFlyout, GetSolidIcon(StyleDefinition.IconUser, solidFontFamily));
|
||||
Add(FontIconSparklesFlyout, GetSolidIcon(StyleDefinition.IconSparkles, solidFontFamily));
|
||||
Add(FontIconOrderFlyout, GetSolidIcon(StyleDefinition.IconOrder, solidFontFamily));
|
||||
Add(FontIconFavoriteFlyout, GetSolidIcon(StyleDefinition.IconFavorite, solidFontFamily));
|
||||
Add(FontIconOption, GetSolidIcon(StyleDefinition.IconOption, solidFontFamily));
|
||||
#elif __ANDROID__
|
||||
Add(FontIconUserFlyout, ImageSource.FromFile("ic_user"));
|
||||
Add(FontIconSparklesFlyout, ImageSource.FromFile("ic_sparkles"));
|
||||
Add(FontIconOrderFlyout, ImageSource.FromFile("ic_rank"));
|
||||
Add(FontIconFavoriteFlyout, ImageSource.FromFile("ic_bookmark"));
|
||||
Add(FontIconOption, ImageSource.FromFile("ic_option"));
|
||||
#endif
|
||||
|
||||
Add(FontIconLove, GetSolidIcon(StyleDefinition.IconLove, solidFontFamily, StyleDefinition.ColorRedBackground));
|
||||
Add(FontIconCircleLove, GetSolidIcon(StyleDefinition.IconCircleLove, solidFontFamily, StyleDefinition.ColorRedBackground));
|
||||
Add(FontIconRefresh, GetSolidIcon(StyleDefinition.IconRefresh, solidFontFamily));
|
||||
Add(FontIconNotLove, GetSolidIcon(StyleDefinition.IconLove, regularFontFamily));
|
||||
Add(FontIconShare, GetSolidIcon(StyleDefinition.IconShare, solidFontFamily));
|
||||
Add(FontIconMore, GetSolidIcon(StyleDefinition.IconMore, regularFontFamily));
|
||||
Add(FontIconCaretCircleLeft, GetSolidIcon(StyleDefinition.IconCaretCircleLeft, solidFontFamily));
|
||||
Add(FontIconCaretCircleRight, GetSolidIcon(StyleDefinition.IconCaretCircleRight, solidFontFamily));
|
||||
Add(FontIconCalendarDay, GetSolidIcon(StyleDefinition.IconCalendarDay, regularFontFamily));
|
||||
Add(FontIconCloudDownload, GetSolidIcon(StyleDefinition.IconCloudDownload, solidFontFamily));
|
||||
|
||||
Add(IconCircleCheck, StyleDefinition.IconCircleCheck);
|
||||
Add(IconCaretDown, StyleDefinition.IconCaretDown);
|
||||
Add(IconClose, StyleDefinition.IconClose);
|
||||
}
|
||||
|
||||
private FontImageSource GetSolidIcon(string icon, string family, Color color = default)
|
||||
{
|
||||
return new FontImageSource
|
||||
{
|
||||
FontFamily = family,
|
||||
Glyph = icon,
|
||||
Size = StyleDefinition.FontSizeTitle,
|
||||
Color = color
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user