[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顯示的時間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM