【问题标题】:Prevent a multiline TextView from unnecessarily expanding to it's maximum width防止多行 TextView 不必要地扩展到其最大宽度
【发布时间】:2022-05-18 09:17:57
【问题描述】:

扩展为多行的 TextView 似乎会自动扩展以适应其最大可能宽度。我怎样才能防止这种情况发生?

这是一个示例布局 (test.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<TextView
android:background="@color/green"
android:layout_alignParentRight="true"
android:id="@+id/foo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:text="This is the message a much shorter message"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/black" />
</RelativeLayout>

如果我在左侧添加边距,它会正确缩小 TextView 的宽度(无需重新格式化内容),但边距的大小必须根据 TextView 的内容来计算。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<TextView
android:layout_marginLeft="32dp"
android:background="@color/green"
android:layout_alignParentRight="true"
android:id="@+id/foo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:text="This is the message a much shorter message"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/black" />
</RelativeLayout>

【问题讨论】:

    标签: android


    【解决方案1】:

    您可以在计算宽度的地方使用带有覆盖方法 onMeasure() 的自定义 TextView:

    public class WrapWidthTextView extends TextView {
    
        // ...
        
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            
            Layout layout = getLayout();
            if (layout != null) {
                int width = (int)FloatMath.ceil(getMaxLineWidth(layout))
                        + getCompoundPaddingLeft() + getCompoundPaddingRight();
                int height = getMeasuredHeight();            
                setMeasuredDimension(width, height);
            }
        }
        
        private float getMaxLineWidth(Layout layout) {
            float max_width = 0.0f;
            int lines = layout.getLineCount();
            for (int i = 0; i < lines; i++) {
                if (layout.getLineWidth(i) > max_width) {
                    max_width = layout.getLineWidth(i);
                }
            }
            return max_width;
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果您想使用@Vitaliy Polchuk 的建议(最佳答案),请改写或在Why is wrap content in multiple line TextView filling parent? 上查看他的答案:

      public class WrapWidthTextView extends AppCompatTextView {
          public WrapWidthTextView(Context context) {
              super(context);
          }
      
          public WrapWidthTextView(Context context, @Nullable AttributeSet attrs) {
              super(context, attrs);
          }
      
          public WrapWidthTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
              super(context, attrs, defStyleAttr);
          }
      
          @Override
          protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
              super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      
              Layout layout = getLayout();
              if (layout != null) {
                  int width = (int) Math.ceil(getMaxLineWidth(layout))
                          + getCompoundPaddingLeft() + getCompoundPaddingRight();
                  int height = getMeasuredHeight();
                  setMeasuredDimension(width, height);
              }
          }
      
          private float getMaxLineWidth(Layout layout) {
              float max_width = 0.0f;
              int lines = layout.getLineCount();
              for (int i = 0; i < lines; i++) {
                  if (layout.getLineWidth(i) > max_width) {
                      max_width = layout.getLineWidth(i);
                  }
              }
              return max_width;
          }
      }
      
      当您将此类插入 XML 时,

      重建项目。否则找不到这个类。

      【讨论】:

        【解决方案3】:

        使用android:padding="32dp" 如果您想从左侧使用填充,使用填充可以帮助您使用android:paddingLeft="32dp"

        【讨论】:

        • 问题不在于填充。我希望 TextView 实际包装内容,而不是当它是多行时,它会扩展到父视图的宽度。
        【解决方案4】:

        我已经尝试过 Vitaliy Polchuk 的解决方案,效果很好。我还想补充一点小修正:

        ...
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            Layout layout = getLayout();
            if (layout != null) {
                int width = (int) FloatMath.ceil(getMaxLineWidth(layout))
                        + getCompoundPaddingLeft() + getCompoundPaddingRight();
                widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
            }
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            // get already measured dimensions
            int width = getMeasuredWidth();
            int height = getMeasuredHeight();
            setMeasuredDimension(width, height);
        }
        ...
        

        【讨论】:

          猜你喜欢
          • 2013-08-10
          • 2015-10-04
          • 1970-01-01
          • 1970-01-01
          • 2016-06-28
          • 1970-01-01
          • 1970-01-01
          • 2013-11-04
          • 1970-01-01
          相关资源
          最近更新 更多