Android exoplayer subtitleview 字幕 居中`置顶`置底位置设置方法

解决办法

        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, 置底就改成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的一些原理就容易很多了. 

        楼主是第一次分析源码, 如果文章中有错误的地方, 请各位大佬指点. 以防误导前来学习的同学~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃饱很舒服

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值