zoukankan      html  css  js  c++  java
  • [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),欢迎大家随意吐槽&提意见!

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

  • 相关阅读:
    通过HttpListener实现简单的Http服务
    WCF心跳判断服务端及客户端是否掉线并实现重连接
    NHibernate初学六之关联多对多关系
    NHibernate初学五之关联一对多关系
    EXTJS 4.2 资料 跨域的问题
    EXTJS 4.2 资料 控件之Grid 那些事
    EXTJS 3.0 资料 控件之 GridPanel属性与方法大全
    EXTJS 3.0 资料 控件之 Toolbar 两行的用法
    EXTJS 3.0 资料 控件之 combo 用法
    EXTJS 4.2 资料 控件之 Store 用法
  • 原文地址:https://www.cnblogs.com/hhchaos/p/10292665.html
Copyright © 2011-2022 走看看