【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等这些属性配置是不管用的,其实用起来还是不方便

时间: 2024-10-19 14:06:22

【Android】TextView自动换行文字排版参差不齐的原因的相关文章

Android TextView自动换行文字排版参差不齐的原因

今天项目没什么进展,公司后台出问题了.看了下刚刚学习Android时的笔记,发现TextView会自动换行,而且排版文字参差不齐.查了下资料,总结原因如下: 1.半角字符与全角字符混乱所致:这种情况一般就是汉字与数字.英文字母混用 解决方法一: 将textview中的字符全角化.即将所有的数字.字母及标点全部转为全角字符,使它们与汉字同占两个字节,这样就可以避免由于占位导致的排版混乱问题了. 半角转为全角的代码如下,只需调用即可. public static String ToDBC(Strin

Android TextView自动换行文字排字参差不齐的原因及处理

Android TextView自动换行文字排版参差不齐的原因及处理 转自: TextView会自动换行,而且排版文字参差不齐.查了下资料,总结原因如下: 1.半角字符与全角字符混乱所致:这种情况一般就是汉字与数字.英文字母混用 解决方法一: 将textview中的字符全角化.即将所有的数字.字母及标点全部转为全角字符,使它们与汉字同占两个字节,这样就可以避免由于占位导致的排版混乱问题了. 半角转为全角的代码如下,只需调用即可.public static String ToDBC(String

android textview 自动换行 整齐排版

一.问题在哪里? textview显示长文字时会进行自动折行,如果遇到一些特殊情况,自动折行会杯具成这个样子: 上述特殊情况包括: 1)全角/半角符号混排(一般是数字.字母.汉字混排) 2)全角/半角标点符号出现在行首时,该标点符号会连同其前一个字符跳到下一行 3)英文单词不能被折成两行 4)...... [转载请保留本文地址:http://www.cnblogs.com/goagent/p/5159125.html] 二.怎么搞? 通常有两类解决方案: 1)修改文本内容,将所有符号全角化.在标

Android TextView 实现文字大小不同和文字颜色不同

效果图如下: 关键代码如下: StringBuffer sb = new StringBuffer(); if(day > 0) { sb.append("<a href=\"1\">"); sb.append(""+day); sb.append("</a>"); sb.append(""+Global.getString(R.string.unit_Day2)); } sb

android textView 替文字添加下划线 删除线

android textView 为文字添加下划线 删除线android textview 添加下划线 中划线 删除线tv=(TextView)findViewById(R.id.tvId);tv.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG); //删除线//Paint.UNDERLINE_TEXT_FLAG 下划线 XAMARIN: TextView text = FindViewById<TextView>(Resource.Id.xxx

android:TextView实现文字走马灯效果(欺骗系统获取持久的焦点)

通常情况下我们想实现文字的走马灯效果需要在xml文件中这样设置 <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:ellipsize="marquee" android:focusable="true" android:

Android TextView修改文字样式

一. 引出CharSequence接口 TextView.setText(CharSequence); 二.实现CharSequence接口 SpannableString.SpannableStringBuilder实现此接口,但是二者的区别是? 三.例子 String text = "Love_World_"; SpannableString style = new SpannableString(text); style.setSpan(new ForegroundColorSp

Android TextView部分文字实现点击事件

This is the class for text whose content and markup can both be changed. (这是一个内容和标记都可以更改的文本类) 快速实现 直接看代码: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextV

Android TextView中文字通过SpannableString来设置超链接、颜色、字体等属

在Android中,TextView是我们最常用的用来显示文本的控件. 一般情况下,TextView中的文本都是一个样式.那么如何对于TextView中各个部分的文本来设置字体,大小,颜色,样式,以及超级链接等属性呢?下面我们通过SpannableString的具体实例操作来演示一下. res-layout-main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:and