7

私が作成しているカスタムビューがあります。これは、子のフォントサイズを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_PARENTWRAP_CONTENT幅に対しては正常に機能していますが、コンポーネントに重みを与えてその重みを自動設定しようとすると失敗します。

MeasureSpec.getSize(widthMeasureSpec)0を返しますgetMinimumSuggestedWidth()。lineWidth は常に返されるよりも小さいcalculateTextWidth()ため、whileループは永久に実行されるため、これにより素晴らしい Activity Not Responding エラーが発生します。私が使用した 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か? 単純な答えがあればいいような気がするのですが、それが何なのか途方に暮れています。

4

1 に答える 1

10

私はいくつかの重要なグーグルでそれを理解することになりました。このページで、 onMeasure が設定されている場合、実際には 2 回呼び出されることがわかりましたandroid:layout_weight後で、 Android がビューを描画する方法で言及されていることを知りましたmeasure()。これは何度でも呼び出すことができますが、すぐには頭に浮かびませんでした。ビューのすべての兄弟の重みがわからないため、最初のパスは明らかに各子のサイズの値を与えることができません。一度通過し、MeasureSpec.UNSPECIFIED で幅 0 を指定して、子に特定の制約があるかどうかを確認してから、もう一度通過します。MeasureSpec.EXACTLY で実際の重みを割り当てます。私のアクティビティは最初のパスで台無しになっていたため、レイアウトのステップに到達しませんでした。onMeasure() を次のコードに修正すると、問題が修正されました。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  if (widthMode != MeasureSpec.UNSPECIFIED) {
    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);
}
于 2012-01-26T18:39:56.990 に答える