WP8中自定义Lrc歌词同步显示控件(一)

  最近开始做WP8上的一个音乐相关的项目,在此之中需要一个Lrc歌词同步显示控件,核心功能即支持随播放进度同步显示歌词,当前正在演唱的一句歌词高亮并在控件中居中显示。

      因为之前在android中也写过这样一个Lrc歌词显示控件,当时的做法是控件继承TextView,并重写控件的自我绘制方法即OnDraw方法,在这个方法中绘制歌词,首先用高亮的画笔把当前正在演唱的一句歌词绘制在控件的竖直方向最中间,然后用其他颜色的画笔向上绘制在此句之前的歌词,向下绘制此句之后的歌词,随播放进度不断重绘自己既实现了一个歌词同步显示的控件。

  刚开始我也想用这样的思路在WP中实现,但是在WP中我们没有办法来重写控件的自我绘制方法,所以只有另辟蹊径。下面介绍一下我实现WP8下的歌词实现控件的思路。

  首先我们知道在歌词显示时歌词有3个部分,一个部分是正在演唱的那句歌词,一个部分是此句歌词之前的歌词,最后一个部分是此句歌词之后的歌词,如下图所示

所以在控件布局考虑上,我们可以用3个按竖直方向排列的TextBlock来承载这3部分的歌词,并把中间的TextBlock的Foreground设置成我们需要的高亮色就有了高亮效果了。因为我们需要在用户在控件上滑动时能上下滚动查看整个歌词内容,所以我们需要在布局外层有一个可滚动的容器控件即ScrollViewer控件。这时我们就有Lrc歌词同步显示的大体布局

 <ScrollViewer x:Name="RootScrollViewer">
        <Grid x:Name="RootGrid" >
              <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="*"/>
               </Grid.RowDefinitions>
               <TextBlock x:Name="TopRowText" Grid.Row="0" TextWrapping="Wrap" 
VerticalAlignment="Bottom"
TextAlignment="Center" Foreground="{TemplateBinding Foreground}"/> <TextBlock x:Name="MidRowText" Grid.Row="1" TextWrapping="Wrap"
Foreground="{TemplateBinding EmphasisBrush}" TextAlignment="Center"/> <TextBlock x:Name="BottomRowText" Grid.Row="2" TextWrapping="Wrap"
VerticalAlignment="Top" TextAlignment="Center"

Foreground
="{TemplateBinding Foreground}" /> </Grid> </ScrollViewer>

 接下来考虑的问题是如何确保在播放时,正在演唱的那句歌词在控件的中间显示。针对以上的控件布局,我们要做的就是调整ScrollViewer的竖直滚动偏移量,使承载正在演唱的那一句歌词的TextBlock滚动到Lrc歌词显示控件的竖直中间。怎么确定ScrollViewer的这个竖直滚动偏移量呢?其实也很简单,我们知道在RootSrcollViewer没有滚动的情形下MidRowText不在控件中间时有两种情况:

  1.TopRowText的高度与MidRowText的一半的高度和小于RootScrollViewer高度的一半,即TopRowText.ActualHeight + MidTextBlock.ActualHeight / 2 < RootScrollViewer.ActualHeight/2时,MidRowText将在控件竖直中间以上的位置

  2.TopRowText的高度与MidRowText的一半的高度和大于RootScrollViewer高度的一半,即TopRowText.ActualHeight + MidTextBlock.ActualHeight / 2 > RootScrollViewer.ActualHeight/2时,MidRowText将在控件竖直中间以下的位置

第一种情况我们不要调整RootScroolViewer的竖直滚动偏移量,因为调整了就会使MidRowText的位置会更靠上。第二种情况MidRowText的位置在控件中间以下,这是就需要调整RootScroolViewer的竖直滚动偏移量使其向上滚动一些,MidRowText正好在竖直居中。这时的这个竖直滚动偏移量verticalScrollOffset为:

1 double verticalScrollOffset = TopRowText.ActualHeight - RootScrollViewer.ActualHeight/2 
+ MidTextBlock.ActualHeight / 2 2 RootScrollViewer.ScrollToVerticalOffset(verticalScrollOffset);

  至此我们解决了实现自定义Lrc同步歌词显示控件的所有关键问题。当播放进度变化时,我们把当前正在播放的那句歌词赋值给MidRowText.Text属性,前面的歌词赋值给TopRowText.Text属性,后面的歌词赋值给BottomRowText.Text属性,并相应调整RootScrollViewer的竖直偏移量使MidRowText显示在控件的竖直正中间。

  当然还有lrc歌词的解析,如何确定当前播放到那一句歌词等问题,关于lrc歌词的解析,网上有很多算法了请自行搜索参阅;lrc歌词解析好后,当前播放到哪一句歌词的确定就不是问题了,只要给出当前播放的进度,查找一下就可以确定了。

     具体的Lrc歌词同步显示控件实现将在接下来的一篇文章介绍。

本文章为原创文章,转载请注明出处:http://www.cnblogs.com/westmount/p/3550558.html

原文地址:https://www.cnblogs.com/westmount/p/3550558.html