• [UWP]实现一个轻量级的应用内消息通知控件


    在UWP应用开发中,我们常常有向用户发送一些提示性消息的需求。这种时候我们一般会选择MessageDialog、ContentDialog或者ToastNotification来完成功能。

    但是,我们大多数时候仅仅是需要在应用内向用户显示一条提示消息(例如“登录成功!”),不需要用户对这条消息做出处理,在这种情况下这几种方法都不算是很好的解决方式,它们不够轻量,也不够优雅,甚至会阻断用户的当前操作,这是我们所不期望的。

    如果有安卓平台开发经验的开发者,可能会想到Toast组件。对,为什么UWP平台没有类似Toast的轻量级应用内消息提示组件呢?

    现在,让我们来实现一个UWP可用的Toast组件。

    先放一张效果图:

    toast

    如何实现

    在之前《[UWP]使用Popup构建UWP Picker》中我们讲了Picker的实现过程,其中利用到的主要呈现手段就是Popup。而我们在这里想要构建一个代码中调用的消息通知组件,也可以采用同样的方式来实现。

    Toast的主要功能是呈现通知,所以我定义了下面几个依赖属性来控制:

    • Content:类型为string,设置要向用户呈现的消息内容;
    • Duration:类型为TimeSpan,设置Toast控件在屏幕上的呈现时长。

    在呈现逻辑上使用一个Popup作为加载Toast的容器。这里的逻辑非常简单,我直接贴出代码来,大家一看就能懂。

    核心代码如下:

    public class Toast : Control
    {
        // Using a DependencyProperty as the backing store for Content.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.Register("Content", typeof(string), typeof(Toast), new PropertyMetadata(0));
    
        // Using a DependencyProperty as the backing store for Duration.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DurationProperty =
            DependencyProperty.Register("Duration", typeof(TimeSpan), typeof(Toast),
                new PropertyMetadata(TimeSpan.FromSeconds(2.0)));
    
        public Toast(string content)
        {
            DefaultStyleKey = typeof(Toast);
            Content = content;
            Width = Window.Current.Bounds.Width;
            Height = Window.Current.Bounds.Height;
            Transitions = new TransitionCollection
            {
                new EntranceThemeTransition()
            };
            Window.Current.SizeChanged += Current_SizeChanged;
        }
    
        public TimeSpan Duration
        {
            get => (TimeSpan) GetValue(DurationProperty);
            set => SetValue(DurationProperty, value);
        }
    
        public string Content
        {
            get => (string) GetValue(ContentProperty);
            set => SetValue(ContentProperty, value);
        }
    
        private void Current_SizeChanged(object sender, WindowSizeChangedEventArgs e)
        {
            Width = Window.Current.Bounds.Width;
            Height = Window.Current.Bounds.Height;
        }
    
        public async void Show()
        {
            var popup = new Popup
            {
                IsOpen = true,
                Child = this
            };
            await Task.Delay(Duration);
            popup.Child = null;
            popup.IsOpen = false;
            Window.Current.SizeChanged -= Current_SizeChanged;
        }
    }
    

    上面代码中,我在构造函数里为Toast控件添加了一个默认的隐式动画EntranceThemeTransition,使它呈现出来的时候不会显得太生硬。

    Toast控件的默认样式:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:HHChaosToolkit.UWP.Controls">
        <Style TargetType="local:Toast">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:Toast">
                        <Border
                            Margin="0,0,0,60"
                            HorizontalAlignment="Center"
                            VerticalAlignment="Bottom"
                            Background="#af000000"
                            CornerRadius="4">
                            <TextBlock
                                Margin="30,15"
                                FontSize="14"
                                Foreground="White"
                                Text="{TemplateBinding Content}" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
    

    如何调用

    我们参考下安卓中Toast的使用方法:

    Toast.makeText(getApplicationContext(), "This is a sample toast.",Toast.LENGTH_SHORT).show();
    

    看起来挺长的一句代码,其实就是通过Toast.makeText()静态方法创建了一个新的Toast,然后调用其show()方法让它出现在手机屏幕上。

    在这里,我们也可以直接创建一个Toast,调用其Show()方法呈现。

    或者也可以创建一个ToastHelper静态类来更方便的使用Toast组件:

    public static class ToastHelper
    {
        public static void SendToast(string content, TimeSpan? duration = null)
        {
            var toast = new Toast(content);
            if (duration.HasValue)
            {
                toast.Duration = duration.Value;
            }
            toast.Show();
        }
    }
    

    自定义样式

    我们可以在自己的应用里为Toast组件新建一个资源字典,然后将自定义的样式添加在其中,例如:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:controls="using:HHChaosToolkit.UWP.Controls">
        <Style x:Key="CustomToastStyle" TargetType="controls:Toast">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="controls:Toast">
                        <Border
                            Width="160"
                            Height="160"
                            HorizontalAlignment="Center"
                            VerticalAlignment="Center"
                            Background="#af000000"
                            CornerRadius="4">
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition />
                                    <RowDefinition Height="Auto" />
                                </Grid.RowDefinitions>
                                <FontIcon
                                    FontFamily="Segoe MDL2 Assets"
                                    FontSize="50"
                                    Foreground="White"
                                    Glyph="&#xF1AD;" />
                                <TextBlock
                                    Grid.Row="1"
                                    Margin="30,0,30,15"
                                    FontSize="14"
                                    Foreground="White"
                                    TextWrapping="Wrap"
                                    Text="{TemplateBinding Content}" />
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
    

    然后在App.xaml中引入我们编写好的资源字典。

    <Application
        x:Class="HHChaosToolkit.Sample.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:HHChaosToolkit.Sample"
        xmlns:viewModels="using:HHChaosToolkit.Sample.ViewModels">
        <Application.Resources>
            <ResourceDictionary>
                <viewModels:ViewModelLocator x:Name="Locator" />
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="Themes/Toast.xaml" />
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>
    

    使用时,我们只需要为Toast控件设置预定义的样式即可,或者在我们上面写的ToastHelper类中增加调用自定义样式Toast的静态方法:

            public static void SendCustomToast(string content, TimeSpan? duration = null)
            {
                var toast = new Toast(content);
                toast.Style = App.Current.Resources["CustomToastStyle"] as Style;
                if (duration.HasValue)
                {
                    toast.Duration = duration.Value;
                }
                toast.Show();
            }
    

    结尾

    Toast组件是我的开源项目HHChaosToolkit项目中的一部分,其中还有一个与Toast原理差不多的组件WaitingDialog,原理是一样的,之后不会再单独写博文赘述了。

    完整的示例代码在这里(GitHub),欢迎大家随意吐槽&提意见!

    这篇博文到此结束,谢谢大家阅读!

  • 相关阅读:
    T-GCN: A Temporal Graph Convolutional Network for Traffic Prediction
    pandas.read_csv中的usecols函数实现读取指定列
    python3.7+tensorflow+keras的安装
    python操作word表格格式
    windows下pip换阿里云(贼快)
    Python中 sys.argv[]的用法简明解释
    ARIMA时间序列分析
    python--data.dropna
    查看linux系统的常用命令
    redis在php中的应用(server篇)
  • 原文地址:https://www.cnblogs.com/hhchaos/p/10292665.html
Copyright © 2020-2023  润新知