去除Android TextView預設內邊距
阿新 • • 發佈:2019-02-04
由於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達到要求。
沒使用canvas.translate(0, fontMetricsInt.bottom - fontMetricsInt.descent);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 - minRect.bottom);
是因為文字實際顯示的時候,文字最底部並不一定是fontMetricsInt.descent,但minRect.bottom確一定能取到實際顯示的最底部的值。
具體原理還是要參考:http://blog.csdn.net/harvic880925/article/details/50423762
使用方法:
1.在xml中使用該自定義控制元件:
2.java程式碼中獲取該控制元件,並操作該控制元件:<com.test.myapplication.MyTextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:background="@android:color/holo_red_dark" android:padding="10dp" android:text="hello" android:textSize="30sp"/>
//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的方法呼叫。
上述缺點目前都是可接受的。
以後有機會優化上面的缺點。同時感謝上述引用網站的創作者。