WPF之loading正在加載效果的兩種實現


WPF開發程序過程中總會遇到一個需求:Loading...正在加載中,這樣一個需求作為加載的過渡效果。

這里博主給出兩種方法來實現:

1.使用一張規則圖片,加上圖片的wpf旋轉效果來實現加載效果。

2.wpf程序划點,然后旋轉實現加載效果。

下面分別給出實現方法及代碼:

1.規則圖片的旋轉實現

<Image x:Name="run_image" Source="../Images/loading_pic.png" Stretch="UniformToFill" Margin="25,0,0,0" Width="28" Height="28"
HorizontalAlignment="Center" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" >
</Image>

這里的RenderTransformOrigin="0.5,0.5"表示以圖片的圓心為指定變換原點

在后台中初始化代碼中加上下面一段:

//圖片轉動
            DoubleAnimation da = new DoubleAnimation();
            da.From = 0;
            da.To = 360;
            da.Duration = new Duration(TimeSpan.FromSeconds(3));
            da.RepeatBehavior = RepeatBehavior.Forever;
            RotateTransform rt = new RotateTransform();
            run_image.RenderTransform = rt;
            rt.BeginAnimation(RotateTransform.AngleProperty, da);
//圖片轉動
View Code

2.wpf程序划點,然后旋轉實現加載效果

在xaml中我們添加一個遮罩層和這個loading的圖像:

<Grid x:Name="LoadGrid" Visibility="Collapsed" IsVisibleChanged="HandleVisibleChanged">
            <Grid.Background>
                <SolidColorBrush Color="Black" Opacity="0.2"  />
            </Grid.Background>
            <Grid.Resources>
                <SolidColorBrush Color="#FF007BE5" x:Key="CirclesColor" />
                <!--<SolidColorBrush Color="Black" x:Key="BackgroundColor" Opacity=".20" />-->
            </Grid.Resources>

            <Viewbox Width="100" Height="100"  
            HorizontalAlignment="Center"  
            VerticalAlignment="Center">
                <Grid x:Name="LayoutRoot"   
                Background="Transparent"  
                ToolTip="Please wait...."  
                HorizontalAlignment="Center"  
                VerticalAlignment="Center">
                    <TextBlock Text="Loading..."  HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" Foreground="#FFE3953D" FontWeight="Bold" />
                    <Canvas RenderTransformOrigin="0.5,0.5"  
                    HorizontalAlignment="Center"  
                    VerticalAlignment="Center" Width="120"  
                    Height="120" Loaded="HandleLoaded"  
                    Unloaded="HandleUnloaded"  >
                        <Ellipse x:Name="C0" Width="20" Height="20"  
                         Canvas.Left="0"  
                         Canvas.Top="0" Stretch="Fill"  
                         Fill="{StaticResource CirclesColor}" Opacity="1.0"/>
                        <Ellipse x:Name="C1" Width="20" Height="20"  
                         Canvas.Left="0"  
                         Canvas.Top="0" Stretch="Fill"  
                         Fill="{StaticResource CirclesColor}" Opacity="0.9"/>
                        <Ellipse x:Name="C2" Width="20" Height="20"  
                         Canvas.Left="0"  
                         Canvas.Top="0" Stretch="Fill"  
                         Fill="{StaticResource CirclesColor}" Opacity="0.8"/>
                        <Ellipse x:Name="C3" Width="20" Height="20"  
                         Canvas.Left="0"  
                         Canvas.Top="0" Stretch="Fill"  
                         Fill="{StaticResource CirclesColor}" Opacity="0.7"/>
                        <Ellipse x:Name="C4" Width="20" Height="20"  
                         Canvas.Left="0"  
                         Canvas.Top="0" Stretch="Fill"  
                         Fill="{StaticResource CirclesColor}" Opacity="0.6"/>
                        <Ellipse x:Name="C5" Width="20" Height="20"  
                         Canvas.Left="0"  
                         Canvas.Top="0" Stretch="Fill"  
                         Fill="{StaticResource CirclesColor}" Opacity="0.5"/>
                        <Ellipse x:Name="C6" Width="20" Height="20"  
                         Canvas.Left="0"  
                         Canvas.Top="0" Stretch="Fill"  
                         Fill="{StaticResource CirclesColor}" Opacity="0.4"/>
                        <Ellipse x:Name="C7" Width="20" Height="20"  
                         Canvas.Left="0"  
                         Canvas.Top="0" Stretch="Fill"  
                         Fill="{StaticResource CirclesColor}" Opacity="0.3"/>
                        <Ellipse x:Name="C8" Width="20" Height="20"  
                         Canvas.Left="0"  
                         Canvas.Top="0" Stretch="Fill"  
                         Fill="{StaticResource CirclesColor}" Opacity="0.2"/>
                        <Canvas.RenderTransform>
                            <RotateTransform x:Name="SpinnerRotate"  
                         Angle="0" />
                        </Canvas.RenderTransform>
                    </Canvas>
                </Grid>
            </Viewbox>
        </Grid>
View Code

上面的代碼實現了:一個半透明的黑色蒙版,9個顏色相同但是透明度不同的藍色圓點,loading字樣

然后需要在后台cs代碼中加入下列代碼:

        #region 
        /// <summary>
        /// 隊列計時器
        /// </summary>
        private DispatcherTimer animationTimer;
        #endregion

        #region 加載界面初始化方法

        public void LoadingWait()
        {
            animationTimer = new DispatcherTimer(
                DispatcherPriority.ContextIdle, Dispatcher);
            animationTimer.Interval = new TimeSpan(0, 0, 0, 0, 90);
        }
        #endregion

        #region 執行方法

        private void Start()
        {
            animationTimer.Tick += HandleAnimationTick;
            animationTimer.Start();
        }

        private void Stop()
        {
            animationTimer.Stop();
            animationTimer.Tick -= HandleAnimationTick;
        }

        private void HandleAnimationTick(object sender, EventArgs e)
        {
            SpinnerRotate.Angle = (SpinnerRotate.Angle + 36) % 360;
        }

        private void HandleLoaded(object sender, RoutedEventArgs e)
        {
            const double offset = Math.PI;
            const double step = Math.PI * 2 / 10.0;

            SetPosition(C0, offset, 0.0, step);
            SetPosition(C1, offset, 1.0, step);
            SetPosition(C2, offset, 2.0, step);
            SetPosition(C3, offset, 3.0, step);
            SetPosition(C4, offset, 4.0, step);
            SetPosition(C5, offset, 5.0, step);
            SetPosition(C6, offset, 6.0, step);
            SetPosition(C7, offset, 7.0, step);
            SetPosition(C8, offset, 8.0, step);
        }

        private void SetPosition(Ellipse ellipse, double offset,
            double posOffSet, double step)
        {
            ellipse.SetValue(Canvas.LeftProperty, 50.0
                + Math.Sin(offset + posOffSet * step) * 50.0);

            ellipse.SetValue(Canvas.TopProperty, 50
                + Math.Cos(offset + posOffSet * step) * 50.0);
        }

        private void HandleUnloaded(object sender, RoutedEventArgs e)
        {
            Stop();
        }

        private void HandleVisibleChanged(object sender,
            DependencyPropertyChangedEventArgs e)
        {
            bool isVisible = (bool)e.NewValue;
            if (animationTimer == null)
            {
                LoadingWait();
            }
            if (isVisible)
                Start();
            else
                Stop();
        }    
View Code

以上的代碼主要實現loading圖像的旋轉,這里原理是這樣的:初始化的時候先將9個圓點按照圓形正圓排列(HandleLoaded方法),然后初始化一個DispatcherTimer定時器(知識點:timer和DispatcherTimer的區別),這樣定時觸發HandleAnimationTick方法(該方法會給圓形圖像設置旋轉角度)

最重要的是,這些動作在該圖顯示顯示的時候發生(IsVisibleChanged="HandleVisibleChanged" //這個元素的 IsVisible 屬性值變化時發生),要想不顯示該效果只需要將該元素隱藏即可(this.LoadGrid.Visibility = System.Windows.Visibility.Collapsed;//遮罩層隱藏)。

這塊其實可以單獨提取出來,哪里想要使用直接引用即可。

 新建一個usercontrol

<UserControl x:Class="LoadingMask_Demo.LoadingWait"  
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
             IsVisibleChanged="HandleVisibleChanged">  
    <UserControl.Background>  
        <SolidColorBrush Color="Black" Opacity="0.2"  />  
    </UserControl.Background>  
    <UserControl.Resources>  
        <SolidColorBrush Color="#FF007BE5" x:Key="CirclesColor" />  
        <!--<SolidColorBrush Color="Black" x:Key="BackgroundColor" Opacity=".20" />-->  
    </UserControl.Resources>  
  
    <Viewbox Width="100" Height="100"    
            HorizontalAlignment="Center"    
            VerticalAlignment="Center">  
        <Grid x:Name="LayoutRoot"     
                Background="Transparent"    
                ToolTip="Please wait...."    
                HorizontalAlignment="Center"    
                VerticalAlignment="Center">  
            <TextBlock Text="Loading..."  HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" Foreground="#FFE3953D" FontWeight="Bold" />  
            <Canvas RenderTransformOrigin="0.5,0.5"    
                    HorizontalAlignment="Center"    
                    VerticalAlignment="Center" Width="120"    
                    Height="120" Loaded="HandleLoaded"    
                    Unloaded="HandleUnloaded"  >  
                <Ellipse x:Name="C0" Width="20" Height="20"    
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="1.0"/>  
                <Ellipse x:Name="C1" Width="20" Height="20"    
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.9"/>  
                <Ellipse x:Name="C2" Width="20" Height="20"    
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.8"/>  
                <Ellipse x:Name="C3" Width="20" Height="20"    
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.7"/>  
                <Ellipse x:Name="C4" Width="20" Height="20"    
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.6"/>  
                <Ellipse x:Name="C5" Width="20" Height="20"    
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.5"/>  
                <Ellipse x:Name="C6" Width="20" Height="20"    
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.4"/>  
                <Ellipse x:Name="C7" Width="20" Height="20"    
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.3"/>  
                <Ellipse x:Name="C8" Width="20" Height="20"    
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.2"/>  
                <Canvas.RenderTransform>  
                    <RotateTransform x:Name="SpinnerRotate"    
                         Angle="0" />  
                </Canvas.RenderTransform>  
            </Canvas>  
        </Grid>  
    </Viewbox>  
</UserControl>  
View Code

對應的cs文件代碼:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Data;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Navigation;  
using System.Windows.Shapes;  
using System.Windows.Threading;  
  
namespace LoadingMask_Demo  
{  
    /// <summary>  
    /// Interaction logic for LoadingWait.xaml  
    /// </summary>  
    public partial class LoadingWait : UserControl  
    {  
        #region Data  
        private readonly DispatcherTimer animationTimer;  
        #endregion  
 
        #region Constructor  
        public LoadingWait()  
        {  
            InitializeComponent();  
  
            animationTimer = new DispatcherTimer(  
                DispatcherPriority.ContextIdle, Dispatcher);  
            animationTimer.Interval = new TimeSpan(0, 0, 0, 0, 90);  
        }  
        #endregion  
 
        #region Private Methods  
        private void Start()  
        {  
            animationTimer.Tick += HandleAnimationTick;  
            animationTimer.Start();  
        }  
  
        private void Stop()  
        {  
            animationTimer.Stop();  
            animationTimer.Tick -= HandleAnimationTick;  
        }  
  
        private void HandleAnimationTick(object sender, EventArgs e)  
        {  
            SpinnerRotate.Angle = (SpinnerRotate.Angle + 36) % 360;  
        }  
  
        private void HandleLoaded(object sender, RoutedEventArgs e)  
        {  
            const double offset = Math.PI;  
            const double step = Math.PI * 2 / 10.0;  
  
            SetPosition(C0, offset, 0.0, step);  
            SetPosition(C1, offset, 1.0, step);  
            SetPosition(C2, offset, 2.0, step);  
            SetPosition(C3, offset, 3.0, step);  
            SetPosition(C4, offset, 4.0, step);  
            SetPosition(C5, offset, 5.0, step);  
            SetPosition(C6, offset, 6.0, step);  
            SetPosition(C7, offset, 7.0, step);  
            SetPosition(C8, offset, 8.0, step);  
        }  
  
        private void SetPosition(Ellipse ellipse, double offset,  
            double posOffSet, double step)  
        {  
            ellipse.SetValue(Canvas.LeftProperty, 50.0  
                + Math.Sin(offset + posOffSet * step) * 50.0);  
  
            ellipse.SetValue(Canvas.TopProperty, 50  
                + Math.Cos(offset + posOffSet * step) * 50.0);  
        }  
  
        private void HandleUnloaded(object sender, RoutedEventArgs e)  
        {  
            Stop();  
        }  
  
        private void HandleVisibleChanged(object sender,  
            DependencyPropertyChangedEventArgs e)  
        {  
            bool isVisible = (bool)e.NewValue;  
  
            if (isVisible)  
                Start();  
            else  
                Stop();  
        }  
        #endregion    
    }  
}  
View Code

調用時前台的代碼:

<Window x:Class="LoadingMask_Demo.MainWindow"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        Title="MainWindow" Height="350" Width="525"  
        xmlns:local="clr-namespace:LoadingMask_Demo"  
        >  
    <DockPanel>  
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top">  
            <Button  Content="show" Width="70" Height="30" Click="ShowButton_Click" />  
            <Button  Content="hide" Width="70" Height="30" Click="HideButton_Click"/>  
        </StackPanel>  
          
        <Grid Background="#FF484848" DockPanel.Dock="Bottom">  
            <TextBlock Text="asdfasdfasdf" Foreground="White"/>  
            <local:LoadingWait x:Name="_loading"  Visibility="Collapsed"/>  
        </Grid>  
    </DockPanel>  
</Window>
View Code

調用時后台控制顯示隱藏的代碼:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Data;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Navigation;  
using System.Windows.Shapes;  
  
namespace LoadingMask_Demo  
{  
    /// <summary>  
    /// Interaction logic for MainWindow.xaml  
    /// </summary>  
    public partial class MainWindow : Window  
    {  
        public MainWindow()  
        {  
            InitializeComponent();  
        }  
  
        private void ShowButton_Click(object sender, RoutedEventArgs e)  
        {  
            this._loading.Visibility = Visibility.Visible;  
        }  
  
        private void HideButton_Click(object sender, RoutedEventArgs e)  
        {  
            this._loading.Visibility = Visibility.Collapsed;  
        }  
  
    }  
}  
View Code

看一下最后的效果圖:


免責聲明!

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



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