Android StackLayout简单应用
创始人
2025-05-28 07:35:54
0

初识StaticLayout是在一个需要计算TextView高度的时候,计算完高度后对TextView进行分页显示。为此我仔细观看了TextView中计算高度的部分,并从中找到了答案

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int width;int height;// 篇幅太长,我们略过宽度部分,高度是由getDesiredHeight()来计算的... ...if (heightMode == MeasureSpec.EXACTLY) {// Parent has told us how big to be. So be it.height = heightSize;mDesiredHeightAtMeasure = -1;} else {int desired = getDesiredHeight();height = desired;mDesiredHeightAtMeasure = desired;if (heightMode == MeasureSpec.AT_MOST) {height = Math.min(desired, heightSize);}}... ...setMeasuredDimension(width, height);
}private int getDesiredHeight() {return Math.max(getDesiredHeight(mLayout, true),getDesiredHeight(mHintLayout, mEllipsize != null));
}private int getDesiredHeight(Layout layout, boolean cap) {if (layout == null) {return 0;}/** Don't cap the hint to a certain number of lines.* (Do cap it, though, if we have a maximum pixel height.)*/int desired = layout.getHeight(cap);final Drawables dr = mDrawables;if (dr != null) {desired = Math.max(desired, dr.mDrawableHeightLeft);desired = Math.max(desired, dr.mDrawableHeightRight);}int linecount = layout.getLineCount();final int padding = getCompoundPaddingTop() + getCompoundPaddingBottom();desired += padding;if (mMaxMode != LINES) {desired = Math.min(desired, mMaximum);} else if (cap && linecount > mMaximum && (layout instanceof DynamicLayout|| layout instanceof BoringLayout)) {desired = layout.getLineTop(mMaximum);if (dr != null) {desired = Math.max(desired, dr.mDrawableHeightLeft);desired = Math.max(desired, dr.mDrawableHeightRight);}desired += padding;linecount = mMaximum;}if (mMinMode == LINES) {if (linecount < mMinimum) {desired += getLineHeight() * (mMinimum - linecount);}} else {desired = Math.max(desired, mMinimum);}// Check against our minimum heightdesired = Math.max(desired, getSuggestedMinimumHeight());return desired;
}

从上面的代码中我们可以看到TextView中文本的高度是由Lyout.getHeight(boolean)得到的,由此可见,文字的管理是通过Layout实现的。TextView内部会根据不同的设置,创建不同的Layout,总共有三种。

  • DynamicLayout:用在EditText或者TextView中设置的是Spannable类型的文字。
  • BoringLayout:常用在处理单行文本。
  • StaticLayout:这个是默认的TextViewLayout,用在文字不会被改变的状态下。。

在这里我们主要研究了StaticLayout,用它来计算文本高度。StaticLayout是基于Builder模式创建的

var layout = StaticLayout.Builder.obtain(source, start, end, paint, width).setAlignment(alignment).setTextDirection(textDir).setLineSpacing(spacingAdd, spacingMult).setIncludePad(includePad).setBreakStrategy(breakStrategy).setHyphenationFrequency(hyphenationFrequency).setMaxLines(maxLine).build()

主要参数

  • source是文本,startend分别是开始和结束位置。
  • paintTextPaint,用来绘制文本。
  • width是文本宽度,文字到达这个宽度后就会自动换行。
  • alignment是文本对齐方向,主要有ALIGN_NORMAL/ALIGN_CENTER/ALIGN_OPPOSITE
  • spacingAdd是行间距的额外增加值,默认为0。spacingmult是行间距的倍数,默认是1。
  • includePad是指是否在文字上下添加额外的空间,超出ascentdescent部分。
  • breakStrategy是换行策略,主要有BREAK_STRATEGY_SIMPLE/BREAK_STRATEGY_HIGH_QUALITY/BREAK_STRATEGY_BALANCED
  • maxLine是最大行数。

找到了TextView计算高度的方法后,我们自定义了一个文本显示控件,

class StaticLayoutView (context: Context, attrs: AttributeSet?, defStyleAttr: Int) :View(context, attrs, defStyleAttr) {private var mStaticLayout: StaticLayout? = nullconstructor(context: Context) : this(context, null)constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)fun setLayout(layout: StaticLayout) {mStaticLayout = layout}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {var height = mStaticLayout?.height ?: 0setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height)}override fun onDraw(canvas: Canvas?) {super.onDraw(canvas)mStaticLayout?.draw(canvas)}}

相关内容

热门资讯

王毅:日本现职领导人讲了不该讲... 据外交部网站,11月19日至22日,中共中央政治局委员、外交部长王毅应邀赴吉尔吉斯斯坦、乌兹别克斯坦...
陕西兴平失联的12岁双胞胎姐妹... 据大风新闻,11月21日晚7时17分,陕西兴平一对12岁的双胞胎姐妹从家里外出。走的时候还穿着蓝色校...
原创 中... 中国再下一令,日本却辗转从韩国口中才得知这个噩耗,高市有点坐不住了,关键时刻放出猛料,要把美国拉下水...
公园掰手腕致骨折起诉索赔被驳回 公园内一场普通的掰手腕,竟导致手臂骨折、花费数万元医疗费。近日,江苏省苏州工业园区人民法院审理了一起...
护航浙商出海发展 浙江省涉外法... 中新网杭州11月23日电 (钱晨菲 吴怡欣)11月23日,浙江省涉外法律服务合作对接会在杭州举行,浙...
吕文君社媒庆祝夺冠:不只是海港... 2025赛季中超联赛于昨日正式落幕,上海海港队凭借出色的表现,成功捧起了冠军奖杯,成为了中超历史上又...
日本政府顾问:无需等到160关... 日本政府顾问表示,高市早苗政府对日元干预将采取更积极姿态,以抑制日元疲软带来的通胀压力,干预门槛可能...
被摄影师起诉侵权 视觉中国公开... 来源:每日经济新闻 持续两年多的摄影师起诉视觉中国(000681.SZ)侵权一案近日迎来进展。 法...
《哪吒2》被质疑过多使用动捕技... 搜狐娱乐讯 22日,奥斯卡公开的最佳动画长片奖“符合参评资格”大名单中没有《哪吒之魔童闹海》,引发热...
为了少付合同款,湖南一公司诉讼... 华声在线11月23日讯(文/视频 全媒体记者 杨昱 通讯员 胡云淞)为了少支付40万元合同款及利息,...