如何处理 onMeasue 中自定义视图的权重?
我正在创建一个自定义视图,它将缩放其子 TextViews
的字体大小以适应设定的宽度,因此每个视图都在自己的行上。显然,需要宽度来解决这个问题。
我已经重写了 onMeasure()
,如下所示:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int lineWidth = widthSize - getPaddingLeft() - getPaddingRight();
// Change the text size until the largest line of text fits.
while (lineWidth < calculateTextWidth()) {
for (TextView textView : this.childViews) {
float newSize = textView.getTextSize() - 1;
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSize);
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
calculateTextWidth()
计算最大文本行的宽度,一切都可以使用。这段代码对于 FILL_PARENT
和 WRAP_CONTENT
宽度工作得很好,但是当我尝试给组件一个权重并让它以这种方式自动设置权重时,就搞砸了。
MeasureSpec.getSize(widthMeasureSpec)
返回 0
,getMinimumSuggestedWidth()
也会返回 0
。这会产生一个奇妙的 Activity Not Responding 错误,因为 lineWidth 始终小于返回的 calculateTextWidth()
,因此 while
循环将永远运行。我使用的 XML 代码本质上是这样的:
<com.my.widgets.ScalingTextViewGroup
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center_horizontal"
>
<TextView
android:id="@+id/text_1"
android:text="Text 1"
android:textSize="20sp" />
<TextView
android:id="@+id/text_2"
android:text="Text 2"
android:textSize="18sp" />
<TextView
android:id="@+id/text_3"
android:text="Text 3"
android:textSize="18sp" />
<TextView
android:id="@+id/text_4"
android:text="Text 4"
android:textSize="18sp" />
</com.my.widgets.ScalingTextViewGroup>
我理解为什么它返回 0 - 显然,它被设置为 0 - 但我如何让它使用 layout_weight
?我觉得这应该有一个简单的答案,但我不知道它是什么。
I have a custom view which I'm creating that will scale the font size of its child TextViews
to fit all in a set width, so each is on its own line. Obviously it's going to need the width to figure that out.
I had overridden onMeasure()
like so:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int lineWidth = widthSize - getPaddingLeft() - getPaddingRight();
// Change the text size until the largest line of text fits.
while (lineWidth < calculateTextWidth()) {
for (TextView textView : this.childViews) {
float newSize = textView.getTextSize() - 1;
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSize);
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
calculateTextWidth()
calculates the width of the largest line of text and everything works with that. This code is working fine for FILL_PARENT
and WRAP_CONTENT
widths, but screws up when I try to give the component a weight and let it auto-set its weight that way.
MeasureSpec.getSize(widthMeasureSpec)
returns 0
, as getMinimumSuggestedWidth()
does, too. This gives a wonderful Activity Not Responding error, since lineWidth will always be less than calculateTextWidth()
would ever return, so the while
loop runs forever. The XML code I used was this, essentially:
<com.my.widgets.ScalingTextViewGroup
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center_horizontal"
>
<TextView
android:id="@+id/text_1"
android:text="Text 1"
android:textSize="20sp" />
<TextView
android:id="@+id/text_2"
android:text="Text 2"
android:textSize="18sp" />
<TextView
android:id="@+id/text_3"
android:text="Text 3"
android:textSize="18sp" />
<TextView
android:id="@+id/text_4"
android:text="Text 4"
android:textSize="18sp" />
</com.my.widgets.ScalingTextViewGroup>
I understand why it's returning 0 - obviously, it's being set to 0 - but how do I get it to use the layout_weight
? I feel like it's something that should have a simple answer, but I'm at a loss as to what it is.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我最终通过一些重要的谷歌搜索找到了答案。在 这个页面我发现当
android:layout_weight
设置时onMeasure实际上被调用了两次。后来我发现 How Android Draws Views 中提到了measure()
可以被调用任意多次,但它并没有立即出现在我的脑海中。第一遍显然无法给出每个子视图的大小值,因为它不知道该视图的所有兄弟视图的权重是多少。它会遍历一次并使用 MeasureSpec.UNSPECIFIED 给出 0 的宽度,以查看子级是否有任何特定约束,然后再次遍历它以使用 MeasureSpec.EXACTLY 分配实际权重。我的 Activity 在第一次通过时就搞砸了,所以它从未到达布局步骤。将我的 onMeasure() 修改为以下代码解决了问题。I ended up figuring it out through some significant Googling. On this page I found out that onMeasure is actually called twice when
android:layout_weight
is set. I found out later that it's mentioned in How Android Draws Views thatmeasure()
can be called any number of times, it just didn't immediately sit in my brain. The first pass obviously can't give a value for the size of each child, since it doesn't know what the weights of all of the View's siblings are. It goes through it once and gives a width of 0 with a MeasureSpec.UNSPECIFIED to see if the child has any specific constraints, then goes through again to assign the actual weights with a MeasureSpec.EXACTLY. My Activity was getting screwed up at the first pass, so it never got to the layout step. Amending my onMeasure() to the following code fixed the problem.