[MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构

科技资讯 投稿 5700 0 评论

[MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构

    [MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构
  • [MAUI 项目实战] 手势控制音乐播放器(二): 手势交互
  • [MAUI 项目实战] 手势控制音乐播放器(三): 动画
  • [MAUI 项目实战] 手势控制音乐播放器(四):圆形进度条

在之前的博文中提到这个项目,它是为音乐播放器专门开发的基于手势控制的UI界面。

手势来控制的交互方式适合不方便看手机屏幕时简单的音乐播放需求,在驾车、运动等场景下有较好的用户体验。

架构

跨平台

播放内核

此项目重点关注的是手势交互UI,播放内核的实现将不再赘述。

手势原理

拖拽平移和控制区域的关系,可以抽象成四个状态,分别是Out,In,Over,Start。

    In:pan进入pit时触发,
  • Out:pan离开pit时触发,
  • Over:释放pan时触发,
  • Start:pan开始拖拽时触发
public enum PanType
{
    Out, In, Over, Start
}

对拖拽手势的处理,由手势容器控件PanContainer封装,实现方式将在下一章节介绍。

当整个控制触发完成后,控件将触发OnfinishedChoise事件。

基本控制

如上一曲操作,订阅事件后,实现如下逻辑:

private void DefaultPanContainer_OnOnfinishedChoise(object sender, PitGrid e
{
    CurrentPitView = e;
    switch (CurrentPitView.PitName
    {
        case "LeftPit":
        MusicRelatedViewModel.PreAction(null;
        break;

        ...
    }
}

控件会将当前触发的pit传递给事件方法,通过pit的名称,可以判断当前触发的是哪个控制区域。

public NowPlayingPage(
{
    InitializeComponent(;
    WeakReferenceMessenger.Default.Register<PanActionArgs, string>(this, TokenHelper.PanAction, PanActionHandler;
    ...
}

如在拖拽开始时,显示控制区域的提示信息,拖拽结束时,隐藏提示信息。

private async void PanActionHandler(object recipient, PanActionArgs args
{
    var parentAnimation = new Animation(;

    Animation scaleUpAnimation1;
    Animation scaleUpAnimation2;
    switch (args.PanType
    {
        case PanType.Over:

            scaleUpAnimation1 = new Animation(v => this.PitContentLayout.Opacity = v, PitContentLayout.Opacity, 0, Easing.CubicOut;
            scaleUpAnimation2 = new Animation(v => this.TitleLayout.Opacity = v, TitleLayout.Opacity, 1, Easing.CubicOut;

            parentAnimation.Add(0, 1, scaleUpAnimation1;
            parentAnimation.Add(0, 1, scaleUpAnimation2;

            parentAnimation.Commit(this, "RestoreAnimation", 16, 250;
         
...

快进/快退

拖拽停留在左右控制区域超过一定时间,将触发“快进”或“快退”

private IDispatcherTimer _dispatcherTimer;

拖拽进入控制区域时,启动定时器,停留在左右控制区域大于2s时将触发定时器Tick事件,执行快进或快退操作。

private async void PanActionHandler(object recipient, PanActionArgs args
{

    switch (args.PanType
    {
        ...
        case PanType.In:

            switch (args.CurrentPit?.PitName
            {
                case "LeftPit":

                    _dispatcherTimer =Dispatcher.CreateTimer(;
                    _dispatcherTimer.Interval=new TimeSpan(0, 0, 2;

                    _dispatcherTimer.Tick+=   async (o, e =>
                    {
                        this.TipLabel.Text = FaIcons.IconFastBackward;
                        this.TipTextLabel.Text = "快退";
                        _runCount++;
                        await MusicRelatedViewModel.StartFastSeeking(-2;


                    };
                    _dispatcherTimer.Start(;
                    this.TipTextLabel.Text = "上一曲";

                    break;
    ...

_runCount是个全局变量,记录是否已经执行过快进或快退操作,当退出控制区域时,如果已经执行过快进或快退操作,将停止快进或快退操作,并将计时器停止。

 case PanType.Out:
    this.PitTipLayout.Children.Clear(;
    if (this._runCount > 0
    {
        MusicRelatedViewModel.EndFastSeeking(;
    }
    if (_dispatcherTimer!=null
    {
        _dispatcherTimer.Stop(;

    }
    _runCount = 0;
    this.TipTextLabel.Text = string.Empty;


    break;

同理,在松手时,应该停止快进或快退操作,并将计时器停止。

case PanType.Over:

    ...
    MusicRelatedViewModel.EndFastSeeking(;
    if (_dispatcherTimer!=null
    {
        _dispatcherTimer.Stop(;

    }
    _runCount = 0;

沉浸模式

_dispatcherTimer2是控制界面进入“沉浸模式”的定时器,当界面无操作5s之后界面将进入沉浸模式,隐藏标题栏。

private void SetupFullScreenMode(int delay = 5
{
    _dispatcherTimer2 =Dispatcher.CreateTimer(;
    _dispatcherTimer2.Interval=new TimeSpan(0, 0, delay;

    _dispatcherTimer2.Tick+=   (o, e =>
    {

        this.MainCircleSlider.BorderWidth = 3;
        this.TitleLayout.FadeTo(0;

    };

    _dispatcherTimer2.Start(;
}

有操作进行时,恢复到正常模式。

case PanType.Start:

    ...

    if (_dispatcherTimer2.IsRunning
    {
        _dispatcherTimer2.Stop(;
    }
    SetupNormalMode(;

    break;

下一章将逐步展开手势控制的实现细节。

项目地址

Github:maui-samples

编程笔记 » [MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构

赞同 (34) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽