[MAUI 项目实战] 手势控制音乐播放器(四):圆形进度条

这篇具有很好参考价值的文章主要介绍了[MAUI 项目实战] 手势控制音乐播放器(四):圆形进度条。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

@

目录
  • 关于图形绘制
  • 创建自定义控件
  • 使用控件
  • 创建专辑封面
  • 项目地址

我们将绘制一个圆形的音乐播放控件,它包含一个圆形的进度条、专辑页面和播放按钮。

[MAUI 项目实战] 手势控制音乐播放器(四):圆形进度条

关于图形绘制

使用MAUI的绘制功能,需要Microsoft.Maui.Graphics库。

Microsoft.Maui.Graphics 是一个实验性的跨平台图形库,它可以在 .NET MAUI 中使用。它提供了一组基本的图形元素,如矩形、圆形、线条、路径、文本和图像。它还提供了一组基本的图形操作,如填充、描边、裁剪、变换和渐变。

Microsoft.Maui.Graphics在不同的目标平台上使用一致的API访问本机图形功能,而底层实现使用了不同的图形渲染引擎。其中通用性较好的是SkiaSharp图形库,支持几乎所有的操作系统,在不同平台上的表现也近乎一致。

创建自定义控件

在项目中添加SkiaSharp绘制功能的引用Microsoft.Maui.Graphics.Skia以及SkiaSharp.Views.Maui.Controls

<ItemGroup>
    <PackageReference Include="Microsoft.Maui.Graphics.Skia" Version="7.0.59" />
    <PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="2.88.3" />
</ItemGroup>

创建CircleSlider.xaml文件,添加如下内容:

<?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"
             xmlns:forms="clr-namespace:SkiaSharp.Views.Maui.Controls;assembly=SkiaSharp.Views.Maui.Controls"
             
             x:Class="MatoMusic.Controls.CircleSlider">
  <ContentView.Content>

      <forms:SKCanvasView x:Name="canvasView"
                          PaintSurface="OnCanvasViewPaintSurface" />

    </ContentView.Content>
</ContentView>

SKCanvasView是SkiaSharp.Views.Maui.Controls封装的View控件。

打开CircleSlider.xaml.cs文件

控件将包含以下可绑定属性:

  • Maximum:最大值
  • Minimum:最小值
  • Value:当前值
  • TintColor:进度条颜色
  • ContainerColor:进度条背景颜色
  • BorderWidth:进度条宽度

定义两个SKPaint画笔属性,OutlinePaint用于绘制进度条背景,ArcPaint用于绘制进度条本身。他们的描边宽度StrokeWidth则是圆形进度条的宽度。
两个画笔的初始值样式为SKPaintStyle.Stroke,描边宽度为BorderWidth的值。

private SKPaint _outlinePaint;

public SKPaint OutlinePaint
{
    get
    {
        if (_outlinePaint == null)
        {
            SKPaint outlinePaint = new SKPaint
            {
                Style = SKPaintStyle.Stroke,
                StrokeWidth = BorderWidth,
            };
            _outlinePaint = outlinePaint;
        }
        return
            _outlinePaint;
    }
    set { _outlinePaint = value; }
}

private SKPaint _arcPaint;

public SKPaint ArcPaint
{
    get
    {
        if (_arcPaint == null)
        {
            SKPaint arcPaint = new SKPaint
            {
                Style = SKPaintStyle.Stroke,
                StrokeWidth = BorderWidth,
            };
            _arcPaint = arcPaint;
        }

        return _arcPaint;
    }
    set { _arcPaint = value; }
}

SetStrokeWidth用于设置描边宽度,并产生一个动效,

[MAUI 项目实战] 手势控制音乐播放器(四):圆形进度条

在BorderWidth发生变更的时候,会出现一个动效。宽度会缓慢地变化至新的值。刷新率为10ms一次,每次变化的值为1。


private float _borderWidth;

public float BorderWidth
{
    get { return _borderWidth; }
    set
    {
        var old_borderWidth = _borderWidth;

        var span = value - old_borderWidth;

        SetStrokeWidth(span, old_borderWidth);

        _borderWidth = value;

        this.ArcPaint.StrokeWidth = _borderWidth;
        this.OutlinePaint.StrokeWidth = _borderWidth;
    }
}

private async void SetStrokeWidth(float span, float old_borderWidth)
{
    if (span > 0)
    {
        for (int i = 0; i <= span; i++)
        {
            await Task.Delay(10);
            this.ArcPaint.StrokeWidth = old_borderWidth + i;
            this.OutlinePaint.StrokeWidth = old_borderWidth + i;
            RefreshMainRectPadding();
        }
    }
    else
    {
        for (int i = 0; i >= span; i--)
        {
            await Task.Delay(10);
            this.ArcPaint.StrokeWidth = old_borderWidth + i;
            this.OutlinePaint.StrokeWidth = old_borderWidth + i;
            RefreshMainRectPadding();

        }
    }

}

于此同时,因为描边宽度变化了,需要对Padding进行补偿。调用RefreshMainRectPadding方法计算一个新的Padding值,BoderWidth缩小时,Padding也随之增大。

private void RefreshMainRectPadding()
{
    this._mainRectPadding =  this.BorderWidth / 2;
}

在视觉上,进度条宽度从内向外扩张变细。

[MAUI 项目实战] 手势控制音乐播放器(四):圆形进度条

若设为原宽度减去计算值,从视觉上是从外向内收缩变细。

private void RefreshMainRectPadding()
{
    this._mainRectPadding =  15 -  this.BorderWidth / 2;
}

[MAUI 项目实战] 手势控制音乐播放器(四):圆形进度条

接下来写订阅了CanvaseView的PaintSurface事件的方法OnCanvasViewPaintSurface。在这个方法中,我们将编写圆形进度条的绘制逻辑。

PaintSurface事件在绘制图形时触发。程序运行时会实时触发这个方法,它的参数SKPaintSurfaceEventArgs事件附带的对象具有两个属性:

  • Info类型SKImageInfo
  • Surface类型SKSurface

SKImageInfo对象包含如宽度和高度等有关绘图区域的信息,对象SKSurface为绘制本身,我们需要利用SKImageInfo宽度和高度等信息,结合业务数据,在SKSurface绘制出我们想要的图形。

清空上一次绘制的图形,调用SKSurface.Canvas获取Canvas对象,调用Canvas.Clear方法清空上一次绘制的图形。

canvas.Clear();

rect是一个SKRect对象,进度条本身是圆形,我们需要一个正方形的区域来控制圆形区域。

sweepAngle是当前进度对应的角度,首先计算出总进度值,通过计算当前进度对应总进度的比值,换算成角度,将这一角度赋值给sweepAngle。

startAngle是进度条的起始角度,我们将其设置为-90度,即从正上方开始绘制。


SKRect rect = new SKRect(_mainRectPadding, _mainRectPadding, info.Width - _mainRectPadding, info.Height - _mainRectPadding);
float startAngle = -90;
float sweepAngle = (float)((Value / SumValue) * 360);

调用Canvas.DrawOval,使用OutlinePaint画笔绘制进度条背景,它是一个圆形

canvas.DrawOval(rect, OutlinePaint);

创建绘制路径path,调用AddArc方法,将rect对象和起始角度和终止角度传入,即可绘制出弧形。

using (SKPath path = new SKPath())
{
    path.AddArc(rect, startAngle, sweepAngle);
    canvas.DrawPath(path, ArcPaint);
}

绘制部分的完整代码如下:

private void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{

    var SumValue = Maximum - Minimum;


    SKImageInfo info = args.Info;
    SKSurface surface = args.Surface;
    SKCanvas canvas = surface.Canvas;

    canvas.Clear();

    SKRect rect = new SKRect(_mainRectPadding, _mainRectPadding, info.Width - _mainRectPadding, info.Height - _mainRectPadding);
    float startAngle = -90;
    float sweepAngle = (float)((Value / SumValue) * 360);

    canvas.DrawOval(rect, OutlinePaint);

    using (SKPath path = new SKPath())
    {
        path.AddArc(rect, startAngle, sweepAngle);
        canvas.DrawPath(path, ArcPaint);
    }
}

使用控件

在MainPage.xaml中添加一个CircleSlider控件,
设置的Maximum,是当前曲目的时长,Value是当前曲目的进度

<controls:CircleSlider 
    HeightRequest="250"
    WidthRequest="250"
    x:Name="MainCircleSlider"
    Maximum="{Binding Duration}"
    Minimum="0.0"
    TintColor="#FFFFFF"
    ContainerColor="#4CFFFFFF"
    IsEnabled="{Binding Canplay}"
    ValueChanged="OnValueChanged"
    Value="{Binding CurrentTime,Mode=TwoWay} ">
</controls:CircleSlider>

创建专辑封面

使用MAUI的VisualElement中的Clip属性,创建Clip裁剪,可以传入一个Geometry对象,这里我们使用RoundRectangleGeometry,将它的CornerRadius属性设置为图片宽度的一半,即可实现圆形图片。

<Image HeightRequest="250"
        WidthRequest="250"
        Margin="7.5"
        Source="{Binding  CurrentMusic.AlbumArt}"
        VerticalOptions="CenterAndExpand"
        HorizontalOptions="CenterAndExpand"
        Aspect="AspectFill">
    <Image.Clip>
        <RoundRectangleGeometry  CornerRadius="125" Rect="0,0,250,250" />
    </Image.Clip>
</Image>

设置一个半透明背景的播放状态指示器,当IsPlaying为False时将显示一个播放按钮

<Grid IsVisible="{Binding IsPlaying, Converter={StaticResource True2FalseConverter}}">
    <BoxView HeightRequest="250"
            WidthRequest="250"
            Margin="7.5"
            Color="#60000000"
            VerticalOptions="CenterAndExpand"
            HorizontalOptions="CenterAndExpand"
            CornerRadius="250" ></BoxView>
    <Label  x:Name="PauseLabel"                               
            HorizontalOptions="CenterAndExpand"
            FontSize="58"  
            TextColor="{Binding Canplay,Converter={StaticResource Bool2StringConverter},ConverterParameter=White|#434343}"
            FontFamily="FontAwesome"
            Margin="0"></Label>
</Grid>

[MAUI 项目实战] 手势控制音乐播放器(四):圆形进度条

创建PanContainer对象,用于实现拖动效果,设置AutoAdsorption属性为True,即可实现拖动后自动吸附效果。

关于PanContainer请查看上期的文章:平移手势交互

用一个Grid将专辑封面,CircleSlider,以及播放状态指示器包裹起来。完整代码如下

 <controls1:PanContainer BackgroundColor="Transparent"
                        x:Name="DefaultPanContainer"
                        OnTapped="DefaultPanContainer_OnOnTapped"
                        AutoAdsorption="True"
                        OnfinishedChoise="DefaultPanContainer_OnOnfinishedChoise">
    <Grid PropertyChanged="BindableObject_OnPropertyChanged"
        VerticalOptions="Start"
        HorizontalOptions="Start">
        <Image HeightRequest="250"
                WidthRequest="250"
                Margin="7.5"
                Source="{Binding  CurrentMusic.AlbumArt}"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="CenterAndExpand"
                Aspect="AspectFill">
            <Image.Clip>
                <RoundRectangleGeometry  CornerRadius="125" Rect="0,0,250,250" />
            </Image.Clip>
        </Image>
        <controls:CircleSlider>...</controls:CircleSlider>
        <Grid IsVisible="{Binding IsPlaying, Converter={StaticResource True2FalseConverter}}">
            <BoxView HeightRequest="250"
                    WidthRequest="250"
                    Margin="7.5"
                    Color="#60000000"
                    VerticalOptions="CenterAndExpand"
                    HorizontalOptions="CenterAndExpand"
                    CornerRadius="250" ></BoxView>
            <Label  x:Name="PauseLabel"                               
                    HorizontalOptions="CenterAndExpand"
                    FontSize="58"  
                    TextColor="{Binding Canplay,Converter={StaticResource Bool2StringConverter},ConverterParameter=White|#434343}"
                    FontFamily="FontAwesome"
                    Margin="0"></Label>
        </Grid>
    </Grid>
</controls1:PanContainer>

[MAUI 项目实战] 手势控制音乐播放器(四):圆形进度条
以上就是这个项目的全部内容,感谢阅读

项目地址

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

到了这里,关于[MAUI 项目实战] 手势控制音乐播放器(四):圆形进度条的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 《微信小程序》音乐播放器项目

    需求:在装有node.js的机器上使用微信开发者工具开发一个音乐播放项目 写这个项目的时候电脑前后蓝屏了5次,制作不易,希望大佬们给个双击,顺子在这感谢啦! 展示: pages–index–index.js 01.png 02.png 02stop.png 03.png 04.png 05.png 06.png banner.jpg banner2.jpg banner3.jpg cover.jpg cover1.png

    2024年02月11日
    浏览(47)
  • 项目7-音乐播放器6+评论区

    前端小白:怎么为你的网页增加评论功能?(一)_为网页添加评论区怎么弄-CSDN博客 参考的上述文章的前端代码 我们从上述前端图片知道,我们数据库需要准备的字段: id,commentuserName,coomentmusicId,comment,time 路径:\\\"/comment/upload\\\" 1.MAPPER 2.SERVICE 3.Controller MAPPER SERVICE CONTROLLER 成功

    2024年04月23日
    浏览(67)
  • 项目7-音乐播放器2(上传音乐+查询音乐+拦截器)

    之后就不用对用户是否登录进行判断了 生效 请求: { post, /music/upload {singer,MultipartFile file}, } 响应: { \\\"status\\\": 0, \\\"message\\\": \\\"上传成功!\\\", \\\"data\\\": true } Java如何判断一个文件是否为真实的MP3文件_判断一个文件是否是mp3 文件-CSDN博客 流程:前端进行相关的文件操作-再将上传的文

    2024年04月17日
    浏览(46)
  • 小项目开发——Android 音乐播放器

    ◼ 音乐播放器 . ◼ 要求 : Activity 编程、 ListView 编程、 SeekBar 编程、 ExoPlayer 编程( 播放 、 暂停 、 停止 、 上一首 、 下一首 ),音乐文件放在 assets/music 目录下,界面自拟. ◼ 期望最终效果: ◼ 分别对应 activity_music_list.xml 、 activity_my_music_player.xml 的视图. ◼ 点击列表任

    2024年01月21日
    浏览(41)
  • 完整实例项目:使用python自制音乐播放器~

    今天使用python的pygame等模块制作了一个简单的音乐播放器,实现了很多好玩的功能,在这里和大家一起分享!这是笔者的第二篇博客,也是正式的完成一个小项目,希望获得大家的支持~ 暂停、继续播放、调整声音大小、上一曲下一曲调整、无限制追加音乐(但需要下载音乐

    2024年02月11日
    浏览(40)
  • 微信小程序仿网易音乐播放器项目

    主页样式 播放页样式 搜索页样式 排行榜页样式 小控件样式 网易云音乐API接口 后端接口,使用node写的,使用了网易云音乐API: 封装的api文件 主页面功能点 banner,滑动菜单栏采用微信的API( swiper 与 scroll-view )进行开发 滑动到底部重新获取后续的歌曲,使用onReachBottom周期

    2024年02月06日
    浏览(39)
  • 基于STM32制作的音乐播放器,用PWM控制蜂鸣器

    目录 效果展示  前言         一、设计背景         1.1、知识储备          二、系统设计方案         2.1、实现功能          2.2、硬件部分         2.3、软件部分          三、软件设计          3.1、设计流程图          3.2、音乐频率的设置          3.3、编

    2024年02月03日
    浏览(72)
  • 开源小项目 - 基于无源蜂鸣器实现的音乐播放器

    目录 一、音乐简谱相关知识 1、音符 2、音调 3、识读简谱 1. 找到简谱中C调的音符对应的蜂鸣器频率(确定音调对应的频率) 2. 确定蜂鸣器演奏一拍所需的时间(即确定一个音调对应的节拍数) 3.创建结构体确定一个音符所需的两个属性(音调频率、节拍数) 4.将《两只老虎

    2024年03月10日
    浏览(49)
  • 【无标题】单片机小项目———音乐播放器(keil+protues)

    刚学完单片机的朋友可以看一看。 主要功能: 1.播放音乐 2.切歌 3.显示歌曲数 仿真:  代码: #includeREG52.H //#define sound_amount 5  sbit play_up=P1^0;        sbit play_down=P1^1;    sbit pause=P1^2;        sbit speaker=P3^1;      unsigned char timer0h,timer0l,time,n; unsigned char music_num;    unsigned int

    2024年02月11日
    浏览(46)
  • 微信小程序做一个圆形图片旋转可以控制开始和结束-音乐播放器的图片旋转功能

    1.在 WXML 文件中添加一个 标签,并设置图片的 src 和样式,并为其绑定一个 animation 用来控制旋转动画。 2.在 WXSS 文件中添加样式,将图片设置为圆形并居中显示。 3.在 JS 文件中定义旋转动画对象和控制方法。 4.在 WXML 文件中添加按钮来触发开始和结束旋转动画。 在以上步骤

    2024年02月16日
    浏览(40)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包