Share via

windows phone live tile replica don't work

Eduardo Gomez Romero 1,315 Reputation points
Mar 4, 2025, 8:12 PM

Hello, I am a big fan of Microsoft live tiles (Windows phone days)

So I made my own

XML
 <StackLayout Padding="0">
       <control:LiveTileControl
           Title="My live tile"
           LiveTileBackgroundColor="Green"
           TitleColor="White"
           TitleFontAtributes="Bold"
           TitleFontSize="14"
           TitlePosition="LowerLeft"
           RefreshRate="5"
           IconSource="{Static font:FluentUI.people_12_regular}"
           TransparencyPercentage="30" />
   </StackLayout>

C#

TypeScript
using Microsoft.Maui.Controls.Shapes;

namespace LiveTileControl.Controls;
public partial class LiveTileControl : ContentView {
    #region Bindiable Properties 

    public static readonly BindableProperty TransparencyPercentageProperty = BindableProperty.Create(
        nameof(TransparencyPercentage),
        typeof(double),
        typeof(LiveTileControl),
        100.0,
        propertyChanged: OnTransparencyPercentageChanged);

    public static readonly BindableProperty LiveTileBackGroundProperty = BindableProperty.Create(
       nameof(LiveTileBackgroundColor),
       typeof(Color),
       typeof(LiveTileControl),
       Colors.Transparent);

    public static readonly BindableProperty IconSourceProperty = BindableProperty.Create(
        nameof(IconSource),
        typeof(string),
        typeof(LiveTileControl));

    public static readonly BindableProperty RefreshRateProperty = BindableProperty.Create(
        nameof(RefreshRate),
        typeof(int),
        typeof(LiveTileControl),
        30); // 30 seconds;

    public static readonly BindableProperty TitleProperty = BindableProperty.Create(
        nameof(Title),
        typeof(string),
        typeof(LiveTileControl));

    public static readonly BindableProperty TitleFontFamilyProperty = BindableProperty.Create(
        nameof(TitleFontFamily),
        typeof(string),
        typeof(LiveTileControl),
        "Default");

    public static readonly BindableProperty TitlePositionProperty = BindableProperty.Create(
        nameof(TitlePosition),
        typeof(TitlePositionEnum),
        typeof(LiveTileControl),
        TitlePositionEnum.LowerLeft);

    public static readonly BindableProperty TitleColorProperty = BindableProperty.Create(
        nameof(TitleColor),
        typeof(Color),
        typeof(LiveTileControl),
        Colors.Black);

    public static readonly BindableProperty TitleFontSizeProperty = BindableProperty.Create(
        nameof(TitleFontSize),
        typeof(int),
        typeof(LiveTileControl));

    public static readonly BindableProperty TitleFontAtributesProperty = BindableProperty.Create(
        nameof(TitleFontAtributes),
        typeof(FontAttributes),
        typeof(LiveTileControl));


    public TitlePositionEnum TitlePosition {
        get => (TitlePositionEnum)GetValue(TitlePositionProperty);
        set => SetValue(TitlePositionProperty, value);
    }

    private static void OnTransparencyPercentageChanged(BindableObject bindable, object oldValue, object newValue) {
        if(bindable is LiveTileControl control && newValue is double transparency) {

            control.UpdateBackgroundTransparency(transparency);
        }
    }

    private void UpdateBackgroundTransparency(double transparency) {
        // Convert the transparency percentage (0-100) to a float value (0.0-1.0)
        float alpha = (float)Math.Clamp(transparency / 100.0, 0.0, 1.0);

        var baseColor = BackgroundColor != null ? BackgroundColor : Colors.Transparent;

        // Update the BackgroundColorWithTransparency property with the new alpha value
        LiveTileBackgroundColor = baseColor.WithAlpha(alpha);
    }

    public double TransparencyPercentage {
        get => (double)GetValue(TransparencyPercentageProperty);
        set => SetValue(TransparencyPercentageProperty, value);
    }

    public Color LiveTileBackgroundColor {
        get => (Color)GetValue(LiveTileBackGroundProperty);
        set => SetValue(LiveTileBackGroundProperty, value);
    }

    public string IconSource {
        get => (string)GetValue(IconSourceProperty);
        set => SetValue(IconSourceProperty, value);
    }

    public int RefreshRate {
        get => (int)GetValue(RefreshRateProperty);
        set => SetValue(RefreshRateProperty, value);
    }

    public string Title {
        get => (string)GetValue(TitleProperty);
        set => SetValue(TitleProperty, value);
    }

    public string TitleFontFamily {
        get => (string)GetValue(TitleFontFamilyProperty);
        set => SetValue(TitleFontFamilyProperty, value);
    }

    public Color TitleColor {
        get => (Color)GetValue(TitleColorProperty);
        set => SetValue(TitleColorProperty, value);
    }

    public int TitleFontSize {
        get => (int)GetValue(TitleFontSizeProperty);
        set => SetValue(TitleFontSizeProperty, value);
    }

    public FontAttributes TitleFontAtributes {
        get => (FontAttributes)GetValue(TitleFontAtributesProperty);
        set => SetValue(TitleFontAtributesProperty, value);
    }

    #endregion

    #region This enum will be use for the position o the title

    public enum TitlePositionEnum {

        UpperLeft,
        UpperRight,
        LowerLeft,
        LowerRight,
        Center
    }

    #endregion


    private View CreateIcon() {
        return new Image {
            Source = IconSource,
            WidthRequest = 48,
            HeightRequest = 48,
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        };
    }

    private View CreateText() {

        var label = new Label {

            Text = Title,
            TextColor = TitleColor,
            FontFamily = TitleFontFamily,
            FontSize = TitleFontSize,
            FontAttributes = TitleFontAtributes
        };

        UpdateTextAlligment(label);

        return label;
    }

    private void UpdateTextAlligment(Label label) {

        switch(TitlePosition) {
            case TitlePositionEnum.UpperLeft:
                label.HorizontalOptions = LayoutOptions.Start;
                label.VerticalOptions = LayoutOptions.Start;
                break;
            case TitlePositionEnum.UpperRight:
                label.HorizontalOptions = LayoutOptions.End;
                label.VerticalOptions = LayoutOptions.Start;
                break;
            case TitlePositionEnum.LowerLeft:
                label.HorizontalOptions = LayoutOptions.Start;
                label.VerticalOptions = LayoutOptions.End;
                break;
            case TitlePositionEnum.LowerRight:
                label.HorizontalOptions = LayoutOptions.End;
                label.VerticalOptions = LayoutOptions.End;
                break;
            case TitlePositionEnum.Center:
                label.HorizontalOptions = LayoutOptions.Center;
                label.VerticalOptions = LayoutOptions.Center;
                break;
            default:
                label.HorizontalOptions = LayoutOptions.Center;
                label.VerticalOptions = LayoutOptions.Center;
                break;
        }
    }

    public async Task UpdateAnimation() {
        await this.ScaleTo(1.1, 150, Easing.CubicOut);
        await this.FadeTo(0.5, 150, Easing.CubicIn);
        await this.ScaleTo(1, 150, Easing.CubicOut);
        await this.FadeTo(1, 150, Easing.CubicIn);
    }

    public async void StartAutoRefresh() {
        // Use PeriodicTimer for periodic updates
        var timer = new PeriodicTimer(TimeSpan.FromSeconds(RefreshRate));

        // Loop to handle the timer ticks
        while(await timer.WaitForNextTickAsync()) {
            await Dispatcher.DispatchAsync(async () => {
                await UpdateAnimation(); // Trigger the animation

                // Fetch new data and update the UI
                string newData = await FetchData();
                UpdateContent(newData);
            });
        }
    }

    private async Task<string> FetchData() {
        try {
            using var httpClient = new HttpClient();
            var response = await httpClient.GetStringAsync("https://jsonplaceholder.typicode.com/posts/1");

            // Extract a portion of the response, e.g., the "title" field (you can use JSON parsing libraries like Newtonsoft.Json or System.Text.Json)
            return "Sample Data Fetched!"; // Replace this with parsed data

        } catch(Exception ex) {
            Console.WriteLine($"Error fetching data: {ex.Message}");
            return "Error Fetching Data";
        }
    }

    private void UpdateContent(string newData) {
        if(Content is Border border && border.Content is Grid grid) {
            foreach(var child in grid.Children) {
                if(child is Label label) {
                    label.Text = newData; // Update the text with the fetched data
                }
            }
        }
    }

    public LiveTileControl() {
        var grid = new Grid {
            HorizontalOptions = LayoutOptions.Fill,
            VerticalOptions = LayoutOptions.Fill
        };

        // Add the icon and title to the grid
        grid.Children.Add(CreateIcon());
        grid.Children.Add(CreateText());

        // Wrap the grid in a border for transparency and rounded corners
        var border = new Border {
            StrokeShape = new RoundRectangle {
                CornerRadius = new CornerRadius(10)
            },
            BackgroundColor = LiveTileBackgroundColor,
            Content = grid
        };

        // Set the border as the content of the LiveTileControl
        Content = border;
    }
}

Is still don't work as expended

User's image

is supposed to be green, with 30% transparency, animate, show the icon, print into console evetime the data is updated

also, I included the icon of fluentUI that Microsoft included in .Net (Microsoft Created the class but did not include the font itself,

User's image

and I modify the main

YAML
  fonts.AddFont("FluentSystemIcons-Regular.ttf", "FluentUI");
.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,982 questions
{count} votes

Accepted answer
  1. Yonglun Liu (Shanghai Wicresoft Co,.Ltd.) 49,126 Reputation points Microsoft External Staff
    Mar 5, 2025, 5:58 AM

    Hello,

    This is because in ContentView, when you assign a value to a property in the constructor, such as the Title property, the property value is null. That's why you can't see anything in the Border after running.

    You can assign values ​​to properties in the following ways.

    C#
    protected override void OnHandlerChanged()
    {
        base.OnHandlerChanged();
        var grid = new Grid
        {
            HorizontalOptions = LayoutOptions.Fill,
            VerticalOptions = LayoutOptions.Fill
        };
     
        // Add the icon and title to the grid
        grid.Children.Add(CreateIcon());
        grid.Children.Add(CreateText());
     
        // Wrap the grid in a border for transparency and rounded corners
        var border = new Border
        {
            StrokeShape = new RoundRectangle
            {
                CornerRadius = new CornerRadius(10)
            },
            BackgroundColor = LiveTileBackgroundColor,
            Content = grid
        };
     
        // Set the border as the content of the LiveTileControl
        Content = border;
    }
    

    Best Regards,

    Alec Liu.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.