add account page layout

This commit is contained in:
2022-02-25 16:33:31 +08:00
parent 6254985c9b
commit fae6d2ce50
56 changed files with 592 additions and 191 deletions

View File

@ -17,7 +17,7 @@
<Setter Property="HorizontalOptions" Value="Center"/>
</Style>
<ControlTemplate x:Key="weekDay">
<Grid Padding="0, 8, 0, 0" RowDefinitions="Auto, 3" RowSpacing="0">
<Grid Padding="0, 8, 0, 0" RowDefinitions="Auto, 3" RowSpacing="{OnPlatform Android=0, iOS=4}">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnDayTapped, Source={x:Reference billingDate}}" CommandParameter="{TemplateBinding BillingDay}"/>
</Grid.GestureRecognizers>
@ -32,7 +32,7 @@
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="weekEnd">
<Grid Padding="0, 8, 0, 0" RowDefinitions="Auto, 3" RowSpacing="0">
<Grid Padding="0, 8, 0, 0" RowDefinitions="Auto, 3" RowSpacing="{OnPlatform Android=0, iOS=4}">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnDayTapped, Source={x:Reference billingDate}}" CommandParameter="{TemplateBinding BillingDay}"/>
</Grid.GestureRecognizers>

View File

@ -38,4 +38,17 @@ namespace Billing.UI
return value;
}
}
public class NotNullConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
}

View File

@ -1,5 +1,4 @@
using Billing.Themes;
using System;
using System;
using Xamarin.Forms;
namespace Billing.UI
@ -30,126 +29,4 @@ namespace Billing.UI
LongPressed?.Invoke(this, EventArgs.Empty);
}
}
public class OptionEntry : Entry { }
public abstract class OptionCell : ViewCell
{
public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(OptionCell));
public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(OptionCell));
public string Title
{
get => (string)GetValue(TitleProperty);
set => SetValue(TitleProperty, value);
}
public Color BackgroundColor
{
get => (Color)GetValue(BackgroundColorProperty);
set => SetValue(BackgroundColorProperty, 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, BaseTheme.TextColor),
Content.GridColumn(1)
}
}
.DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
}
}
public class OptionTextCell : OptionCell
{
public static readonly BindableProperty DetailProperty = BindableProperty.Create(nameof(Detail), typeof(string), typeof(OptionTextCell));
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, BaseTheme.SecondaryTextColor);
}
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 OptionEntryCell : OptionCell
{
public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEntryCell));
public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEntryCell));
public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEntryCell));
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, BaseTheme.TextColor)
.DynamicResource(Entry.PlaceholderColorProperty, BaseTheme.SecondaryTextColor)
.DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
}
}

View File

@ -13,10 +13,10 @@ namespace Billing.UI
public static class ExtensionHelper
{
public static View Binding(this View view, BindableProperty property, string path, BindingMode mode = BindingMode.Default, IValueConverter converter = null)
public static T Binding<T>(this T obj, BindableProperty property, string path, BindingMode mode = BindingMode.Default, IValueConverter converter = null) where T : BindableObject
{
view.SetBinding(property, path, mode, converter);
return view;
obj.SetBinding(property, path, mode, converter);
return obj;
}
public static View DynamicResource(this View view, BindableProperty property, string key)
@ -36,6 +36,24 @@ namespace Billing.UI
Grid.SetRow(view, row);
return view;
}
public static View GridColumnSpan(this View view, int columnSpan)
{
Grid.SetColumnSpan(view, columnSpan);
return view;
}
public static View GridRowSpan(this View view, int rowSpan)
{
Grid.SetRowSpan(view, rowSpan);
return view;
}
public static View Margin(this View view, Thickness margin)
{
view.Margin = margin;
return view;
}
}
public class Tap : IDisposable

View File

@ -0,0 +1,286 @@
using Billing.Themes;
using Xamarin.Forms;
namespace Billing.UI
{
public class OptionEntry : Entry { }
public class OptionEditor : Editor { }
public abstract class OptionCell : ViewCell
{
public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(OptionCell));
public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(OptionCell));
public static readonly BindableProperty IconProperty = BindableProperty.Create(nameof(Icon), typeof(ImageSource), typeof(OptionCell));
public string Title
{
get => (string)GetValue(TitleProperty);
set => SetValue(TitleProperty, value);
}
public Color BackgroundColor
{
get => (Color)GetValue(BackgroundColorProperty);
set => SetValue(BackgroundColorProperty, value);
}
[TypeConverter(typeof(ImageSourceConverter))]
public ImageSource Icon
{
get => (ImageSource)GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
protected abstract View Content { get; }
public OptionCell()
{
View = new Grid
{
BindingContext = this,
Padding = new Thickness(20, 0),
ColumnDefinitions =
{
new ColumnDefinition { Width = GridLength.Auto },
new ColumnDefinition { Width = new GridLength(.3, GridUnitType.Star) },
new ColumnDefinition { Width = new GridLength(.7, GridUnitType.Star) }
},
Children =
{
new Image
{
WidthRequest = 20,
HeightRequest = 20,
Aspect = Aspect.AspectFit,
VerticalOptions = LayoutOptions.Center,
Margin = new Thickness(6, 0)
}
.Binding(VisualElement.IsVisibleProperty, nameof(Icon), converter: new NotNullConverter())
.Binding(Image.SourceProperty, nameof(Icon)),
new Label
{
LineBreakMode = LineBreakMode.TailTruncation,
VerticalOptions = LayoutOptions.Center
}
.GridColumn(1)
.Binding(Label.TextProperty, nameof(Title))
.DynamicResource(Label.TextColorProperty, BaseTheme.TextColor),
Content.GridColumn(2)
}
}
.DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
}
}
public abstract class OptionVerticalCell : OptionCell
{
public OptionVerticalCell()
{
View = new Grid
{
BindingContext = this,
Padding = new Thickness(20, 0),
ColumnDefinitions =
{
new ColumnDefinition { Width = GridLength.Auto },
new ColumnDefinition { Width = GridLength.Star }
},
RowDefinitions =
{
new RowDefinition { Height = new GridLength(40) },
new RowDefinition { Height = GridLength.Star }
},
Children =
{
new Image
{
WidthRequest = 20,
HeightRequest = 20,
Aspect = Aspect.AspectFit,
VerticalOptions = LayoutOptions.Center,
Margin = new Thickness(6, 0)
}
.Binding(VisualElement.IsVisibleProperty, nameof(Icon), converter: new NotNullConverter())
.Binding(Image.SourceProperty, nameof(Icon)),
new Label
{
LineBreakMode = LineBreakMode.TailTruncation,
VerticalOptions = LayoutOptions.Center
}
.GridColumn(1)
.Binding(Label.TextProperty, nameof(Title))
.DynamicResource(Label.TextColorProperty, BaseTheme.TextColor),
Content.GridRow(1).GridColumnSpan(2)
}
}
.DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
}
}
public class OptionTextCell : OptionCell
{
public static readonly BindableProperty DetailProperty = BindableProperty.Create(nameof(Detail), typeof(string), typeof(OptionTextCell));
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, BaseTheme.SecondaryTextColor);
}
public class OptionSelectCell : OptionTextCell
{
public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(Command), typeof(OptionSelectCell));
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(OptionSelectCell));
public Command Command
{
get => (Command)GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
public object CommandParameter
{
get => GetValue(CommandParameterProperty);
set => SetValue(CommandParameterProperty, value);
}
protected override View Content => new StackLayout
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions = LayoutOptions.End,
Children =
{
new Label
{
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Center
}
.Binding(Label.TextProperty, nameof(Detail))
.DynamicResource(Label.TextColorProperty, BaseTheme.SecondaryTextColor),
new TintImage
{
HeightRequest = 20,
VerticalOptions = LayoutOptions.Center,
Margin = new Thickness(6, 0),
Source = "right.png"
}
},
GestureRecognizers =
{
new TapGestureRecognizer()
.Binding(TapGestureRecognizer.CommandProperty, nameof(Command))
.Binding(TapGestureRecognizer.CommandParameterProperty, nameof(CommandParameter))
}
};
}
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 OptionEntryCell : OptionCell
{
public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEntryCell));
public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEntryCell));
public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEntryCell));
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, BaseTheme.TextColor)
.DynamicResource(Entry.PlaceholderColorProperty, BaseTheme.SecondaryTextColor)
.DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
}
public class OptionEditorCell : OptionVerticalCell
{
public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEditorCell));
public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(nameof(FontSize), typeof(double), typeof(OptionEditorCell), defaultValue: Device.GetNamedSize(NamedSize.Default, typeof(Editor)));
public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEditorCell), defaultValue: Keyboard.Default);
public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEditorCell));
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
[TypeConverter(typeof(FontSizeConverter))]
public double FontSize
{
get => (double)GetValue(FontSizeProperty);
set => SetValue(FontSizeProperty, 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 OptionEditor
{
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.Fill
}
.Binding(Editor.TextProperty, nameof(Text), BindingMode.TwoWay)
.Binding(Editor.FontSizeProperty, nameof(FontSize))
.Binding(InputView.KeyboardProperty, nameof(Keyboard))
.Binding(Editor.PlaceholderProperty, nameof(Placeholder))
.DynamicResource(Editor.TextColorProperty, BaseTheme.TextColor)
.DynamicResource(Editor.PlaceholderColorProperty, BaseTheme.SecondaryTextColor)
.DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
}
}