【Android】TextView自動換行文字排版良莠不齊的緣由

參考網上文章:
html

http://www.2cto.com/kf/201503/383397.html java

http://www.apkbus.com/android-176726-1-1.html linux

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等這些屬性配置是無論用的,其實用起來仍是不方便 android


   

public class DensityUtil {

	/**
	 * dip轉換成px
	 */
	public static int dip2px(Context context, float dpValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dpValue * scale + 0.5f);
	}

	/**
	 * px轉換成dip
	 */
	public static int px2dip(Context context, float pxValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (pxValue / scale + 0.5f);
	}


}
相關文章
相關標籤/搜索