[MAUI]模仿网易云音乐黑胶唱片的交互实现

这篇具有很好参考价值的文章主要介绍了[MAUI]模仿网易云音乐黑胶唱片的交互实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

@

目录
  • 创建页面布局
  • 创建手势控件
  • 创建影子控件
  • 唱盘拨动交互
  • 唱盘和唱针动画
  • 项目地址

用过网易云音乐App的同学应该都比较熟悉它播放界面。

这是一个良好的交互设计,留声机的界面隐喻准确地向人们传达产品概念和使用方法:当手指左右滑动时,便模拟了更换唱盘从而导向切换歌曲的交互功能。

今天在 .NET MAUI 中我们来实现这个交互效果,先来看看效果:

[MAUI]模仿网易云音乐黑胶唱片的交互实现

使用.NET MAU实现跨平台支持,本项目可运行于Android、iOS平台。

创建页面布局

项目模拟了网易云音乐的播放主界面,可播放本地音乐文件。使用MatoMusic.Core作为播放内核,此项目对其将不再赘述。请阅读此博文[MAUI 项目实战] 音乐播放器(二):播放内核

新建.NET MAUI项目,命名CloudMusicGroove,项目引用MatoMusic.Core。

将界面图片资源文件拷贝到项目\Resources\Images中,这些界面图片资源可通过解包官方apk的方式轻松获取。

[MAUI]模仿网易云音乐黑胶唱片的交互实现

将他们包含在MauiImage资源清单中。

<MauiImage Include="Resources\Images\*" />

创建页面的静态布局,布局如下图所示

[MAUI]模仿网易云音乐黑胶唱片的交互实现

其中唱盘元素是一个300 × 300的圆形,专辑封面为200 × 200的圆形,图片的圆形区域是通过裁剪实现的,代码如下:

<Grid 
        VerticalOptions="Start"
        HorizontalOptions="Start">
    <Image Source="ic_disc.png"
            WidthRequest="300"
            HeightRequest="300" />

    <Image HeightRequest="200"
            WidthRequest="200"
            x:Name="AlbumArtImage"
            Margin="0"
            Source="{Binding  CurrentMusic.AlbumArt}"
            VerticalOptions="CenterAndExpand"
            HorizontalOptions="CenterAndExpand"
            Aspect="AspectFill">

        <Image.Clip>
            <RoundRectangleGeometry  CornerRadius="125"
                                        Rect="0,0,200,200" />
        </Image.Clip>
    </Image>

</Grid>

设置留声机唱针元素,代码如下:

<Image WidthRequest="100"
    HeightRequest="167"
    HorizontalOptions="Center"
    VerticalOptions="Start"
    Margin="70,-50,0,0"
    Source="ic_needle.png"
    x:Name="AlbumNeedle" />

创建PitContentLayout区域,这个区域是一个3 × 2的网格布局,用来放置三个功能区域

在PitContentLayout中创建三个PitGrid控件,并对这三个功能区域的PitGrid控件命名,LeftPitMiddlePitRightPit,代码如下:

<Grid  x:Name="PitContentLayout"
        Opacity="1"
        BindingContext="{Binding CurrentMusicRelatedViewModel}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*"></ColumnDefinition>
        <ColumnDefinition Width="2*"></ColumnDefinition>
        <ColumnDefinition Width="1*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <controls1:PitGrid x:Name="LeftPit"
                        Background="pink"
                        PitName="LeftPit">
    </controls1:PitGrid>
    <controls1:PitGrid Grid.Column="1"
                        x:Name="MiddlePit"
                        Background="azure"
                        
                        PitName="MiddlePit">
    </controls1:PitGrid>
    <controls1:PitGrid Grid.Column="2"
                        x:Name="RightPit"
                        Background="lightyellow"
                        PitName="RightPit">

    </controls1:PitGrid>


</Grid>

[MAUI]模仿网易云音乐黑胶唱片的交互实现

创建手势控件

手势控件,或称为手势容器控件,它来对拖拽物进行包装,以赋予拖拽物响应平移手势的能力。

创建一个容器控件HorizontalPanContainer,控件包含的PanGestureRecognizer提供了当手指在屏幕移动这一过程的描述

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiSample.Controls.HorizontalPanContainer">
    <ContentView.GestureRecognizers>
        <PanGestureRecognizer PanUpdated="PanGestureRecognizer_OnPanUpdated"></PanGestureRecognizer>
        <TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped"></TapGestureRecognizer>

    </ContentView.GestureRecognizers>
</ContentView>

创建一个手势控件。他将留声机唱盘区域包裹起来。这样当手指在唱盘区域滑动时,就可以触发平移手势事件。

<controls:HorizontalPanContainer Background="Transparent"
        x:Name="DefaultPanContainer"
        OnTapped="DefaultPanContainer_OnOnTapped"
        OnfinishedChoise="DefaultPanContainer_OnOnfinishedChoise">
    <controls:HorizontalPanContainer.Content>
        <Grid PropertyChanged="BindableObject_OnPropertyChanged"
                VerticalOptions="Start"
                HorizontalOptions="Start">
            <Image Source="ic_disc.png"
                    WidthRequest="300"
                    HeightRequest="300" />

            <Image HeightRequest="200"
                    WidthRequest="200"
                    x:Name="AlbumArtImage"
                    Margin="0"
                    Source="{Binding  CurrentMusic.AlbumArt}"
                    VerticalOptions="CenterAndExpand"
                    HorizontalOptions="CenterAndExpand"
                    Aspect="AspectFill">

                <Image.Clip>
                    <RoundRectangleGeometry  CornerRadius="125"
                                                Rect="0,0,200,200" />
                </Image.Clip>
            </Image>

        </Grid>

    </controls:HorizontalPanContainer.Content>
</controls:HorizontalPanContainer>

[MAUI]模仿网易云音乐黑胶唱片的交互实现

创建影子控件

影子控件用于滑动唱盘时,显示上一曲、下一曲的专辑封面。

在左右滑动的全程中,唱盘的中心点与相邻唱盘的中心点距离,应为屏幕宽度。如下图所示

[MAUI]模仿网易云音乐黑胶唱片的交互实现

唱盘与唱盘的距离应是

创建影子控件,这个控件将随拖拽物的移动而跟随移动,当然我们只需要保持X方向的移动即可。

在NowPlayingPage中的HorizontalPanContainer相邻容器视图中创建影子控件,代码如下:

<Grid TranslationX="{Binding Source={x:Reference  DefaultPanContainer} ,Path=Content.TranslationX}">
    <Image Source="ic_disc.png"
            WidthRequest="300"
            HeightRequest="300" />

    <Image HeightRequest="200"
            WidthRequest="200"
            Margin="0"
            Source="{Binding  PreviewMusic.AlbumArt}"
            VerticalOptions="CenterAndExpand"
            HorizontalOptions="CenterAndExpand"
            Aspect="AspectFill">

        <Image.Clip>
            <RoundRectangleGeometry  CornerRadius="125"
                                        Rect="0,0,200,200" />
        </Image.Clip>
    </Image>

</Grid>

我们将这个影子控件的TranslationX属性将绑定到拖拽物的TranslationX属性上,初步效果如下

[MAUI]模仿网易云音乐黑胶唱片的交互实现

拖拽区域需要两个影子控件,分别显示上一曲和下一曲的专辑封面。

我们需要将影子控件的偏移量与屏幕宽度作匹配,我们用转换器来实现这个功能。

创建CalcValueConverter.cs文件,代码如下:

public class CalcValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var d = (double)value;
        double compensation;
        if (double.Parse((string)parameter)>=0)
        {
            compensation=((App.Current as App).PanContainerWidth+300)/2;
        }
        else
        {
            compensation=-1.5*(App.Current as App).PanContainerWidth+300/2;
        }
        return d+compensation;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

}

将CalcValueConverter添加至资源字典中,

<converter:CalcValueConverter x:Key="CalcValueConverter"></converter:CalcValueConverter>

对影子控件的属性绑定设置转换器,并设置转换器参数,代码如下:

左影子控件(上一曲专辑唱盘)

TranslationX="{Binding Source={x:Reference  DefaultPanContainer} ,Path=Content.TranslationX,Converter={StaticResource CalcValueConverter},ConverterParameter=-1}"

右影子控件(下一曲专辑唱盘)

TranslationX="{Binding Source={x:Reference  DefaultPanContainer} ,Path=Content.TranslationX,Converter={StaticResource CalcValueConverter},ConverterParameter=-1}"

[MAUI]模仿网易云音乐黑胶唱片的交互实现

唱盘拨动交互

当然我们仅希望拖拽物仅在水平方向上响应手势

在HorizontalPanContainer中,注册PanGestureRecognizer的响应事件PanGestureRecognizer_OnPanUpdated,在GestureStatus.Running添加代码如下:

private async void PanGestureRecognizer_OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
    var isInPit = false;
    switch (e.StatusType)
    {
        case GestureStatus.Running:
            var translationX = PositionX + e.TotalX;
            var translationY = PositionY;

        ...
    }
}

结合上一小节写的三个PitGrid,此时拖拽唱盘,并且在拖拽开始,进入pit,离开pit,释放时,分别触发Start,In,Out,Over四个状态事件。

响应状态事件的有效区域如下

[MAUI]模仿网易云音乐黑胶唱片的交互实现

创建检测唱盘中心点是否在有效区域的方法,

当平移方向为向右时,唱盘中心点的X坐标应大于右pit区域的起始X坐标;
当平移方向为向左时,唱盘中心点的X坐标应小于左pit区域的结束X坐标。

在GestureStatus.Running添加代码如下:


foreach (var item in PitLayout)
{
    var pitRegion = new Region(item.X, item.X + item.Width, item.Y, item.Y + item.Height, item.PitName);
    var isXin = (e.TotalX>0 && translationX >= pitRegion.StartX - Content.Width / 2 && pitRegion.StartX>this.Width/2)||
        (e.TotalX<0 && translationX <= pitRegion.EndX - Content.Width / 2&&pitRegion.EndX<this.Width/2);
    if (isXin)
    {
        isInPit = true;      
    }
    ...
}

在不同的pit中,处理对应的状态事件。

若在手指离开时,唱盘的中心点还在MiddlePit区域范围内,则将唱盘回弹移动到MiddlePit中心点。

若在LeftPit或RightPit区域,则将唱盘移动到LeftPit或RightPit区域中心点。

[MAUI]模仿网易云音乐黑胶唱片的交互实现

此时已经实现了拖拽唱盘的基本功能,但是在释放唱盘时,影子唱盘并没有如预期那样移动到MiddlePit的中心点。

[MAUI]模仿网易云音乐黑胶唱片的交互实现

当命中LeftPit或RightPit区域时,我们希望影子控件移动到MiddlePit中心点。当影子控件移动到位时,替换掉当前的唱盘,成为新的拖拽物。由此可以无限的拨动唱盘实现连续切歌的效果。

当手指释放,唱盘准备向左或右移动时,迅速将影子控件的位置替换成当前唱盘的位置。用当前唱盘的“瞬移”,看起来像唱盘被影子唱盘替换掉了,但是在屏幕中心活动的拖拽物,一直是真正的那个控件。

在GestureStatus.Completed添加代码如下:

case GestureStatus.Completed:
    double destinationX;
    var view = this.CurrentView;

    if (isInPitPre)
    {
        var pitRegion = new Region(view.X, view.X + view.Width, view.Y, view.Y + view.Height, view.PitName);

        var prefix = pitRegion.StartX>this.Width/2 ? 1 : -1;
        destinationX=PositionX+prefix*(App.Current as App).PanContainerWidth;
    }
    else
    {
        destinationX=PositionX;

    }

这样看起来像可以无限地拨动唱盘了

[MAUI]模仿网易云音乐黑胶唱片的交互实现

唱盘和唱针动画

唱盘转动,音乐随之播放,通过将专辑封面图片以20秒每圈的速度旋转来实现唱盘旋转的效果。

在NowPlayingPage中创建一个Animation对象,用于控制唱盘旋转。

private Animation rotateAnimation;

编写启动旋转动画方法StartAlbumArtRotation以及停止动画方法StopAlbumArtRotation,代码如下:

private void StartAlbumArtRotation()
{
    this.AlbumArtImage.AbortAnimation("AlbumArtImageAnimation");
    rotateAnimation = new Animation(v => this.AlbumArtImage.Rotation = v, this.AlbumArtImage.Rotation, this.AlbumArtImage.Rotation+ 360);
    rotateAnimation.Commit(this, "AlbumArtImageAnimation", 16, 20*1000, repeat: () => true);
}

private void StopAlbumArtRotation()
{
    this.AlbumArtImage.CancelAnimations();
    if (this.rotateAnimation!=null)
    {
        this.rotateAnimation.Dispose();
    }

}

效果如下:

[MAUI]模仿网易云音乐黑胶唱片的交互实现

注意,当音乐暂停后,停止旋转动画,当音乐恢复播放时,转盘应从之前停止的角度开始启动旋转动画。

在拨动唱盘或切歌时,唱针将从唱盘上移开,通过旋转唱针图片30度来实现唱针移开的效果。

[MAUI]模仿网易云音乐黑胶唱片的交互实现

首先设置锚点,AnchorX=0.18,AnchorY=0.059,如下:

<Image WidthRequest="100"
    HeightRequest="167"
    HorizontalOptions="Center"
    VerticalOptions="Start"
    Margin="70,-50,0,0"
    Source="ic_needle.png"
    x:Name="AlbumNeedle"
    AnchorX="0.18"
    AnchorY="0.059" />

在音乐播放时
当手指开始滑动时,唱针从唱盘上移开,唱盘停止旋转;
当手指离开时,唱针回到唱盘上,唱盘继续旋转。

private async void PanActionHandler(object recipient, HorizontalPanActionArgs args)
{
    switch (args.PanType)
    {
        case HorizontalPanType.Over:

            if (MusicRelatedViewModel.IsPlaying)
            {
                await this.AlbumNeedle.RotateTo(0, 300);
                this.StartAlbumArtRotation();
            }


            break;
        case HorizontalPanType.Start:

            if (MusicRelatedViewModel.IsPlaying)
            {
                await this.AlbumNeedle.RotateTo(-30, 300);
                this.StopAlbumArtRotation();
            }
            break;
        ...
    }
}

效果如下:

[MAUI]模仿网易云音乐黑胶唱片的交互实现

当暂停、恢复时,唱针的位置也应该随之改变。

private async void MusicRelatedViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName==nameof(MusicRelatedViewModel.IsPlaying))
    {
        if (MusicRelatedViewModel.IsPlaying)
        {
            await this.AlbumNeedle.RotateTo(0, 300);
            this.StartAlbumArtRotation();
        }
        else
        {
            await this.AlbumNeedle.RotateTo(-30, 300);
            this.StopAlbumArtRotation();

        }

    }
}

效果如下:

[MAUI]模仿网易云音乐黑胶唱片的交互实现

最终效果如下:

[MAUI]模仿网易云音乐黑胶唱片的交互实现

项目地址

Github:maui-samples文章来源地址https://www.toymoban.com/news/detail-424568.html

到了这里,关于[MAUI]模仿网易云音乐黑胶唱片的交互实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序之网易云音乐的实现-云音乐

    基本介绍 基本功能都实现了,音乐的上一首下一首播放等,顺便把进度条的拖动播放写了下 主页的 每日推荐界面 写了 ,登录通过账号密码登录 (你也可以自己加一个验证码或者邮箱登录 ) 基于iPhone6(375*667分辨率)开发,后面一些计算都是通过获取当前屏幕下的尺寸来计算的,但是不

    2024年02月10日
    浏览(43)
  • 网易云音乐开发--音乐播放暂停切换上下首功能实现

     问题就是我们点击播放,暂停之后,再次播放,它会多次发起请求。而我们现在对它的优化是,不需要重复的发起请求 这里我们通过把musicLink改为形参的方式,如果有给它传入参数,没有链接那么就让它发起请求,如果有那就继续走下去。而且我们将musicLink保存到data中 

    2024年02月06日
    浏览(42)
  • 网易云音乐开发--个人中心页效果实现

    就是我们真机调试,是没有数据的 就是我们手机上去访问我们电脑上自己搭的服务器,肯定是访问不到的 此时就需要我们内网穿透 1.win+R  输入 cmd 输入ipconfig 2.找到无线局域网适配器的IPv4 3.重新设置一个新的地址,只需将host中的localhost改为你的IPv4 4.用手机连上电脑的热点

    2024年02月04日
    浏览(44)
  • 网易音乐网站系统|前后端分离springboot+vue实现在线音乐网站

    作者主页:编程千纸鹤 作者简介:Java、前端、Python开发多年,做过高程,项目经理,架构师 主要内容:Java项目开发、毕业设计开发、面试技术整理、最新技术分享 收藏点赞不迷路  关注作者有好处 文末获得源码 项目编号:BS-PT-104 网易音乐网站系统是一个在线的音乐网站

    2024年02月05日
    浏览(42)
  • 【微信小程序学习】网易云音乐歌曲详情页代码实现

    这里记录一下做网易云小程序的音乐播放详情页面的代码。 音乐播放界面的主要的重点有几个:   1、磁盘和摇杆的旋转效果,这里运用了css的动画属性   2、音乐播放和暂停,下一首/上一首等播放效果的实现   3、进度条的样式和控制   4、和上一页音乐推荐列表页通信,利

    2024年02月09日
    浏览(46)
  • 网易云音乐开发--search模块基本功能实现(除历史记录模块)

    老样子搭建一个search搜索页面  还有一块没有实现,那就是让输入框默认的文本变换颜色  微信小程序: input输入框placeholder样式的修改_微信小程序placeholder样式_酷伊奥的博客-CSDN博客  百度搜索了一下,找到了这个大佬的解决方案。很nice 查看文档 网易云音乐 NodeJS 版 API (b

    2024年02月06日
    浏览(79)
  • 微信小程序网易云音乐设计与实现 毕业设计-附源码261620

    随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,微信小程序的网易云音乐系统被用户普遍使用,为方便用户能够可以随时进行微信小程序的网易云音乐系统的

    2024年02月05日
    浏览(39)
  • ssm+微信小程序网易云音乐设计与实现毕业设计源码261620

    随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,微信小程序的网易云音乐系统被用户普遍使用,为方便用户能够可以随时进行微信小程序的网易云音乐系统的

    2023年04月17日
    浏览(43)
  • SSM+微信小程序网易云音乐设计与实现 毕业设计-附源码261620

      随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,微信小程序的网易云音乐系统被用户普遍使用,为方便用户能够可以随时进行微信小程序的网易云音乐系统

    2024年02月10日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包