參考網上文章:
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); } }