zoukankan      html  css  js  c++  java
  • [UWP 开发] 一个简单的Toast实现

    Toast简介

    在安卓里Toast是内置原生支持,它是Android中用来显示显示信息的一种机制。它主要用于向用户显示提示消息,没有焦点,显示的时间有限,过一定的时间就会自动消失。在UWP中虽然没有原生支持的Toast,但是完全可以用Popup封装实现一个简单的Toast自定义控件。

    Toast效果图

    先上效果图:

    上面是最终要做的效果图,从动态图中我们一点一点分析一下Toast是怎样做出来的。

    • 首先,我们可以明显看出它是有渐显效果。想要让它不是突兀地显示出来,而是慢慢显示出来,我们就要用到StoryBoard来做显示的动画。
    • 其次,Toast的控件构成上是由一个带背景色的Grid加一个垂直居中的TextBlock组合而成。
    • 最后,既然是要将它封装成一个用户控件,而在不同场景中Toast显示的文字提示肯定也不一样,所以我们还需要使用依赖属性DependcyProperty为它指定对应的消息。

    Toast的实现

    在实现上,由于Popup与Toast非常相似,都是只需要在必要的时候弹出来,所以我们这里以Popup作为主体来改造成我们需要的Toast。首先我们新建一个User Control,叫Toast.xaml即可。新建的方法如下图:

    控件布局

    Popup的Border可以从效果图中非常轻易地看出来,一个Background为Black的半透明Grid + 一个不透明的白色字TextBlock就可以帮我们解决问题,代码如下:

    <UserControl
        x:Class="Course.Controls.ToastPrompt"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Course.Controls"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300"
        d:DesignWidth="400">
        <Popup x:Name="Toast">
            <Border>
                <Grid HorizontalAlignment="Center" 
                      VerticalAlignment="Center"
                      MinHeight="100" 
                      MinWidth="300">
                    <!--这里为了不让Textblock的字Opacity保持100%,我们只对Grid的Border设置Opacity和Background即可-->
                    <Border Background="Black" 
                            Opacity="0.6" 
                            HorizontalAlignment="Stretch"
                            CornerRadius="4"/>
                    <Grid VerticalAlignment="Center"
                          Margin="30">
                        <TextBlock x:Name="textBlockMsg"
                               MinWidth="150"
                               TextWrapping="Wrap"
                               Text="{Binding Label}"
                               Foreground="#FFFFFFFF"/>
                    </Grid>
                </Grid>
            </Border>
        </Popup>
    </UserControl>
    
    

    动画效果

    为了做出渐显和渐隐的效果,我们需要使用Storyboard中的DoubleAnimation(应该是叫线性动画)。它指定一个Double类型的属性,可以使其在指定的时间内由起点值到达终点值,从而形成动画效果。
    这里改变的Double类型的属性是控件的Opacity(透明度)。这里我们可以用指定动画中的关键帧与出现的时间、属性,之后后台会自动帮我们进行线性插值计算,达到最终的效果。下面是动画效果部分的代码。

    <UserControl.Resources>
        <Storyboard x:Name="StoryboardShowPopup">
            <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetProperty="(UIElement.Opacity)" 
            Storyboard.TargetName="Toast">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <!--这里的0:0:0.2是关键帧在时间轴上的位置-->
                <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Name="StoryboardHiddenPopup">
            <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetProperty="(UIElement.Opacity)" 
            Storyboard.TargetName="Toast">
                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </UserControl.Resources>
    

    后台逻辑

    在写完控件和动画的部分后,我们来做一下后台的逻辑。后台的逻辑按照我们上面的表述,要包括两部分:

    • 依赖属性,用于从外部传递要显示的消息内容。
    • Toast的显示函数:弹出Toast,开始播放显示动画,停顿一会,开始播放隐藏动画,动画完成后Toast关闭。

    为了达到动画完成后Toast关闭这一点,我们需要在上面的Storyboard中小小地加一句,添加在这里:

        <Storyboard x:Name="StoryboardHiddenPopup" Completed="StoryboardHiddenPopup_Completed" .../>
    

    这段代码的意思是指,当StoryboardHiddenPopup动画结束后,自动执行函数StoryboardHiddenPopup_Completed。其他逻辑的实现代码如下:

        public sealed partial class Toast : UserControl
        {
            //这段代码是通用的依赖属性定义代码,为控件自定义了一个名为Label的属性。
            public DependencyProperty LabelProperty = 
                    DependencyProperty.Register("Label", typeof(string), typeof(ToastPrompt), null);
    
            //这一段代码将变量Label和Label依赖属性绑定在了一起,从而可以通过Binding到Label变量来间接绑定到依赖属性LabelProperty。
            public string Label
            {
                get { return GetValue(LabelProperty) as string; }
                set { SetValue(LabelProperty, value); }
            }
    
            public ToastPrompt()
            {
                this.InitializeComponent();
                this.DataContext = this;
            }
    
            public async Task Show()
            {
                this.Toast.IsOpen = false;
                this.StoryboardHiddenPopup.Stop();
                this.StoryboardShowPopup.Stop();            
                //这三步是为了清除上一次动画的效果
                this.Toast.IsOpen = true;
                this.StoryboardShowPopup.Begin();
                //内容提示停留1.2s后开始隐藏
                await Task.Delay(1200);
                this.StoryboardHiddenPopup.Begin();
            }
    
            //当隐藏动画播放结束后会自动调用StoryboardHiddenPopup_Completed
            private void StoryboardHiddenPopup_Completed(object sender, object e)
            {
                this.Toast.IsOpen = false;
            }
        }
    
    

    写完了前后台逻辑,下面来讲一下如何使用这个Toast控件。

    Toast的使用

    使用Toast也非常简单,就像使用普通的UserControl一样,前台在xxx.xaml 的某个容器中定义好即可,比如下面这段:

    <Grid>
        <local:ToastPrompt 
        x:Name="LoginToast" 
        Width="300"
        Height="150"
        HorizontalAlignment="Center"
        VerticalAlignment="Center"
        Label ="{x:Bind ViewModel.Message,Mode=OneWay}"/>
    </Grid>
    

    随后将Label(这个就是我们自定义的依赖属性)绑定到页面ViewModel(MVVM模式)中的某个变量上即可,这样更改ViewModel中的Message,Toast中的消息也会跟着变化。

    需要Toast出现的时候,只需要在后台逻辑里调用Show方法即可,比如下面这段代码:

    public async void Login(){
        ...
        this.LoginToast.Show();
        ...
    }
    

    如果不同的Toast需要停留的时间不一样长,可以考虑使用DispatcherTimer来控制Toast显示的时间。

  • 相关阅读:
    ASP学习笔记
    Access restriction: The type 'BASE64Encoder'
    hdu2094:产生冠军(判断有环图)
    hdu1533:Going Home(KM匹配)
    hdu2112:HDU Today(最短路)
    hdu2112:HDU Today(最短路)
    hdu2813:One fihgt one(KM匹配)
    hdu2813:One fihgt one(KM匹配)
    hdu2236:无题II(枚举+匈牙利算法)
    hdu2236:无题II(枚举+匈牙利算法)
  • 原文地址:https://www.cnblogs.com/SivilTaram/p/uwp_toast.html
Copyright © 2011-2022 走看看