解决办法
????????Talk is cheap. Show me the code.
// 在subtitleView.setCues的地方使用newCues就可以啦~
override fun onCues(cues: MutableList<Cue>) {
super.onCues(cues)
val newCues = ArrayList<Cue>()
for (cue in cues) {
val newCue = cue.buildUpon().apply {
setLine(0.5f, Cue.LINE_TYPE_FRACTION)
lineAnchor = Cue.ANCHOR_TYPE_MIDDLE
}.build()
newCues.add(newCue)
}
subtitleView.setCues(newCues)
}
copy上面的代码, 字幕就可以居中啦, 置顶就把0.5改成0, 置底就改成1?over~
下面分析一下上面代码的形成过程, 有兴趣的可以看一哈~
起因????????
????????我们的首席设计师小姐姐说字幕要居中才好看, 虽然不知道咋设置, 但咱不能在漂亮妹子面前丢人鸭!(行, 给爷👴🏻等着~) ????????在成功的google和百度失败之后, 我决定自己分析源码解决. 当然也是为了让我们成为更有效率的 google/百度 程序员, 于是我就把分析经历整理分享出来~
源码分析
????????下面给个源码分析,?基于exoplayer版本 2.14.1
首先看SubtitleView是个什么东西, 如下
public final class SubtitleView extends FrameLayout implements TextOutput {
...
}
ok, SubtitleView只是一个ViewGroup, 不做具体的字幕显示, 那谁来显示字幕呢, 当然是他的childView啦, 而childView当然是通过addView引入的, 搜索addView看到, 如下
public SubtitleView(Context context, @Nullable AttributeSet attrs) {
...
CanvasSubtitleOutput canvasSubtitleOutput = new CanvasSubtitleOutput(context, attrs);
output = canvasSubtitleOutput;
innerSubtitleView = canvasSubtitleOutput;
addView(innerSubtitleView);
...
}
可以看到, 在SubtitleView初始化的时候, 添加了一个childView -> CavasSubtitleOutput, 那绘制字幕一定就在这里面啦! 但是CavasSubtitleOutput中没有重写onDraw函数, 而是重写了dispatchDraw,?这个不是本文的重点(其实是我不了解~), 大家可以自行搜索~
然后就是一层一层地调用跟进啦, 最终我们在SubtitlePainter -> setupTextLayout 函数中, 找到如下代码
if (cueLine != Cue.DIMEN_UNSET) {
if (cueLineType == Cue.LINE_TYPE_FRACTION) {
int anchorPosition = Math.round(parentHeight * cueLine) + parentTop;
textTop =
cueLineAnchor == Cue.ANCHOR_TYPE_END
? anchorPosition - textHeight
: cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE
? (anchorPosition * 2 - textHeight) / 2
: anchorPosition;
} else {
// cueLineType == Cue.LINE_TYPE_NUMBER
int firstLineHeight = textLayout.getLineBottom(0) - textLayout.getLineTop(0);
if (cueLine >= 0) {
textTop = Math.round(cueLine * firstLineHeight) + parentTop;
} else {
textTop = Math.round((cueLine + 1) * firstLineHeight) + parentBottom - textHeight;
}
}
...
}
重点就是textTop了, 他的值就是y轴上字幕的实际摆放位置啦,? 代码中有稍显复杂的三目表达式, 认真看一下就能理解了(其实我还是觉得用if更清晰些), 所以我们就可以对cueLine和cuelineAnchor赋值进行字幕的位置更改了.
那么赋值是在哪里呢, 又经过了一段时间的认真查看, 我们知道了Cue的构造函数时私有的, 只能通过builder来创建对象, 所以最终就有了上面的解决办法啦~
? ? ? 另外就是 cueLineType == Cue.LINE_TYPE_NUMBER 的类型, 这个看起来是根据第一行字幕的高度来定位位置的, 大家可以根据需求来自己定制~
总结
? ? ? ? 总体来说分析起来还是挺简单的, 只要了解view的一些原理就容易很多了.?
????????楼主是第一次分析源码, 如果文章中有错误的地方, 请各位大佬指点. 以防误导前来学习的同学~
|