• Stars
    star
    329
  • Rank 128,030 (Top 3 %)
  • Language
    C#
  • License
    MIT License
  • Created over 4 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Add as many custom shadows (Color, Offset, Blur, Neumorphism) as you like to any Xamarin.Forms view (Android, iOS, UWP).

Sharpnado.Shadows

Get it from NuGet:

Nuget

Supported platforms
βœ”οΈ Android
βœ”οΈ iOS
βœ”οΈ UWP
βœ”οΈ Tizen

Presentation

Initialization

  • On Core project in App.xaml.cs:

For the namespace schema to work, you need to call initializer from App.xaml.cs like this:

public App()
{
    InitializeComponent();

    Sharpnado.Shades.Initializer.Initialize(loggerEnable: false);
    ...
}
  • On iOS add this line after Xamarin.Forms.Forms.Init() and before LoadApplication(new App()).

Sharpnado.Shades.iOS.iOSShadowsRenderer.Initialize();

  • On UWP, you must register the renderers assembly like this, before Xamarin.Forms.Forms.Init():

var rendererAssemblies = new[] { typeof(UWPShadowsRenderer).GetTypeInfo().Assembly };

  • On Tizen add this line after Xamarin.Forms.Forms.Init() and before LoadApplication(new App()).

Sharpnado.Shades.Tizen.TizenShadowsRenderer.Initialize();

Presentation

Add as many custom shadows as you like to any Xamarin.Forms view (Android, iOS, UWP, Tizen).

  • You can specify each shadow Color, Opacity, BlurRadius, and Offset
  • Simply implement Neumorphism
  • You can add one shadow, 3 shadows, 99 shadows, to any Xamarin.Forms element
  • Animate any of these property and make the shadows dance around your elements
  • No AndroidX or SkiaSharp dependency required (except Tizen), only Xamarin.Forms

Animating shadows

Rendering Shadows is cpu intensive (especially on Android).

Using Xamarin.Forms animation API whith shadows is totally fine: it won't recreate the Shadows bitmaps.

However, animating the color, blur, opacity or size of a Shade, will result in creating multiple bitmap on Android.

Therefore if you want to animate the size of a view which is using Shadows, you should "disable" the shadows during the animation.

<sh:Shadows x:Name="MyViewShadows"
            CornerRadius="30"
            Shades="{sh:SingleShade Offset='0, 10',
                                    Opacity=0.7,
                                    Color=Violet}">
    <mine:SuperCustomView x:Name="MyView" />
</sh:Shadows>
private async Task MyViewTotallyFineAnimations()
{
    // Nothing to disable here
    await MyView.RotateXTo(90);
    await MyView.ScaleTo(2);
    await MyView.RotateXTo(0);
    await MyView.ScaleTo(1);
}

private async Task MyViewNeedsDisableShadowsAnimation()
{
    var shades = MyViewShadows.Shades;
    
    // Disabling shadows
    MyViewShadows.Shades = new List<Shades>();

    await MyView.AnimateWidthRequestAsync();
    
    // Restoring shadows
    MyViewShadows.Shades = shades;
}

Shadows for Xamarin.Forms components creators

Shadows has been developed with modularity in mind, making it really easy to integrate into your own components.

Read the wiki doc: https://github.com/roubachof/Sharpnado.Shadows/wiki/Shadows-for-Xamarin.Forms-components-builders.

Using Shadows

Shadows is a container for any Xamarin.Forms view. Just wrap your view in it and start adding shadows:

XAML

<sh:Shadows x:Name="CatShadows"
            CornerRadius="10">
    <sh:Shadows.Shades>
        <sh:ImmutableShades>
            <sh:Shade BlurRadius="10"
                      Opacity="0.5"
                      Offset="-10,-10"
                      Color="#FE99FE" />
            <sh:Shade BlurRadius="10"
                      Opacity="0.5"
                      Offset="10,10"
                      Color="#00B0FB" />
        </sh:ImmutableShades>
    </sh:Shadows.Shades>
    <Frame WidthRequest="80"
           Padding="10"
           HorizontalOptions="Center"
           VerticalOptions="Center"
           BackgroundColor="White"
           CornerRadius="10">
        <Image Source="{images:ImageResource nyan_cat.png}" />
    </Frame>
</sh:Shadows>

OUTPUT

Thanks to the CornerRadius property you can match your target corner to achieve a perfect shadow. For example, you can add a shadow to a rounded button:

XAML

<sh:Shadows CornerRadius="30"
            Shades="{sh:SingleShade Offset='0, 10',
                                    Opacity=0.7,
                                    Color=Violet}">
    <ImageButton WidthRequest="60"
                 HeightRequest="60"
                 Padding="20"
                 HorizontalOptions="Center"
                 VerticalOptions="Center"
                 BackgroundColor="Violet"
                 CornerRadius="30"
                 Source="{StaticResource IconPlusWhite}" />
</sh:Shadows>

OUTPUT

Choose your Shade Collection

You can use several type of IEnumerable<Shade>:

1. ReadOnlyCollection

This is what you want to use most of the time. All the different IMarkupExtension like ImmutableShades, NeumorphismShades, SingleShade, return a ReadOnlyCollection<Shade>. If you use a ReadOnlyCollection<Shade>, all shades will be cloned to be sure the immutability is respected. It means, you can specify shades as static objects in your ResourceDictionary, it won't create any leak or view hierarchy issues.

<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    xmlns:sh="clr-namespace:Sharpnado.Shades;assembly=Sharpnado.Shadows">
    <sh:SingleShade x:Key="ShadowTop"
                    BlurRadius="6"
                    Opacity="0.15"
                    Offset="0,-8"
                    Color="{StaticResource ShadowsColor}" />

    <sh:SingleShade x:Key="ShadowBottom"
                    BlurRadius="6"
                    Opacity="0.1"
                    Offset="0,5"
                    Color="{StaticResource ShadowsColor}" />

    <sh:SingleShade x:Key="ShadowAccentBottom"
                    BlurRadius="6"
                    Opacity="0.4"
                    Offset="0,4"
                    Color="{StaticResource AccentColor}" />

    <sh:ImmutableShades x:Key="ShadowNone" />

    <sh:NeumorphismShades x:Key="ShadowNeumorphism" />

    <sh:NeumorphismShades x:Key="ShadowThinNeumorphism"
                          LowerOffset="8, 6"
                          UpperOffset="-8,-6" />
</ResourceDictionary>

2. ObservableCollection

Only if you want to dynamically add or remove shade during the view lifetime.

3. All other IEnumerable

If you want to modify a shade property during the view lifetime.

IMPORTANT: if you don't use a ReadOnlyCollection<Shade> please be sure to declare your Shade as transient. It means you should declare a new instance of Shade for each Shadows views. For example, in code-behind with new Shade(), or in xaml with Shades property. Just don't reference static instances of shade from ResourceDictionary with StaticResource references, or even in a C# class.

Shades

The Shadows component has only 2 properties:

  1. int CornerRadius which should be equal to the component's child view CornerRadius to achieve a good shadow effect,
  2. IEnumerable<Shade> Shades which is the enumeration of all the shades this shadow is made of.

A shade is what you could call a "sub-shadow".

Each shade has 4 properties:

  1. Point Offset: the offset of the shade
  2. Color Color: the color of the shade
  3. double Opacity: the opacity of the shade
  4. double BlurRadius: the amount of blur your want for this shade

Logo.xaml

<?xml version="1.0" encoding="UTF-8" ?>
<sh:Shadows x:Class="ShadowsSample.Views.Logo"
            xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:sh="http://sharpnado.com/schemas/shadows"
            CornerRadius="3">
    <sh:Shadows.Shades>
        <sh:ImmutableShades>
            <sh:Shade BlurRadius="10"
                      Opacity="1"
                      Offset="-15,-15"
                      Color="Yellow" />
            <sh:Shade BlurRadius="10"
                      Opacity="1"
                      Offset="15,15"
                      Color="Yellow" />
            <sh:Shade BlurRadius="10"
                      Opacity="1"
                      Offset="-15,15"
                      Color="Violet" />
            <sh:Shade BlurRadius="10"
                      Opacity="1"
                      Offset="15,-15"
                      Color="Violet" />
            <sh:Shade BlurRadius="5"
                      Opacity="1"
                      Offset="-5,-5"
                      Color="DeepSkyBlue" />
            <sh:Shade BlurRadius="5"
                      Opacity="1"
                      Offset="5,5"
                      Color="DeepSkyBlue" />
            <sh:Shade BlurRadius="5"
                      Opacity="1"
                      Offset="0,0"
                      Color="White" />
        </sh:ImmutableShades>
    </sh:Shadows.Shades>
    <Label Style="{StaticResource TextHuge}"
           VerticalOptions="Center"
           FontFamily="{StaticResource FontKarmatic}"
           Text="Shadows" />
</sh:Shadows>

OUTPUT

Neumorphism

To have a nice Neumorphism effect we need to choose a background color. I found that #F0F0F3 was quite good, so I will stick to it for our content and our page background color.

Since Neumorphism implementation is made of 2 shadows, one bright at the top left, one dark at the bottom right, achieving a Neumorphism style with Shadows for all the views is really easy:

<Style ApplyToDerivedTypes="True" TargetType="sh:Shadows">
    <Setter Property="CornerRadius" Value="10" />
    <Setter Property="Shades">
        <sh:ImmutableShades>
            <sh:Shade BlurRadius="10"
                      Opacity="1"
                      Offset="-10,-10"
                      Color="White" />
            <sh:Shade BlurRadius="10"
                      Opacity="1"
                      Offset="6, 6"
                      Color="#19000000" />
        </sh:ImmutableShades>
    </Setter>
</Style>

If you want to add Neumorphism to specific elements a NeumorphismShades markup extension will help you with that:

XAML

<sh:Shadows Grid.Row="1"
            Grid.Column="0"
            CornerRadius="40"
            Shades="{sh:NeumorphismShades}">
    <ImageButton WidthRequest="60"
                 HeightRequest="60"
                 Padding="20"
                 HorizontalOptions="Center"
                 VerticalOptions="Center"
                 BackgroundColor="#F0F0F3"
                 CornerRadius="30"
                 Source="{StaticResource IconPlusGray}" />
</sh:Shadows>

<sh:Shadows Grid.Row="1"
            Grid.Column="1"
            CornerRadius="10"
            Shades="{sh:NeumorphismShades}">
    <Button Style="{StaticResource TextHeadline}"
            WidthRequest="120"
            HeightRequest="60"
            HorizontalOptions="Center"
            VerticalOptions="Center"
            BackgroundColor="#F0F0F3"
            CornerRadius="10"
            Text="Reset"
            TextColor="Gray" />
</sh:Shadows>

OUTPUT

Be creative!

One last thing: all properties of a Shade are animatable.

You can achieve nice effects thinking outside the box! Have a look at the BeCreative.xaml file and its code-behind.

BeCreative

Immutable and mutable collections of shades

To have a better control of your shades, Shadows provides 2 kinds of MarkupExtension:

  1. One immutable collection of shades: ImmutableShades (readonly type)
  2. One mutable collection: ShadeStack (observable collection type)

Use the first one if the shade collection will not change and the second one if you want to dynamically add or remove shades.

Dynamic shades starting with 0 shade.

<sh:Shadows CornerRadius="10">
    <sh:Shadows.Shades>
        <sh:ShadeStack />
    </sh:Shadows.Shades>
    <Frame WidthRequest="80"
           Padding="10"
           HorizontalOptions="Center"
           VerticalOptions="Center"
           BackgroundColor="White"
           CornerRadius="10">
        <Image Source="{images:ImageResource nyan_cat.png}" />
    </Frame>
</sh:Shadows>

SingleShade

You can also use the SingleShade markup extension if you just have one shadow. It will remove some xaml elements:

<sh:Shadows CornerRadius="30"
            Shades="{sh:SingleShade Offset='0, 10',
                                    Opacity=0.7,
                                    Color=Violet}">
    <ImageButton WidthRequest="60"
                 HeightRequest="60"
                 Padding="20"
                 HorizontalOptions="Center"
                 VerticalOptions="Center"
                 BackgroundColor="Violet"
                 CornerRadius="30"
                 Source="{StaticResource IconPlusWhite}" />
</sh:Shadows>

Performance

Warning: be sure to have the latest version of Shadows installed. Very big performance improvements (bitmap caching) have been implement in version 1.2.

  • On Android, shadows are created thanks to RenderScript. Bitmaps are cached in a global BitmapCache. For a particular color, size and blur, you will only have one instance alive.
  • On iOS, a Shade is implemented with a simple CALayer
  • On UWP, Shade is implemented with SpriteVisual drop shadows.
  • On Tizen, Shade is implemented with SkiaSharp.

More Repositories

1

Sharpnado.Presentation.Forms

Presentation layer: Xamarin Forms custom components and renderers
596
star
2

Sharpnado.MaterialFrame

A modern MAUI (and XF) Frame component supporting blur, acrylic, dark mode. Implemented with RealtimeBlurView on Android (custom blurview) and UIVisualEffectView on iOS.
C#
463
star
3

Sharpnado.Tabs

Pure MAUI and Xamarin.Forms Tabs, including fixed tabs, scrollable tabs, bottom tabs, badge, segmented control, custom tabs, button tabs, bendable tabs...
C#
416
star
4

Xamarin-Forms-Practices

Collection of good practices for Xamarin forms developement
C#
289
star
5

Sharpnado.TaskLoaderView

Free yourself from IsBusy=true! The `TaskLoaderView` is a UI component that handles all your UI loading state (Loading, Error, Result, Notification), and removes all the pain of async loading from your view models (try catch / async void / IsBusy / HasErrors / base view models / ...) thanks to its brother the `TaskLoaderNotifier`.
C#
222
star
6

Sharpnado.CollectionView

A performant list view supporting: grid, horizontal and vertical layout, drag and drop, and reveal animations.
C#
217
star
7

Xamarin.Forms.Nuke

The famous iOS Nuke native image caching library for Xamarin.Forms
C#
123
star
8

Sharpnado.TaskMonitor

Free yourself from async void! TaskMonitor is a component (a task wrapper) helping you to deal with "fire and forget" Task (non awaited Task) by implementing async/await best practices.
C#
95
star
9

SkiaSharpnado

SkiaSharp components and case studies for Xamarin.Forms
C#
79
star
10

Maui.Nuke

Maui version of the Nuke iOS image caching native library
C#
38
star
11

falotier_riverpod

The purpose of this PoC is to implement main real life app use cases and see if Riverpod elegantly supports all the needed mutations.
Dart
36
star
12

Xamarin.Forms.ImageSourceHandlers

GlideX.Forms + FFImageLoading.ImageSourceHandler = complete image caching solution for Xamarin.Forms without changing any line of your current project.
C#
28
star
13

Sharpnado.Acrylic

Where Sharpnado is experimenting Acrylic effects.
C#
26
star
14

NukeProxy

C#
17
star
15

Mobile.Practices.Frameworkless

Best practices for Xamarin developpement post MVVM (without binding) (Xamarin.Android and iOS)
C#
8
star
16

Sharpnado.Infrastructure

C#
5
star
17

falotier_design

Dart
5
star
18

Sharpnado.HorizontalListView

Obsolete repository, the project has been renamed to Sharpnado.CollectionView
1
star
19

SLIDES_FreeYourselfFromIsBusy

JavaScript
1
star
20

Mvvm.Flux.Maui

Showcase the mvvm flux architecture (one-way update)
C#
1
star