WPF 仿语音播放 自定义控件

2021-03-07 04:28

阅读:461

标签:template   dem   rom   tco   mat   out   idc   编写   collect   

原文:WPF 仿语音播放 自定义控件

原理很简单,利用Path画一个图,然后用动画进行播放,播放时间由依赖属性输入赋值与控件内部维护的一个计时器进行控制。

控件基本是玩具,无法作为真实项目使用。

因为没有设置播放源,所以编写异步播放源或者实际播放时候要将事件引发,是否播放等属性,事件移到真实播放事件

非专业UI,即使知道怎么画图也是画的不如意,到底是眼睛会了,手不行啊。

技术图片

 

主界面xaml

技术图片
   local:VoiceAnimeButton    Height="40" Width="200" IconMargin="5,0,-8,0"  HorizontalContentAlignment="Center"  CornerRadius="15" VerticalContentAlignment="Center" BorderBrush="Black"  IconFill="Black"    BorderThickness="1" Background="Transparent"   VoicePlayTime="0:0:1" >
            local:VoiceAnimeButton.ContentTemplate>
                DataTemplate>
                    TextBlock FontSize="10" >
                     Run Text="播放时间"/>
                     Run Text="{Binding  RelativeSource={RelativeSource AncestorLevel=1,AncestorType=local:VoiceAnimeButton,Mode=FindAncestor}, Path=VoicePlayTime}"/>
                     Run Text="  "/>
                     Run Text="状态: "/>
                     Run Text="{Binding  RelativeSource={RelativeSource AncestorLevel=1,AncestorType=local:VoiceAnimeButton,Mode=FindAncestor}, Path=IsVoicePlay}"/>
                    TextBlock>
                DataTemplate>
            local:VoiceAnimeButton.ContentTemplate>
        local:VoiceAnimeButton>
技术图片

 

控件设计XAML

技术图片
ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:声音播放动画">


    Style TargetType="{x:Type local:VoiceAnimeButton}">
        Setter Property="Template">
            Setter.Value>
                ControlTemplate TargetType="{x:Type local:VoiceAnimeButton}">
                    Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"  CornerRadius="{TemplateBinding CornerRadius}" Padding="1">
                        Grid  >
                            Grid.ColumnDefinitions>
                                ColumnDefinition Width="auto"/>
                                ColumnDefinition Width="*"/>
                            Grid.ColumnDefinitions>
                            Border Margin="{TemplateBinding IconMargin}" >
                                Viewbox>
                                    Path x:Name="VoicePath"  Height="{TemplateBinding IconHieght}" Width="{TemplateBinding IconWidth}"   Fill="{TemplateBinding IconFill}" >
                                        Path.Data>
                                            PathGeometry>
                                                PathFigureCollection>
                                                    M20 20 Q12 45 20 85 l7 -4 Q18 48 27 23 l-7 -3Z
                                    M32 29 Q22 45 32 75 l7 -4 Q29 50 38 33 l-6.5 -4
                                    M45 35 Q38 48 45 68 l7 -4 Q45 50 52 39 l-7.5 -4
                                    M58 41 Q55 49 58 61 l17 -11Z
                                                PathFigureCollection>
                                            PathGeometry>
                                        Path.Data>
                                    Path>
                                Viewbox>
                            Border>
                            ContentPresenter Grid.Column="1"   HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        Grid>
                    Border>
                    ControlTemplate.Triggers>
                        EventTrigger  RoutedEvent="VoicePlayStart">
                            BeginStoryboard x:Name="bs1">
                                Storyboard Storyboard.TargetProperty="Data" Storyboard.TargetName="VoicePath" RepeatBehavior="Forever" Duration="0:0:0.4" BeginTime="0">
                                    ObjectAnimationUsingKeyFrames>
                                        DiscreteObjectKeyFrame KeyTime="0:0:0.1">
                                            DiscreteObjectKeyFrame.Value>
                                                PathGeometry>
                                                    PathFigureCollection>
                                                        M45 35 Q38 48 45 68 l7 -4 Q45 50 52 39 l-7.5 -4
                                                        M58 41 Q55 49 58 61 l17 -11Z
                                                    PathFigureCollection>
                                                PathGeometry>
                                            DiscreteObjectKeyFrame.Value>
                                        DiscreteObjectKeyFrame>
                                        DiscreteObjectKeyFrame KeyTime="0:0:0.2">
                                            DiscreteObjectKeyFrame.Value>
                                                PathGeometry>
                                                    PathFigureCollection>
                                                        M32 29 Q22 45 32 75 l7 -4 Q29 50 38 33 l-6.5 -4
                                                        M45 35 Q38 48 45 68 l7 -4 Q45 50 52 39 l-7.5 -4
                                                        M58 41 Q55 49 58 61 l17 -11Z
                                                    PathFigureCollection>
                                                PathGeometry>
                                            DiscreteObjectKeyFrame.Value>
                                        DiscreteObjectKeyFrame>
                                        DiscreteObjectKeyFrame KeyTime="0:0:0.3">
                                            DiscreteObjectKeyFrame.Value>
                                                PathGeometry>
                                                    PathFigureCollection>
                                                        M20 20 Q12 45 20 85 l7 -4 Q18 48 27 23 l-7 -3Z
                                                        M32 29 Q22 45 32 75 l7 -4 Q29 50 38 33 l-6.5 -4
                                                        M45 35 Q38 48 45 68 l7 -4 Q45 50 52 39 l-7.5 -4
                                                        M58 41 Q55 49 58 61 l17 -11Z
                                                    PathFigureCollection>
                                                PathGeometry>
                                            DiscreteObjectKeyFrame.Value>
                                        DiscreteObjectKeyFrame>
                                    ObjectAnimationUsingKeyFrames>

                                Storyboard>
                            BeginStoryboard>
                        EventTrigger>
                        EventTrigger RoutedEvent="VoicePlayEnd">
                            RemoveStoryboard BeginStoryboardName="bs1"/>
                        EventTrigger>
                    ControlTemplate.Triggers>
                ControlTemplate>
            Setter.Value>
        Setter>
    Style>
ResourceDictionary>
技术图片

 

控件CS代码

技术图片
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 声音播放动画
{
   
    public class VoiceAnimeButton : ContentControl
    {
        static VoiceAnimeButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(VoiceAnimeButton), new FrameworkPropertyMetadata(typeof(VoiceAnimeButton)));
        }

        private DispatcherTimer Timer;

        public VoiceAnimeButton()
        {
            Timer = new DispatcherTimer();
            Timer.Tick += Timer_Tick;
            Timer.Interval = TimeSpan.FromSeconds(1);
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            Timer.Stop();
            IsVoicePlay = false;
            this.RaiseEvent(new RoutedEventArgs(VoicePlayEndEvent, this));

        }

        public static readonly RoutedEvent VoicePlayStartEvent = EventManager.RegisterRoutedEvent("VoicePlayStart", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(VoiceAnimeButton));

        /// 
        /// 声音播放开始事件
        /// 
        public event RoutedEventHandler VoicePlayStart
        {
            add
            {
                this.AddHandler(VoicePlayStartEvent, value);
            }
            remove
            {
                RemoveHandler(VoicePlayStartEvent, value);
            }
        }


        public static readonly RoutedEvent VoicePlayEndEvent= EventManager.RegisterRoutedEvent("VoicePlayEnd", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(VoiceAnimeButton));

        /// 
        /// 声音播放结束事件
        /// 
        public event RoutedEventHandler VoicePlayEnd
        {
            add
            {
               AddHandler(VoicePlayEndEvent, value);
            }
            remove
            {
                RemoveHandler(VoicePlayEndEvent, value);
            }
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            IsMouseLeftClick = true;
            Timer.Interval = VoicePlayTime;
            Timer.Start();
            IsVoicePlay = true;
            this.RaiseEvent(new RoutedEventArgs(VoicePlayStartEvent,this));
           
        }
        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonUp(e);
            IsMouseLeftClick = false;
        }

        public static readonly DependencyProperty VoicePlayTimeProperty = DependencyProperty.Register("VoicePlayTime", typeof(TimeSpan), typeof(VoiceAnimeButton), new PropertyMetadata(TimeSpan.FromMilliseconds(1000)));
      
        public TimeSpan VoicePlayTime
        {
            get => (TimeSpan)GetValue(VoicePlayTimeProperty);
            set => SetValue(VoicePlayTimeProperty, value);
        }
        public static readonly DependencyProperty IsMouseLeftClickProperty = DependencyProperty.Register("IsMouseLeftClick", typeof(bool), typeof(VoiceAnimeButton),new PropertyMetadata(false));

        public bool IsMouseLeftClick
        {
            get => (bool)GetValue(IsMouseLeftClickProperty);
            set => SetValue(IsMouseLeftClickProperty, value);
        }
        public static readonly DependencyProperty IconWidthProperty = DependencyProperty.Register("IconWidth", typeof(double), typeof(VoiceAnimeButton), new PropertyMetadata(100.0));

        public double IconWidth
        {
            get => Convert.ToDouble(IconWidthProperty);
            set => SetValue(IconWidthProperty, value);
        }
        public static readonly DependencyProperty IconHieghtProperty = DependencyProperty.Register("IconHieght", typeof(double), typeof(VoiceAnimeButton), new PropertyMetadata(100.0));

        public double IconHieght
        {
            get => Convert.ToDouble(IconHieghtProperty);
            set => SetValue(IconHieghtProperty, value);
        }

        public static readonly DependencyProperty IconFillProperty= DependencyProperty.Register("IconFill", typeof(SolidColorBrush), typeof(VoiceAnimeButton), new PropertyMetadata(new SolidColorBrush(Colors.Black)));

        public SolidColorBrush IconFill
        {
            get => GetValue(IconFillProperty) as SolidColorBrush;
            set => SetValue(IconFillProperty, value);
        }

        public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(VoiceAnimeButton), new PropertyMetadata(new CornerRadius(0)));

        public CornerRadius CornerRadius
        {
            get => (CornerRadius)GetValue(CornerRadiusProperty);
            set => SetValue(CornerRadiusProperty, value);
        }
        public static readonly DependencyProperty IconMarginProperty = DependencyProperty.Register("IconMargin", typeof(Thickness), typeof(VoiceAnimeButton), new PropertyMetadata(new Thickness(0.0)));

        public Thickness IconMargin
        {
            get => (Thickness)GetValue(IconMarginProperty);
            set => SetValue(IconMarginProperty, value);
        }

        public static readonly DependencyProperty IsVoicePlayProperty = DependencyProperty.Register("IsVoicePlay", typeof(bool), typeof(VoiceAnimeButton));

        public bool IsVoicePlay
        {
            get => (bool)GetValue(IsVoicePlayProperty);
            set => SetValue(IsVoicePlayProperty, value);
        }
    }
}
技术图片

 

WPF 仿语音播放 自定义控件

标签:template   dem   rom   tco   mat   out   idc   编写   collect   

原文地址:https://www.cnblogs.com/lonelyxmas/p/12833879.html


评论


亲,登录后才可以留言!