【Android】TextView自动换行文字排版参差不齐的原因
参考网上文章:
http://www.2cto.com/kf/201503/383397.html
http://www.apkbus.com/android-176726-1-1.html
public class CYTextView extends TextView { public static int m_iTextHeight; // 文本的高度 public static int m_iTextWidth;// 文本的宽度 private Paint mPaint = null; private String string = ""; private float LineSpace = 0;// 行间距 private Context context; public CYTextView(Context context, AttributeSet set) { super(context, set); this.context = context; TypedArray typedArray = context.obtainStyledAttributes(set, R.styleable.CYTextView); float textsize = typedArray.getDimension(R.styleable.CYTextView_mytextSize, 20); int textcolor = typedArray.getColor(R.styleable.CYTextView_mytextColor, -1442840576); float linespace = typedArray.getDimension(R.styleable.CYTextView_lineSpacingExtra, -12); int typeface = typedArray.getColor(R.styleable.CYTextView_typeface, 0); linespace = DensityUtil.dip2px(context, -5); typedArray.recycle(); // 设置 CY TextView的宽度和行间距www.linuxidc.com LineSpace = linespace; // 构建paint对象 mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(textcolor); mPaint.setTextSize(textsize); switch (typeface) { case 0: mPaint.setTypeface(Typeface.DEFAULT); break; case 1: mPaint.setTypeface(Typeface.SANS_SERIF); break; case 2: mPaint.setTypeface(Typeface.SERIF); break; case 3: mPaint.setTypeface(Typeface.MONOSPACE); break; default: mPaint.setTypeface(Typeface.DEFAULT); break; } } @Override public void setMaxLines(int maxlines) { super.setMaxLines(maxlines); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (m_iTextWidth <= 0) { return; } char ch; int w = 0; int istart = 0; int m_iFontHeight; int m_iRealLine = 0; int x = DensityUtil.dip2px(context, 20); //60; //距左的距离 int y = 10; Vector m_String = new Vector(); FontMetrics fm = mPaint.getFontMetrics(); m_iFontHeight = (int) Math.ceil(fm.descent - fm.top) + (int) LineSpace;// 计算字体高度(字体高度+行间距) y = (int) Math.ceil(fm.descent - fm.top); for (int i = 0; i < string.length(); i++) { ch = string.charAt(i); float[] widths = new float[1]; String srt = String.valueOf(ch); mPaint.getTextWidths(srt, widths); if (ch == ‘\n‘) { m_iRealLine++; m_String.addElement(string.substring(istart, i)); istart = i + 1; w = 0; } else { w += (int) (Math.ceil(widths[0])); if (w > m_iTextWidth) { m_iRealLine++; m_String.addElement(string.substring(istart, i)); istart = i; i--; w = 0; } else { if (i == (string.length() - 1)) { m_iRealLine++; m_String.addElement(string.substring(istart, string.length())); } } } } /**这里是需求要求2行*/ if (m_iRealLine > 2){ m_iRealLine = 2; } m_iTextHeight = m_iRealLine * m_iFontHeight + 2; // canvas.setViewport(m_iTextWidth, m_iTextWidth); for (int i = 0, j = 0; i < m_iRealLine; i++, j++) { canvas.drawText((String) (m_String.elementAt(i)), x, y + m_iFontHeight * j, mPaint); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = measureWidth(widthMeasureSpec); m_iTextWidth = measuredWidth; /**这里也是需求要求*/ m_iTextWidth = m_iTextWidth - DensityUtil.dip2px(context, 26); int measuredHeight = measureHeight(heightMeasureSpec); this.setMeasuredDimension(measuredWidth, measuredHeight); // super.onMeasure(widthMeasureSpec, heightMeasureSpec); } private int measureHeight(int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); // Default size if no limits are specified. initHeight(); int result = m_iTextHeight; if (specMode == MeasureSpec.AT_MOST) { // Calculate the ideal size of your // control within this maximum size. // If your control fills the available // space return the outer bound. result = specSize; } else if (specMode == MeasureSpec.EXACTLY) { // If your control can fit within these bounds return that value. result = specSize; } return result; } private void initHeight() { // 设置 CY TextView的初始高度为0 m_iTextHeight = 0; // 大概计算 CY TextView所需高度 FontMetrics fm = mPaint.getFontMetrics(); int m_iFontHeight = (int) Math.ceil(fm.descent - fm.top) + (int) LineSpace; int line = 0; int istart = 0; int w = 0; for (int i = 0; i < string.length(); i++) { char ch = string.charAt(i); float[] widths = new float[1]; String srt = String.valueOf(ch); mPaint.getTextWidths(srt, widths); if (ch == ‘\n‘) { line++; istart = i + 1; w = 0; } else { w += (int) (Math.ceil(widths[0])); if (w > m_iTextWidth) { line++; istart = i; i--; w = 0; } else { if (i == (string.length() - 1)) { line++; } } } } /**这里是需求,要求两行*/ if (line > 2){ line = 2; } m_iTextHeight = (line) * m_iFontHeight + 2; } private int measureWidth(int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); // Default size if no limits are specified. int result = 500; if (specMode == MeasureSpec.AT_MOST) { // Calculate the ideal size of your control // within this maximum size. // If your control fills the available space // return the outer bound. result = specSize; } else if (specMode == MeasureSpec.EXACTLY) { // If your control can fit within these bounds return that value. result = specSize; } return result; } public void SetText(String text) {// 注:此函数目前只有在UI线程中调用才可以把文本画出来,在其它线程中<p> // //无法画文本,找了好久找不到原因,求高手解答) string = text; requestLayout(); invalidate(); } }
<com.example.picpopupwindow.CYTextView xmlns:cy="http://schemas.android.com/apk/res-auto" android:id="@+id/tv_product_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:maxLines="2" android:paddingLeft="26dp" android:paddingRight="10dp" android:layout_marginBottom="5dp" android:text="" cy:mytextSize="16sp" />
<declare-styleable name="CYTextView"> <attr name="mytextSize" format="dimension"/> <attr name="mytextColor" format="reference|color"/> <attr name="lineSpacingExtra" format="dimension"/> <attr name="typeface" format="dimension" /> </declare-styleable>
这里是通过文本的宽高调用onDraw方法来绘制的。但是像android:paddingLeft, android:maxLines等这些属性配置是不管用的,其实用起来还是不方便
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。