上一期我们制作了类似YouTube 的视频预览功能,这期我们来继续添加时段关注度图表展示功能,YouTube上我们在拖动进度条时可以看到进度条上有一个曲线图,来表示不同时段的流量大小,来告诉用户大部分用户对那个时段的内容最感兴趣,如下图
下面我们还是基于nifty-slider来快速实现以上效果
一、先看下最终效果
二、添加依赖
dependencies {
//基础库 - 实现视频拖动的基础功能
implementation 'io.github.litao0621:nifty-slider:(latest version)'
//可选的效果库 - 来实现touch down、touch up后滑动的放大缩小效果
implementation 'io.github.litao0621:nifty-slider-effect:(latest version)'
}
三、功能实现
- 添加基础控件
<com.litao.slider.NiftySlider
android:id="@+id/nifty_slider"
android:layout_width="0dp"
android:layout_height="64dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:valueFrom="0"
android:valueTo="100"
android:value="0"
app:tipViewVisible="false"
app:enableDrawHalo="false"
app:trackHeight="3dp"
app:trackColor="@color/youtube_theme_color"
app:trackColorInactive="#44FFFFFF"
app:thumbColor="@color/youtube_theme_color"
app:thumbShadowColor="@android:color/transparent"
app:thumbRadius="6dp"
app:thumbWithinTrackBounds="true"
app:trackCornersRadius="0dp"
/>
- 定义我们自己的交互效果,来完成图表的绘制与显隐动画, 首先继承BaseEffect,我们主要实现以下几个方法。
-
onStartTacking()
: 用于用户开始拖动进度时展示图表 -
onStopTacking()
: 用于用户结束拖动进度时隐藏图表 -
onDrawBefore()
: 用户图表的具体绘制逻辑
-
- 添加图表绘制逻辑
// 曲线图的关键点位置信息
//x: 与slider 的进度相对应,slider.valueFrom < x < slider.valueTo
//y: 一般传递具体时间段段热度值,流量值等
private val keyPoints = mutableListOf<PointF>()
override fun onDrawBefore(canvas: Canvas, trackRect: RectF, yCenter: Float) {
//转化为真实的x绘制坐标,将关节点对应的进度信息换算为具体坐标
//(当前进度/总进度)* 滑动条宽度 + 滑动条起始x坐标
fun getRealX(x: Float): Float {
return (x - slider.valueFrom) / (slider.valueTo - slider.valueFrom) * trackRect.width() + trackRect.left
}
//转化为真实的y绘制坐标,y坐标会根据当前定义的最大高度进行比例压缩
fun getRealY(y: Float): Float {
return yCenter - y * heightFraction - slider.trackHeight / 2f
}
chartPath.reset()
var lastX = getRealX(0f)
var lastY = getRealY(0f)
//移动到其实位置
chartPath.moveTo(lastX, lastY)
keyPoints.forEachIndexed { index, pointF ->
val realX = getRealX(pointF.x)
val realY = getRealY(pointF.y * progress)
//贝塞尔曲线控制点,让曲线关键点过渡更为平滑
val x1 = (realX - lastX) / 2f + lastX
val y1 = lastY
val x2 = (realX - lastX) / 2f + lastX
val y2 = realY
chartPath.cubicTo(x1, y1, x2, y2, realX, realY)
lastX = realX
lastY = realY
}
chartPath.close()
}
查看效果的完整代码
- 使用我们创建好的交互效果
//创建图表交互效果
val chartEffect = ChartEffect(sliderView).apply {
//设置图标颜色
chartColor = Color.parseColor("#33FFFFFF")
//设置图标最大高度
chartMaxHeight = 28f.dp
//设置图标关点
updateKeyPoint(mutableListOf(
PointF(0f,10f),
PointF(5f,50f),
PointF(10f,70f),
PointF(15f,130f),
PointF(20f,170f),
PointF(25f,70f),
PointF(30f,110f),
PointF(35f,20f),
PointF(40f,10f),
PointF(45f,110f),
PointF(50f,20f),
PointF(55f,100f),
PointF(60f,170f),
PointF(65f,120f),
PointF(70f,30f),
PointF(75f,80f),
PointF(80f,80f),
PointF(85f,180f),
PointF(90f,10f),
PointF(95f,180f),
PointF(100f,10f),
))
}
sliderView.apply {
effect = chartEffect
}
- 到目前我们就已经添加完成,可以看到我们开始时的效果了,nifty-slider 已经提供能丰富的自定义功能与自定义交互效果,如果大家觉得有不满足需求的都可以提出来,下期我们会提供类似YouTube 视频分章节的功能。
四、结束
YouTube视频关注度的完整Demo可以到这里查看
详细的属性文档可以到这里查看