muak / AiForms.Maui.SettingsView

SettingsView for .NET MAUI
MIT License
148 stars 11 forks source link

AiForms.SettingsView for .NET MAUI

This is a flexible TableView specialized in settings for Android / iOS.

This is currently a preview version. It is not stable, so please use it for research and verification purposes only.

Japanese

Build status

What SettingsView can do.

General

Sections

Cells

Demo movie

https://youtu.be/FTMOqNILxBE

Minimum Device and Version etc

iOS:iPhone5s,iPod touch6,iOS9.3
Android:version 5.1.1 (only FormsAppcompatActivity) / API22

Installation

https://www.nuget.org/packages/AiForms.Maui.SettingsView/

Install-Package AiForms.Maui.SettingsView
public static MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder
        .UseMauiApp<App>()   
        .UseSettingsView() // write this
    ...
}

OR

public static MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder
        .UseMauiApp<App>()   
        .ConfigureMauiHandlers(handlers =>
        {
            handlers.AddSettingsViewHandler(); // write this
        });
    ...
}

Options

MAUI has a fatal flaw in that the DisconnectHandler of the control is not automatically called.
(https://github.com/dotnet/maui/issues/18366)
SettingsView has an option to call DisconnectHandler on PageUnload to clean up.
To enable this, do the following.

...
.UseSettingsView(true)
...

How to write with xaml

<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:sv="clr-namespace:AiForms.Settings;assembly=SettingsView"
    x:Class="Sample.Views.SettingsViewPage">

<sv:SettingsView HasUnevenRows="true">

    <sv:Section Title="Header1" FooterText="Footer1">
        <sv:CommandCell IconSource="icon.png" IconSize="60,60" IconRadius="30"
            Title="Xam Xamarin" Description="hoge@fuga.com"
            Command="{Binding ToProfileCommand}" CommandParameter="{Binding Parameter}"
            KeepSelectedUntilBack="true"            
        />
        <sv:ButtonCell Title="Toggle Section" TitleColor="{StaticResource TitleTextColor}"
             TitleAlignment="Center" Command="{Binding SectionToggleCommand}" />
        <sv:LabelCell Title="Label" ValueText="value" />
        <sv:SwitchCell Title="Switch" On="true" 
            Description="This is description." />
        <sv:CheckboxCell Title="Checkbox" Checked="true" />
    </sv:Section>

    <sv:Section Title="Header2" FooterText="Footer2" IsVisible="{Binding SctionIsVisible}">
        <sv:PickerCell Title="Favorites" ItemsSource="{Binding ItemsSource}" DisplayMember="Name" MaxSelectedNumber="3" 
        SelectedItems="{Binding SelectedItems}" KeepSelectedUntilBack="true" PageTitle="select 3 items" />
        <sv:NumberPickerCell Title="NumberPicker" Min="0" Max="99" Number="15" PickerTitle="Select number" />
        <sv:TimePickerCell Title="TimePicker" Format="HH:mm" Time="15:30" PickerTitle="Select time" />
        <sv:DatePickerCell Title="DatePicker" Format="yyyy/MM/dd (ddd)" Date="2017/11/11" MinimumDate="2015/1/1" MaximumDate="2018/12/15" TodayText="Today's date"/>
        <sv:EntryCell Title="EntryCell" ValueText="{Binding InputText.Value}" Placeholder="Input text" Keyboard="Email" TextAlignment="End" HintText="{Binding InputError.Value}" />
    </sv:Section>

</sv:SettingsView>
</ContentPage>

SettingsView properties settings may as well be witten in App.xaml. For example...

<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:sv="clr-namespace:AiForms.Settings;assembly=SettingsView"
             x:Class="Sample.App">
    <Application.Resources>
        <ResourceDictionary>
            <Color x:Key="AccentColor">#FFBF00</Color>
            <Color x:Key="DisabledColor">#E6DAB9</Color>
            <Color x:Key="TitleTextColor">#CC9900</Color>
            <Color x:Key="PaleBackColorPrimary">#F2EFE6</Color>
            <Color x:Key="PaleBackColorSecondary">#F2EDDA</Color>
            <Color x:Key="DeepTextColor">#555555</Color>
            <Color x:Key="NormalTextColor">#666666</Color>
            <Color x:Key="PaleTextColor">#999999</Color>
            <x:Double x:Key="BaseFontSize">12</x:Double>
            <x:Double x:Key="BaseFontSize+">14</x:Double>
            <x:Double x:Key="BaseFontSize++">17</x:Double>
            <x:Double x:Key="BaseFontSize-">11</x:Double>

            <Style TargetType="sv:SettingsView">
                <Setter Property="SeparatorColor" Value="{StaticResource DisabledColor}" />
                <Setter Property="BackgroundColor" Value="{StaticResource PaleBackColorPrimary}" />
                <Setter Property="HeaderBackgroundColor" Value="{StaticResource PaleBackColorPrimary}" />
                <Setter Property="CellBackgroundColor" Value="{StaticResource AppBackground}" />
                <Setter Property="CellTitleColor" Value="{StaticResource DeepTextColor}" />
                <Setter Property="CellValueTextColor" Value="{StaticResource NormalTextColor}" />
                <Setter Property="CellTitleFontSize" Value="{StaticResource BaseFontSize++}" />
                <Setter Property="CellValueTextFontSize" Value="{StaticResource BaseFontSize}" />
                <Setter Property="CellDescriptionColor" Value="{StaticResource NormalTextColor}" />
                <Setter Property="CellDescriptionFontSize" Value="{StaticResource BaseFontSize-}" />
                <Setter Property="CellAccentColor" Value="{StaticResource AccentColor}" />
                <Setter Property="SelectedColor" Value="#50FFBF00" />
                <Setter Property="HeaderTextColor" Value="{StaticResource TitleTextColor}" />
                <Setter Property="FooterFontSize" Value="{StaticResource BaseFontSize-}" />
                <Setter Property="FooterTextColor" Value="{StaticResource PaleTextColor}" />
            </Style>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Whereby any SettingsView in App will become the same property setttings.

SettingsView Properties

To fit SettingsView height to visible content

If SettingsView's total cells height is shorter than the parent view height, itself height can be fit total cells height as the following:

<sv:SettingsView x:Name="settings" HeightRequest="{Binding VisibleContentHeight,Source={x:Reference settings}}">
</sv:SettingsView>

Sample of ItemsSource and ItemTemplate for a root

public class SomeViewModel
{
    public List<MenuSection> ItemsSource {get;set;}

    public SomeViewModel()
    {
        ItemsSource = new List<MenuSection>{
            new new MenuSection("Select number",3){
                new MenuItem{Title = "3",Value=3},
                new MenuItem{Title = "4",Value=4},
            },
            new MenuSection("Select mode",1){
                new MenuItem{Title = "A",Value = 1},
                new MenuItem{Title = "B",Value = 2}
            }
        }
    }
}
public class MenuItem
{
    public string Title { get; set; }
    public int Value { get; set; }
}

public class MenuSection:List<MenuItem>
{
    public string SectionTitle { get; set; }
    public bool Selected { get;set; } // must implement INotifyPropertyChanged by some way

    public MenuSection(string title,int initalSelectedValue)
    {
        SectionTitle = title;
    }
}
<sv:SettingsView x:Name="Settings" ItemsSource="{Binding ItemsSource}">
    <sv:SettingsView.ItemTemplate>
        <DataTemplate>
            <sv:Section Title="{Binding SectionTitle}" ItemsSource="{Binding}" sv:RadioCell.SelectedValue="{Binding Selected}">
                <sv:Section.ItemTemplate>
                    <DataTemplate>
                        <sv:RadioCell Title="{Binding Title}" Value="{Binding Value}" />
                    </DataTemplate>
                </sv:Section.ItemTemplate>
            </sv:Section>
        </DataTemplate>
    </sv:SettingsView.ItemTemplate>
</sv:SettingsView>

SettingsView Methods

Section Properties

Example for Section HeaderView FooterView with XAML

<sv:Section>
    <sv:Section.HeaderView>
        <StackLayout>
            <Label Text="Header" />
        </StackLayout>
    </sv:Section.HeaderView>
    <sv:Section.FooterView>
        <Label Text="{Binding FooterText}" />
    </sv:Section.FooterView>
</sv:Section>

How to use an ItemsSource and an ItemTemplate for a Section

public class SomeModel
{
   // you should use a ObservableCollection if you use a dynamic list.
   public ObservableCollection<Option> Options {get;set;}
   public void SomeMethod()
   {
       Options = new ObservableCollection(GetServerData());
   }
}
public class Option
{
   public string Name {get;set;}
   public string Address {get;set;}
}
<sv:Section ItemsSource="{Binding Options}">
    <sv:Section.ItemTemplate>
        <DataTemplate>
            <sv:LabelCell Title="{Binding Name}" Value="{Binding Address}" />
        </DataTemplate>
    </sv:Section.ItemTemplate>
</sv:Section>

Cells

CellBase

Layout of cellbase

cell layout

Properties (all cell types)

Methods

To use SVG image

You can use SVG image if SvgImageSource is installed.

https://github.com/muak/SvgImageSource
https://www.nuget.org/packages/Xamarin.Forms.Svg/

Install-Package Xamain.Forms.Svg -pre

LabelCell

This is a cell showing read only text.

Properties

CommandCell

This is a Labelcell invoked an action.

Properties

The others are the same as LabelText.

ButtonCell

This is a simple cell invoked an action like a button.

Properties

This cell don't use Description property.

SwitchCell

This is a LabelCell equipped a switch.

Properties

CheckboxCell

This is a LabelCell equipped a checkbox.

Properties

RadioCell

This is the cell that can be selected just one item from in a Section or a SettingsView.

Properties

Attached Bindable Property

XAML Example

For a section

<sv:SettingsView>
    <sv:Section Title="Sound" sv:RadioCell.SelectedValue="{Binding SelectedItem}">
        <sv:RadioCell Title="Sound1" Value="{Binding Items[0]}">
        <sv:RadioCell Title="Sound2" Value="{Binding Items[1]}">
    </sv:Section>
</sv:SettingsView>

For global

<sv:SettingsView sv:RadioCell.SelectedValue="{Binding GlobalSelectedItem}">
    <sv:Section Title="Effect">
        <sv:RadioCell Title="Sound1" Value="{Binding Items[0]}">
        <sv:RadioCell Title="Sound2" Value="{Binding Items[1]}">
    </sv:Section>
    <sv:Section Title="Melody">
        <sv:RadioCell Title="Melody1" Value="{Binding Items[2]}">
        <sv:RadioCell Title="Melody2" Value="{Binding Items[3]}">
    </sv:Section>
</sv:SettingsView>

NumberPickerCell

This is a LabelCell calling a number picker.

Properties

This cell can't use ValueText property.

TimePickerCell

This is a LabelCell calling a time picker.

Properties

This cell can't use ValueText property.

DatePickerCell

This is a LabelCell calling a date picker.

Properties

This cell can't use ValueText property.

TextPickerCell

This is a LabelCell calling a text picker.

Properties

This cell can't use ValueText property.

PickerCell

This is a LabelCell calling a multiple select picker. When tapped on iOS, move next page and show picker there. When tapped on Android, show the picker on a dialog.

Properties

EntryCell

This is a cell inputing some text.

Properties

Methods

CustomCell

This is a cell that custom layout can be freely set in the center of Layout (blocks of the Title and ValueText and Description). The forms view can be specified with XAML.

It is envisaged that makes use of subclass of CustomCell.

Properties

Example for CustomCell

Contribution

We really appreciate your contribution. Please read the contribution guideline.

Contributors

Thanks

Donation

I am asking for your donation for continuous development🙇

Your donation will allow me to work harder and harder.

Sponsors

I am asking for sponsors too. This is a subscription.

License

MIT Licensed.

Some code is taken from .NET MAUI.

Material design icons - Apache License Version 2.0