返回介绍

构造方法

发布于 2024-12-23 22:10:47 字数 4400 浏览 0 评论 0 收藏

StaticLayout 有多个构造方法,最完整的构造方法(其他构造方法最终也是调用的这个构造方法) 如下所示:

public StaticLayout(CharSequence source, int bufstart, int bufend,
            TextPaint paint, int outerwidth,
            Alignment align, TextDirectionHeuristic textDir,
            float spacingmult, float spacingadd,
            boolean includepad,
            TextUtils.TruncateAt ellipsize, int ellipsizedWidth, int maxLines) {
    super((ellipsize == null)
        ? source
        : (source instanceof Spanned)
          ? new SpannedEllipsizer(source)
          : new Ellipsizer(source),
        paint, outerwidth, align, textDir, spacingmult, spacingadd);

    Builder b = Builder.obtain(source, bufstart, bufend, paint, outerwidth)
      .setAlignment(align)
      .setTextDirection(textDir)
      .setLineSpacing(spacingadd, spacingmult)
      .setIncludePad(includepad)
      .setEllipsizedWidth(ellipsizedWidth)
      .setEllipsize(ellipsize)
      .setMaxLines(maxLines);
    if (ellipsize != null) {
      Ellipsizer e = (Ellipsizer) getText();

      e.mLayout = this;
      e.mWidth = ellipsizedWidth;
      e.mMethod = ellipsize;
      mEllipsizedWidth = ellipsizedWidth;
      mColumns = COLUMNS_ELLIPSIZE;
    } else {
      mColumns = COLUMNS_NORMAL;
      mEllipsizedWidth = outerwidth;
    }

    mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, 2 * mColumns);
    mLines = new int[mLineDirections.length];
    mMaximumVisibleLineCount = maxLines;

    generate(b, b.mIncludePad, b.mIncludePad);

    Builder.recycle(b);
  }

参数说明:

  • CharSequence source 文本内容
  • int bufstart, int bufend, 开始位置和结束位置
  • TextPaint paint 文本画笔对象
  • int outerwidth 布局宽度,超出宽度换行显示
  • Alignment align 对齐方式,默认是 Alignment.ALIGN_LEFT
  • TextDirectionHeuristic textDir 文本显示方向
  • float spacingmult 行间距倍数,默认是 1
  • float spacingadd 行距增加值,默认是 0
  • boolean includepad 文本顶部和底部是否留白
  • TextUtils.TruncateAt ellipsize 文本省略方式,有 START、MIDDLE、 END、MARQUEE 四种省略方式(其实还有一个 END_SMALL,但是 Google 并未开放出来)。
  • int ellipsizedWidth 省略宽度
  • int maxLines 最大行数

细节分析:

  • 构造方法的开始,在调用父类 Layout 构造方法的时候,判断了文本是否需要省略,如果需要省略,则创建一个 Ellipsizer 对象,Ellipsizer 是 Layout 的嵌套内部类,实现了 CharSequence 和 GetChars 接口。该类就是用来对文本进行省略处理的,具体的处理方法是由其 getChars() 方法完成的。
  • 在创建 Ellipsizer 对象之前,还判断了一下需要显示的文本是否是 Spanned ,如果是的话则创建 SpannedEllipsizer 对象,SpannedEllipsizer 类继承 Ellipsizer ,同时实现了 Spanned 接口。
  • StaticLayout.Builder 对象的创建是通过 Builder.obtain() 方法创建的,在该方法内部可以看到 Builder 对象通过 SynchronizedPool 对象池来管理的,起到缓存的作用,避免 Builder 对象的重复创建,在 StaticLayout 的构造方法的最后也可以看到 Builder.recycle(b) 的调用,回收 Builder 对象。 Builder 的构造方法如下所示:
     private Builder() {
        mNativePtr = nNewBuilder();
      }
    

    其调用了 JNI 层的 nNewBuilder() 方法,新建了一个 LineBreak 对象,并将其指针指向 java 层,赋值给 Builder 对象的 mNativePtr 字段 ,后面调用 native 方法时,均需要将 mNativePtr 作为参数传递过去。

     static jlong nNewBuilder(JNIEnv*, jclass) {
        return reinterpret_cast<jlong>(new LineBreaker);
     }
    
  • mLineDirections 需要结合到后面每行文本处理来理解,这里可以大致说一下,StaticLayout 源码中声明了以下的常量:
     int COLUMNS_NORMAL = 4;
     int COLUMNS_ELLIPSIZE = 6;
     int START = 0;
     int DIR = START;
     int TAB = START;
     int TOP = 1;
     int DESCENT = 2;
     int HYPHEN = 3;
     int ELLIPSIS_START = 4;
     int ELLIPSIS_COUNT = 5;
    

    其中 COLUMNS_NORMAL 和 COLUMNS_ELLIPSIZE 会赋值给全局变量 mColumns,正如你在构造方法中看到的那样,这个在没一行处理时会用到,每一行文本处理时需要记录四个值,start,top,desent,hyphen 值,当文本需要省略时,还需要记录 ellipsis_start 和 ellipsis_count 值,因此正常的 mColumn 值为 4,省略时则是 6,因此 mLineDirections 数组大小始终是 mColumn 的倍数,mLine 数组的大小和其保持一致(从后面的分析来看,mLineDirections 数组的大小没必要这么大)。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。