【问题标题】:Remove space between stacked TextViews删除堆叠的 TextView 之间的空间
【发布时间】:2012-06-01 22:41:04
【问题描述】:

我有一个垂直的LinearLayout,里面有两个TextView。前者包含一个静态文本属性(它的文本永远不会改变),最后一个包含一个回归计时器。下图显示了这两个项目:

我想消除两个文本都有顶部和底部的空格。我尝试了几种方法...

android:includeFontPadding="false"
android:lineSpacingMultiplier="1"
android:lineSpacingExtra="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:layout_marginTop="0dp"
android:layout_marginBottom="0dp"

...但他们都没有删除文本上方的空格。如何使两个文本彼此靠近而没有多余的空间?

PS:我找到了this similar question,但是没有人回答。


完整的布局代码:

<LinearLayout 
    android:id="@+id/boxTime"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="20dp" >

    <TextView
        android:id="@+id/textRemainingTime2"
        android:layout_width="wrap_content"
        android:layout_heigh="wrap_content"
        android:layout_gravity="center"
        android:gravity="center_horizontal"
        android:textSize="70sp"
        android:includeFontPadding="false"
        android:lineSpacingMultiplier="1"
        android:lineSpacingExtra="0dp"
        android:paddingTop="0dp"
        android:paddingBottom="0dp"
        android:layout_marginTop="0dp"
        android:layout_marginBottom="0dp"
        android:text="@string/title" />

    <TextView
        android:id="@+id/textRemainingTime"
        android:layout_width="wrap_content"
        android:layout_heigh="wrap_content"
        android:layout_gravity="center"
        android:gravity="center_horizontal"
        android:includeFontPadding="false"
        android:lineSpacingMultiplier="1"
        android:lineSpacingExtra="0dp"
        android:paddingTop="0dp"
        android:paddingBottom="0dp"
        android:layout_marginTop="0dp"
        android:layout_marginBottom="0dp"
        android:textSize="107sp"
        android:text="@string/timer" />

</LinearLayout>

【问题讨论】:

    标签: android android-layout textview


    【解决方案1】:

    尝试使用负边距。可能需要花点时间才能弄好数字,但我以前做过,而且效果很好。

    android:layout_marginTop="-5dp"
    

    【讨论】:

    • 其实我用了很长时间,从来没有遇到过问题,但我一直怀疑这是否真的是一个好的解决方案,但我找不到更好的解决方案。
    • @PozzoApps 这是一种解决方法而不是修复方法,但它确实可以很好地完成工作,所以...
    【解决方案2】:

    默认情况下,TextView includes some padding to leave space for accent characters。您可以通过以下方式关闭它:

     android:includeFontPadding="false"
    

     textView.setIncludeFontPadding(false)
    

    【讨论】:

    • 它对我有用。但是文本的升序和降序仍有一些空间如何删除?
    【解决方案3】:

    使文本的基线等于 TextView 的底部。

    public class BaselineTextView extends TextView {
    
        public BaselineTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            int yOffset = getHeight() - getBaseline();
            canvas.translate(0, yOffset);
            super.onDraw(canvas);
        }
    
    }
    

    注意:为避免切断后代,请在 TextView 的父 ViewGroup(XML 中的 android:clipChildren="false")上调用 setClipChildren(false)

    【讨论】:

    • 这适用于任何字体、字体大小、屏幕密度等。为什么它不是公认的答案?
    • 所有这些都将填充移动到视图的顶部,因此它仍然存在并且必须在任何设计工作中加以考虑。
    • 将上面的代码复制到我的项目中。有斩断下行的作用。
    • @macu,您可能需要在 TextView 的父 ViewGroup 上调用 setClipChildren(false)。
    • 这是唯一有效的答案。非常感谢您的分享!
    【解决方案4】:

    如果您将 includeFontPadding 设置为 false,它会有所帮助。

    android:includeFontPadding="false"
    

    但如果你知道你没有任何后代,因为你设置了

    android:textAllCaps="true"
    

    或者你知道没有字符有下降,你可以制作一个自定义的 TextView 并将高度设置为基线。

    public class ExTextView extends TextView {
    
        public ExTextView(Context context) {
            this(context, null);
        }
    
        public ExTextView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public ExTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public ExTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            setHeight(getBaseline());  // <--- Shrink size to baseline
            super.onDraw(canvas);
        }
    }
    

    源代码包含在我的 UiComponents 测试应用程序中。 https://github.com/landenlabs/UiComponents

    【讨论】:

      【解决方案5】:

      负边距可以解决问题

      【讨论】:

        【解决方案6】:

        由于我的要求是覆盖从findViewById(getResources().getIdentifier("xxx", "id", "android")); 获取的现有textView,所以我不能简单地尝试onDraw() 的其他答案。

        但我只是想出了解决问题的正确步骤,这是 Layout Inspector 的最终结果:

        由于我想要的只是删除顶部空格,所以我不必选择其他字体来删除底部空格。

        这是修复它的关键代码:

        Typeface mfont = Typeface.createFromAsset(getResources().getAssets(), "fonts/myCustomFont.otf");
        myTextView.setTypeface(mfont);
        
        myTextView.setPadding(0, 0, 0, 0);
        
        myTextView.setIncludeFontPadding(false);
        

        第一个关键是设置自定义字体“fonts/myCustomFont.otf”,它在底部有空格,但在顶部没有空格,您可以通过打开 otf 文件并单击 android Studio 中的任何字体轻松找出:

        如您所见,底部的光标有额外的间距,但顶部没有,所以它解决了我的问题。

        第二个关键是你不能简单地跳过任何代码,否则它可能不起作用。这就是为什么您会发现有些人评论说答案有效,而另一些人评论说答案无效。

        让我们举例说明如果我删除其中一个会发生什么。

        没有setTypeface(mfont);

        没有setPadding(0, 0, 0, 0);

        没有setIncludeFontPadding(false);

        没有 3 个(即原版):

        【讨论】:

          【解决方案7】:

          负边距可以解决问题。您可以通过两种方法设置它 -

          1) 通过 xml - 将 android:Layout_marginTop="-10dp" 字段设置为负数

          2) 通过 java(以编程方式) - 将 LayoutParams 的 topMargin 字段设置为负数。

          【讨论】:

            【解决方案8】:

            你应该改变 TextView 的高度,也许改变 android:gravity="bottom"

            高度介于 textsize 和带有 Wrapcontent 的 textView 的大小之间。

            public class MyTextViewBounder extends TextView {
            public MyTextViewBounder(Context context) {
                super(context);
            }
            
            public MyTextViewBounder(Context context, AttributeSet attrs) {
                super(context, attrs);
            }
            
            public MyTextViewBounder(Context context, AttributeSet attrs, int defStyleAttr) {
                super(context, attrs, defStyleAttr);
            
            }
            
            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
            
                //test kích thước thực tế với kích thước của Textview bao quanh text của nó như thế nào
                int width, height;
                Paint iPaint;
                Rect  iRect = new Rect();
            
                iPaint = new Paint();
                iPaint.setTextSize(13);
                iPaint.setTextAlign(Paint.Align.CENTER);
            
                //call below code outsite
                //this.setText("Hung");
                //this.setTextSize(TypedValue.COMPLEX_UNIT_PX,13);
                //this..setIncludeFontPadding(false);   //height from 18px down to 15px
                iPaint.getTextBounds("Hung",0,4,iRect); //width = 34px, height = 12px
            
                width = this.getWidth(); //= 30px
                height = this.getHeight(); //= 18px
            
                width = this.getMeasuredWidth(); //=30px
                height = this.getMeasuredHeight(); //= 18px
            
                width = iRect.width();  //34px
                height = iRect.height(); //12 px
            
            }
            

            }

            【讨论】:

              【解决方案9】:

              只需在下面使用,不需要其他任何东西。

               android:includeFontPadding="false"
              

              如果你想改变行间距,那么使用:

              android:lineSpacingExtra 
              

              【讨论】: