Skip to content

Commit

Permalink
Merge pull request #3557 from unoplatform/dev/cdb/elevated-view
Browse files Browse the repository at this point in the history
Misc fixes around ElevatedView
  • Loading branch information
carldebilly authored Jul 20, 2020
2 parents c2be0d0 + 373842b commit aebe0eb
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 107 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions doc/articles/features/ElevatedView.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# ElevatedView
In many design languages (like [_Material Design_](https://material.io/design)), there's a notion of 'elevation' where a portion of the UI should be presented as being _elevated_ over the rest of the content.

In this case, UWP's native elevation API can't work on all platforms because of technical limitations. To address this problem, Uno provides a control called `ElevatedView`, able to produce a similar elevated effect on all platforms (UWP, Android, iOS, WebAssembly, and macOS).

This control is very useful to create cards with both rounded corners and an elevated effect - which could otherwise be challenging to produce on some platforms.

## How to use the `ElevatedView`

First you need to add the `toolkit` namespace in your XAML file:

```
xmlns:toolkit="using:Uno.UI.Toolkit"
```

After that, use the `ElevatedView` to host the content you need to be elevated:
``` xml
<StackPanel Orientation="Horizontal" Spacing="20">

<Button>Non-Elevated Button</Button>

<toolkit:ElevatedView Elevation="10">
<Button>Elevated Button</Button>
</toolkit:ElevatedView>

</StackPanel>
```

Will produce the following result:

![ElevatedView sample](../Assets/features/elevatedview/elevatedview-sample.png)

> **ATTENTION FOR UWP**: When there is an error seeing the `<toolkit:ElevatedView>` on UWP, the common mistake is to forget to include the `Uno.UI` package for all platforms, including UWP. On UWP, the only component that the `Uno.UI` package adds is the Toolkit.
## Settings

You can set the following properties:

* `Elevation`: numeric number representing the level of the elevation effect. Typical values are between 5 and 30. The default is `0` - no elevation.
* `ShadowColor`: By default the shadow will be `Black`, but you can set any other value. You can reduce the shadow effect by using the alpha channel [except Android]. On Android, the shadow color can only be changed since Android Pie (API 28+). The default is `Black` with alpha channel at 25%.
* `Background`: The default is `Transparent`. Setting `null` will remove the shadow effect.
* `CornerRadius`: Use it to create rounded corner effects. The shadow will follow them.

## Particularities

* Make sure to _give room_ for the shadow in the layout (eg by setting a `Margin` on the `ElevatedView`). Some platforms like macOS may clip the shadow otherwise. For the same reason, avoid wrapping the `<toolkit:ElevatedView>` directly in a `<ScrollViewer> ` because it's designed to clip its content.


68 changes: 35 additions & 33 deletions doc/articles/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,34 +50,52 @@
items:
- name: Accessibility
href: features/working-with-accessibility.md
- name: XAML Hot Reload
href: features\working-with-xaml-hot-reload.md
- name: Assets
href: features/working-with-assets.md
- name: Animations
href: features/working-with-animations.md
- name: Assets
href: features/working-with-assets.md
- name: Lottie animations
href: features/Lottie.md
- name: ComboBox
href: controls\ComboBox.md
- name: CommandBar
href: controls\commandbar.md
- name: Custom fonts
href: features/custom-fonts.md
- name: ElevatedView
href: features\ElevatedView.md
- name: ListView and GridView
href: controls\ListViewBase.md
- name: MapControl
href: controls\map-control-support.md
- name: MediaPlayerElement
href: controls\MediaPlayerElement.md
- name: MenuFlyout
href: controls\MenuFlyout.md
- name: PasswordVault
href: features\PasswordVault.md
- name: Pivot
href: controls\Pivot.md
- name: PowerManager
href: features/windows-system-power.md
- name: ProgressRing
href: features/progressring.md
- name: Shapes & Brushes
href: features/shapes-and-brushes.md
- name: Speech Recognition
href: features/SpeechRecognition.md
- name: Themes
href: features/working-with-themes.md
- name: ToggleSwitch
href: controls\ToggleSwitch.md
- name: Routed Events
href: features/routed-events.md
- name: x:Bind
href: features\windows-ui-xaml-xbind.md
- name: Shapes & Brushes
href: features/shapes-and-brushes.md
- name: Speech Recognition
href: features/SpeechRecognition.md
- name: PowerManager
href: features/windows-system-power.md
- name: ProgressRing
href: features/progressring.md
- name: PasswordVault
href: features\PasswordVault.md
- name: URI Protocol activation
href: features\protocol-activation.md
- name: VisibleBoundsPadding
href: features\VisibleBoundsPadding.md
- name: Windows.ApplicationModel
href: features\windows-applicationmodel.md
- name: Windows.ApplicationModel.Calls
Expand All @@ -101,29 +119,13 @@
- name: Windows.System.Display
href: features\windows-system-display.md
- name: Windows.System.Profile
href: features/windows-system-profile.md
href: features\windows-system-profile.md
- name: Windows.Storage
href: features\windows-storage.md
- name: Windows.UI.ViewManagement
href: features\windows-ui-viewmanagement.md
- name: CommandBar
href: controls\commandbar.md
- name: ListView and GridView
href: controls\ListViewBase.md
- name: ComboBox
href: controls\ComboBox.md
- name: MapControl
href: controls\map-control-support.md
- name: MediaPlayerElement
href: controls\MediaPlayerElement.md
- name: Pivot
href: controls\Pivot.md
- name: ToggleSwitch
href: controls\ToggleSwitch.md
- name: MenuFlyout
href: controls\MenuFlyout.md
- name: VisibleBoundsPadding
href: features\VisibleBoundsPadding.md
- name: XAML Hot Reload
href: features\working-with-xaml-hot-reload.md
- name: Using Uno - implemented views
href: implemented/toc.yml
topicHref: implemented-views.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ public KeyValuePair<string, string>[] Generate()

var resourceKeys = GetResourceKeys();
var filesFull = new XamlFileParser(_excludeXamlNamespaces, _includeXamlNamespaces).ParseFiles(_xamlSourceFiles);
var files = filesFull.Trim()
var files = filesFull
.Trim()
.OrderBy(f => f.UniqueID)
.ToArray();

Expand All @@ -224,33 +225,34 @@ public KeyValuePair<string, string>[] Generate()
.ToArray();

var outputFiles = filesQuery
.Distinct()
#if !DEBUG
.AsParallel()
.AsParallel()
#endif
.Select(file => new KeyValuePair<string, string>(
file.UniqueID,
new XamlFileGenerator(
file: file,
targetPath: _targetPath,
defaultNamespace: _defaultNamespace,
metadataHelper: _metadataHelper,
fileUniqueId: file.UniqueID,
lastReferenceUpdateTime: lastBinaryUpdateTime,
analyzerSuppressions: _analyzerSuppressions,
globalStaticResourcesMap: globalStaticResourcesMap,
outputSourceComments: _outputSourceComments,
resourceKeys: resourceKeys,
isUiAutomationMappingEnabled: _isUiAutomationMappingEnabled,
uiAutomationMappings: _uiAutomationMappings,
defaultLanguage: _defaultLanguage,
isWasm: _isWasm,
isDebug: _isDebug,
skipUserControlsInVisualTree: _skipUserControlsInVisualTree,
shouldAnnotateGeneratedXaml: _shouldAnnotateGeneratedXaml,
isUnoAssembly: IsUnoAssembly
.Select(file => new KeyValuePair<string, string>(
file.UniqueID,
new XamlFileGenerator(
file: file,
targetPath: _targetPath,
defaultNamespace: _defaultNamespace,
metadataHelper: _metadataHelper,
fileUniqueId: file.UniqueID,
lastReferenceUpdateTime: lastBinaryUpdateTime,
analyzerSuppressions: _analyzerSuppressions,
globalStaticResourcesMap: globalStaticResourcesMap,
outputSourceComments: _outputSourceComments,
resourceKeys: resourceKeys,
isUiAutomationMappingEnabled: _isUiAutomationMappingEnabled,
uiAutomationMappings: _uiAutomationMappings,
defaultLanguage: _defaultLanguage,
isWasm: _isWasm,
isDebug: _isDebug,
skipUserControlsInVisualTree: _skipUserControlsInVisualTree,
shouldAnnotateGeneratedXaml: _shouldAnnotateGeneratedXaml,
isUnoAssembly: IsUnoAssembly
)
.GenerateFile()
)
.GenerateFile()
)
)
.ToList();

Expand Down Expand Up @@ -474,7 +476,10 @@ private string GenerateGlobalResources(IEnumerable<XamlFileDefinition> files, Xa
using (writer.BlockInvariant("public sealed partial class GlobalStaticResources"))
{
writer.AppendLineInvariant("static bool _initialized;");
writer.AppendLineInvariant("private static bool _stylesRegistered;");
if (files.Any())
{
writer.AppendLineInvariant("private static bool _stylesRegistered;");
}
if (!IsUnoAssembly)
{
writer.AppendLineInvariant("private static bool _dictionariesRegistered;");
Expand Down Expand Up @@ -540,12 +545,15 @@ private string GenerateGlobalResources(IEnumerable<XamlFileDefinition> files, Xa

using (writer.BlockInvariant("public static void RegisterDefaultStyles()"))
{
using (writer.BlockInvariant("if(!_stylesRegistered)"))
if (files.Any())
{
writer.AppendLineInvariant("_stylesRegistered = true;");
foreach (var file in files)
using (writer.BlockInvariant("if(!_stylesRegistered)"))
{
writer.AppendLineInvariant("RegisterDefaultStyles_{0}();", file.UniqueID);
writer.AppendLineInvariant("_stylesRegistered = true;");
foreach (var file in files.Select(f=>f.UniqueID).Distinct())
{
writer.AppendLineInvariant("RegisterDefaultStyles_{0}();", file);
}
}
}
}
Expand All @@ -560,7 +568,8 @@ private string GenerateGlobalResources(IEnumerable<XamlFileDefinition> files, Xa
writer.AppendLineInvariant("_dictionariesRegistered = true;");
foreach (var file in files.Where(IsResourceDictionary))
{
writer.AppendLineInvariant("global::Uno.UI.ResourceResolver.RegisterResourceDictionaryBySource(uri: \"ms-appx:///{0}/{1}\", context: {2}, dictionary: () => {3}_ResourceDictionary);",
writer.AppendLineInvariant(
"global::Uno.UI.ResourceResolver.RegisterResourceDictionaryBySource(uri: \"ms-appx:///{0}/{1}\", context: {2}, dictionary: () => {3}_ResourceDictionary);",
_metadataHelper.AssemblyName,
map.GetSourceLink(file),
ParseContextPropertyName,
Expand Down Expand Up @@ -600,9 +609,9 @@ private string GenerateGlobalResources(IEnumerable<XamlFileDefinition> files, Xa

// Generate all the partial methods, even if they don't exist. That avoids
// having to sync the generation of the files with this global table.
foreach (var file in files)
foreach (var file in files.Select(f=>f.UniqueID).Distinct())
{
writer.AppendLineInvariant("static partial void RegisterDefaultStyles_{0}();", file.UniqueID);
writer.AppendLineInvariant("static partial void RegisterDefaultStyles_{0}();", file);
}

writer.AppendLineInvariant("[global::System.Obsolete(\"This method is provided for binary backward compatibility. It will always return null.\")]");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Uno.UI.SourceGenerators.Helpers;
using Uno.UI.SourceGenerators.XamlGenerator.XamlRedirection;

namespace Uno.UI.SourceGenerators.XamlGenerator
{
internal class XamlFileDefinition
internal class XamlFileDefinition : IEquatable<XamlFileDefinition>
{
public XamlFileDefinition(string file)
{
Expand All @@ -38,6 +36,7 @@ public XamlFileDefinition(string file)
public string UniqueID { get; }

private int? _shortId;

/// <summary>
/// Compact unique ID, used to name associated global members.
/// </summary>
Expand All @@ -54,5 +53,30 @@ public int ShortId
_shortId = value;
}
}

public bool Equals(XamlFileDefinition other)
{
if (other is null)
{
return false;
}

return ReferenceEquals(this, other)
|| string.Equals(UniqueID, other.UniqueID, StringComparison.InvariantCultureIgnoreCase);

}

public override bool Equals(object obj)
{
if (obj is XamlFileDefinition xfd)
{
return ReferenceEquals(this, xfd)
|| string.Equals(UniqueID, xfd.UniqueID, StringComparison.InvariantCultureIgnoreCase);
}

return false;
}

public override int GetHashCode() => (UniqueID != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(UniqueID) : 0);
}
}
6 changes: 3 additions & 3 deletions src/Uno.UI.Toolkit/ElevatedView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public sealed partial class ElevatedView : Control
public ElevatedView()
{
DefaultStyleKey = typeof(ElevatedView);
Background = new SolidColorBrush(Colors.Transparent);

#if !NETFX_CORE
Loaded += (snd, evt) => SynchronizeContentTemplatedParent();
Expand Down Expand Up @@ -129,7 +130,7 @@ private void SynchronizeContentTemplatedParent()
{
// Manual propagation of the templated parent to the content property
// until we get the propagation running properly
if (ElevatedContent is IFrameworkElement content)
if (ElevatedContent is FrameworkElement content)
{
content.TemplatedParent = this.TemplatedParent;
}
Expand Down Expand Up @@ -158,14 +159,13 @@ private void UpdateElevation()
#if __WASM__
this.SetElevationInternal(Elevation, ShadowColor);
this.SetCornerRadius(CornerRadius);
#elif __IOS__
#elif __IOS__ || __MACOS__
this.SetElevationInternal(Elevation, ShadowColor, _border.BoundsPath);
#elif __ANDROID__
_border.SetElevationInternal(Elevation, ShadowColor);
#elif NETFX_CORE
(ElevatedContent as DependencyObject).SetElevationInternal(Elevation, ShadowColor, _shadowHost as DependencyObject, CornerRadius);
#endif
// TODO: MacOS
}
}

Expand Down
Loading

0 comments on commit aebe0eb

Please sign in to comment.