CommunityToolkit / CommunityToolkit/Maui
[Proposal] OnScreenSize Markup
- Dominant language
- C#
- Stars
- 2.7k
- Forks
- 500
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 7
Description
# OnScreenSize Markup
* [x] Proposed
* [x] Prototype: [Repo](https://github.com/carolzbnbr/OnScreenSizeMarkup) and [nuget](https://www.nuget.org/packages/OnScreenSizeMarkup.Forms)
* [x] Implementation: Works for Xamarin, I will port to Maui.
* [x] iOS Support
* [x] Android Support
* [ ] macOS Support
* [ ] Windows Support
* [ ] Unit Tests: Not Started
* [ ] Sample: Not Started
* [x] Documentation: Needs improvements
## Link to Discussion
Please link to the completed/approved [Discussion](https://github.com/CommunityToolkit/Maui/discussions/422)
## Summary
[summary]: #summary
OnScreenSize Markup: A Markup for controlling Views according to a category a screen size fits in (Small, Medium, Large, ExtraLarge, etc).
## Detailed Design
[design]: #detailed-design
**ScreenCategories.cs** enum:
Depending on the screen-size (Width/Heigh), or a device model is, a `ScreenCategories` enum is used.
```cs
public enum ScreenCategories
{
ExtraSmall = 1,
Small = 2,
Medium = 3,
Large = 4,
ExtraLarge = 5,
NotSet = 6,
}
}
```
**ICategoryFallbackHandler.cs**:
This interface is used to determine the category a device fits in, during first execution we attempt to execute `TryGetCategoryByDeviceModel` and wether it returns false, we attempt to execute `TryGetCategoryByPhysicalSize`
```cs
public interface ICategoryFallbackHandler
{
bool TryGetCategoryByDeviceModel(string deviceModel, out ScreenCategories category);
bool TryGetCategoryByPhysicalSize(double deviceWidth, double deviceHeight, out ScreenCategories category);
}
```
**OnScreenSize.cs**:
The markup itself.
1. During the first run, the methods `ICategoryFallbackHandler.TryGetCategoryByDeviceModel` and `ICategoryFallbackHandler.TryGetCategoryByPhysicalSize` are called to determine the `Device Category` a device fits in, and after that, its result is cached to optimize next runs.
2. Depending on the `Device Category` a device was categorized, a value will be obtained from it's corresponding Markup's property.
For instance: If device category was categorized a `Large`, the markup will attempt to get the value from property `OnScreenSize.Large`.
3. In case a markup property is not defined, it will attempt to use the value from the `OnScreenSize.DefaultSize`.
**Note:** Before returning, each markup property's value are attempted to be converted to its property-type, making it possible to have a batter user experience, but allowing values to be converted to `GridLength`, `Colors`, `Thinkness`, `RowDefinition`, `ColumnDefinition`, and etc.
```cs
public class OnScreenSize : IMarkupExtension
{
public OnScreenSize();
public object DefaultSize { get; set; }
public object ExtraSmall {get;set;}
public object Small {get;set;}
public object Medium {get;set;}
public object Large {get;set;}
public object ExtraLarge {get;set;}
public object ProvideValue(IServiceProvider serviceProvider);
}
```
## Usage Syntax
[usage]: #usage-syntax
### XAML Usage
```xml
```
```xml
<Setter Property="RowDefinitions">
<markups:OnScreenSize>
<markups:OnScreenSize.Small>0.25*, 0.13*, 0.08*, 230, *</markups:OnScreenSize.Small>
<markups:OnScreenSize.Large>0.15*, 0.1*, 0.01*, 290, *</markups:OnScreenSize.Large>
<markups:OnScreenSize.DefaultSize>0.15*, 0.1*, 0.01*, 290, *</markups:OnScreenSize.DefaultSize>
</markups:OnScreenSize>
</Setter>
<Setter Property="ColumnDefinitions">
<markups:OnScreenSize>
<markups:OnScreenSize.Small>*, 230, *</markups:OnScreenSize.Small>
<markups:OnScreenSize.Large>*, 290, *</markups:OnScreenSize.Large>
<markups:OnScreenSize.DefaultSize>*, 290, *</markups:OnScreenSize.DefaultSize>
</markups:OnScreenSize>
</Setter>
...
```
### C# Usage
There is no code-equivalent for instantiating a Markup, since `IServiceProvider` instance from `OnScreenSize.ProvideValue(IServiceProvider serviceProvider)` is only available via XAML.
Contributor guide
Assessment
This issue has not been assessed yet.