去除Android TextView默认内边距

由于textview在绘制文字时,是按照四格线为基准绘制的,所以会在实际显示文字的时候,在textview内部显示出默认的内边距,该内边距并不是padding造成的。具体情况请参考:http://blog.csdn.net/harvic880925/article/details/50423762

网上也有不少解决方案例如:

android:includeFontPadding="false";

android:lineSpacingMultiplier="0.9"

等等,都没达到我想要的预期要求,所以在参考了 http://blog.csdn.net/Ab0510/article/details/52219464之后,

写了个自定义TextView达到要求。

 

 

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MyTextView extends LinearLayout {
    private MyTextViewInner textView;

    public MyTextView(Context context) {
        super(context);
        init(null, 0);
    }

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public MyTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs, defStyle);
    }

    private void init(AttributeSet attrs, int defStyleAttr) {
        if (attrs != null && defStyleAttr > 0) {
            textView = new MyTextViewInner(getContext(), attrs, defStyleAttr);
        } else if (attrs != null) {
            textView = new MyTextViewInner(getContext(), attrs);
        } else {
            textView = new MyTextViewInner(getContext());
        }
        this.setPadding(0, 0, 0, 0);
        addView(textView);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = getMeasuredWidth();
        width = width + textView.getPaddingLeft() + textView.getPaddingRight();
        setMeasuredDimension(width, getMeasuredHeight());
    }

    public TextView getTextView() {
        return textView;
    }

    public class MyTextViewInner extends android.support.v7.widget.AppCompatTextView {
        //设置是否remove间距,true为remove
        private boolean noDefaultPadding = true;
        private Paint.FontMetricsInt fontMetricsInt;
        private Rect minRect;

        public MyTextViewInner(Context context) {
            super(context);
        }

        public MyTextViewInner(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public MyTextViewInner(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            if (fontMetricsInt == null) {
                //fontMetricsInt包含的是text文字四条线的 距离,
                //此四条线距离也是以text文字baseline为基准的
                fontMetricsInt = new Paint.FontMetricsInt();
            }
            getPaint().getFontMetricsInt(fontMetricsInt);
            if (minRect == null) {
                //minRect用来获取文字实际显示的时候的左上角和右下角  坐标
                //该坐标是以text文字baseline为基准的
                minRect = new Rect();
            }
            getPaint().getTextBounds(getText().toString(), 0, getText().length(), minRect);
            ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) this.getLayoutParams();
            lp.topMargin = -(fontMetricsInt.bottom - minRect.bottom) + (fontMetricsInt.top - minRect.top);
            lp.rightMargin = -(minRect.left + (getMeasuredWidth() - minRect.right));
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            if (noDefaultPadding) {
                if (fontMetricsInt == null) {
                    //fontMetricsInt包含的是text文字四条线的 距离,
                    //此四条线距离也是以text文字baseline为基准的
                    fontMetricsInt = new Paint.FontMetricsInt();
                }
                getPaint().getFontMetricsInt(fontMetricsInt);
                if (minRect == null) {
                    //minRect用来获取文字实际显示的时候的左上角和右下角  坐标
                    //该坐标是以text文字baseline为基准的
                    minRect = new Rect();
                }
                getPaint().getTextBounds(getText().toString(), 0, getText().length(), minRect);
                canvas.translate(-minRect.left, fontMetricsInt.bottom - minRect.bottom);
            }
            super.onDraw(canvas);
        }

        @Override
        public void setText(CharSequence text, BufferType type) {
            super.setText(text, type);
            this.requestLayout();
        }
    }
}

没使用canvas.translate(0, fontMetricsInt.bottom - fontMetricsInt.descent);
而使用canvas.translate(0, fontMetricsInt.bottom - minRect.bottom);
是因为文字实际显示的时候,文字最底部并不一定是fontMetricsInt.descent,但minRect.bottom确一定能取到实际显示的最底部的值。
具体原理还是要参考:http://blog.csdn.net/harvic880925/article/details/50423762
使用方法:
1.在xml中使用该自定义控件:

<com.test.myapplication.MyTextView
            android:id="@+id/tv1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/holo_red_dark"
            android:text="hello"
            android:textSize="30sp"/>

2.java代码中获取该控件,并操作该控件:

//myTextView实际上是自定义的LinearLayout
MyTextView myTextView = (MyTextView) findViewById(R.id.tv1);
//textView才是实际上的TextView
TextView textView = (TextView) myTextView.getTextView();
//对textView进行操作
textView.setText("perfect");

优点:1.去除了textView默认情况的下内边距;
  2.支持textview原生的属性设置。
缺点:1.由于在原生textview外层嵌套了一层linearlayout,理论上会有性能降低,但是实际运行时候感觉不到;
  2.也由于该层嵌套,所以在引用textview的时候需要多一步获取textview的方法调用。
上述缺点目前都是可接受的。
以后有机会优化上面的缺点。同时感谢上述引用网站的创作者。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值