发布:2023/3/20 0:22:45作者:管理员 来源:本站 浏览次数:695
文章目录
前言
一、如何实现?
1.显示进度
2.拖动定位
3.点击定位
二、效果预览
总结
前言
实现一个播放器,必然需要一个进度条,一个基本的进度条通常用于显示进度、拖动定位,也可以点击定位,在wpf通常使用slider实现,改变其Value可以显示进度,但是拖动和点击也使用Value或ValueChanged时就会产生冲突,直接死循环了,所以我们需要将这3个功能区分开来,用不同的方式去实现。
一、如何实现?
1.显示进度
显示进度直接通过Slider的Value以及Minimum和Maximum实现即可。
设置播放总时长
sd_cursorTime.Minimum = 0;
sd_cursorTime.Maximum = e.Duration;//视频总时长
更新播放进度
sd_cursorTime.Value = e.Time;//当前播放时间
2.拖动定位
slider和scrollbar一样是基于RangeBase,其内部构造是一样的,甚至style也可以共用,其内部构造可以参考《C# wpf ScrollBar自定义样式详解》。slider的滑块就是一个Thumb控件,所以我们只需要注册Thumb控件的DragStarted和DragCompleted事件以及添加一个忽略当前播放时间标识,即能实现拖动定位了。
注册事件
<Slider x:Name="sd_cursorTime" Thumb.DragStarted="sb_cursorTime_DragStarted" Thumb.DragDelta="sb_cursorTime_DragDelta" Thumb.DragCompleted="sb_cursorTime_DragCompleted" />
事件中定位
//是否忽略播放进度更新
bool _isIgnoreCursorTime = false;
private void sd_cursorTime_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{ //忽略播放进度更新,让进度条拖动不受影响。
_isIgnoreCursorTime = true;
}
private void sb_cursorTime_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
//拖动中实时定位。根据需求,也可以不使用。
_play.Seek(sb_cursorTime.Value);
}
private void sd_cursorTime_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
//播放器定位
_play.Seek(sb_cursorTime.Value);
//还原标识,然进度条重新变化。
_isIgnoreCursorTime = false;
}
忽略播放进度更新
if(!_isIgnoreCursorTime )
sd_cursorTime.Value = e.Time;//当前播放时间
3.点击定位
一般到了这里,会想到直接使用IsMoveToPointEnabled="True"来实现点击定位,但实际上会遇到问题,点击进度条只会触发Value改变,使用Value会和显示进度功能冲突,而且IsMoveToPointEnabled设为True之后Slider的轨道会无法响应鼠标按下弹起事件,所以使用这个属性是行不通的。我们需要做是使用Slider的MouseDown事件,在事件中进行计算进度值然后定位。
需要注意IsMoveToPointEnabled不可设为True
<Slider x:Name="sd_cursorTime" PreviewMouseDown="sb_cursorTime_MouseDown" />
private void sd_cursorTime_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//根据鼠标点击位置的x值计算定位的Value值,下列代码是轨道宽等于slider控件宽的算法,如果情况不同情自行调整。
var value = (e.GetPosition(sd_cursorTime).X / sd_cursorTime.ActualWidth) * (sd_cursorTime.Maximum - sd_cursorTime.Minimum);
//播放器定位
_play.Seek(value);
}
二、效果预览
由于完整例子代码规模略大,涉及到一个完整的播放器,不便在这里展示,如果弄一个定时器的demo又不太真实,所以这里只给出效果预览:
总结
以上就是今天要讲的内容,实现一个播放进度条其实主要难点在于数据响应冲突,不能共用一个事件,需要将3个功能关联的事件独立开来。曾经试过只用Value绑定和ValueChanged的实现,以及使用一个隐藏slider用来定位的方式实现,但效果都不是特别好,本文讲述则是很好的实现了功能且简单易懂。
© Copyright 2014 - 2024 柏港建站平台 ejk5.com. 渝ICP备16000791号-4