现在的位置: 首页 > 综合 > 正文

android 自定义TextView

2018年04月05日 ⁄ 综合 ⁄ 共 4436字 ⁄ 字号 评论关闭

系统自带的控件TextView有时候没满一行就换行了,为了解决这个问题,自定义了一个TextView,只有一行显示不完全的情况下才会去换行显示,代码如下:

package com.open.textview;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;

/**
 * 不换行的TextView
 * @author Administrator
 *
 */
public class CusTextView extends View {
	
    protected float textSize=35;  
    protected float paddingLeft=0;
    protected float paddingRight=0;
    protected float paddingTop=0;
    protected float paddingBottom=0;
    
    protected float lineSpace=5; 
    protected int lineWidth=320;
    protected float lineHeight=20;
    protected int lineCount;
    protected int maxLines=-1;//最大的行数
    
    protected String mText;
    protected ArrayList<LineParams> lineList=new ArrayList<LineParams>(0);//行的字符串索引
	
    
    protected Paint mPaint = new Paint();  
	{
		mPaint.setTextSize(textSize);  
        mPaint.setAntiAlias(true); 
	}
	
	public CusTextView(Context context) {
		super(context);
	}

	public CusTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public CusTextView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	
	public void setText(String text) {
		this.mText = text;
		lineList.clear();
		requestLayout();
		invalidate();
	}
	
	public void setText(String text,int maxLines)
	{
		this.maxLines=maxLines;
		this.setText(text);
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		
		if(TextUtils.isEmpty(mText))
		{
			setMeasuredDimension(0, 0);
			return;
		}
		
		lineWidth=(int)(MeasureSpec.getSize(widthMeasureSpec)-paddingLeft-paddingRight);//每行的宽度
		Rect bounds = new Rect();
        mPaint.getTextBounds(mText, 0, mText.length(), bounds);
        lineHeight=bounds.bottom-bounds.top;

        maxLines=-1;
        lineList.clear();
        calculate();
        lineCount=lineList.size();//总行数
		maxLines=(maxLines>0)?Math.min(lineCount, maxLines):lineCount;
		
		int measuredHeight=0;//总的高度
		if(maxLines>0)
		{
			measuredHeight+=(paddingTop+paddingBottom);//顶部与底部
			measuredHeight+=(maxLines-1)*lineSpace;//空隙的间隔
			measuredHeight+=(maxLines*(lineHeight));//行高之和
		}

		int result=measuredHeight;
		int specMode = MeasureSpec.getMode(heightMeasureSpec);
        int specSize =  MeasureSpec.getSize(heightMeasureSpec);
        switch (specMode) {
        case MeasureSpec.UNSPECIFIED:
            result = measuredHeight;
            break;
        case MeasureSpec.AT_MOST:
            result = Math.min(measuredHeight, specSize);
            break;
        case MeasureSpec.EXACTLY:
            result = specSize;
            break;
        }
		setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), result);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		
		if(TextUtils.isEmpty(mText))
		{
			return;
		}
		
		for(int i=0;i<lineList.size();i++)
		{
			if(i==0)
			{
				canvas.drawText(mText, lineList.get(i).startIndex, lineList.get(i).endIndex, paddingLeft, paddingTop+lineHeight, mPaint);
			}
			else
			{
				canvas.drawText(mText, lineList.get(i).startIndex, lineList.get(i).endIndex, paddingLeft, paddingTop+lineHeight+(lineHeight+lineSpace)*i, mPaint);
			}
		}
		
	}
	
	private void calculate()
	{
		int startIndex=0;
		while(true)
		{
			int[] itemLine=getIndexArray(startIndex);
			lineList.add(new LineParams(itemLine[0], itemLine[1]));
			if(itemLine[1]>=mText.length())
			{
				break;
			}
			
			startIndex=itemLine[1];
		}
	}
	
	private int[] getIndexArray(int startIndex)
	{
		int[] ret=new int[2];
		
		int  canholdcharSize=0;
		int singleCharWidth=(int) mPaint.measureText(mText, startIndex, startIndex+1);//单个字符宽度
		singleCharWidth=Math.max(singleCharWidth, 1);
		canholdcharSize=lineWidth/singleCharWidth;//每行可以容纳的字数,非精确值
		
		if(isOutOfIndex(startIndex,canholdcharSize))//检查是否越界了
		{
			canholdcharSize=mText.length()-startIndex;
		}
		
		if(isFitness(startIndex,canholdcharSize,lineWidth))//如果linecharSize个字符还小于单行的长度,需要再次自加长度来判断
		{
			while(true)
			{
				canholdcharSize++;
				if(isOutOfIndex(startIndex,canholdcharSize))
				{
					canholdcharSize--;
					break;
				}
				
				if(isFitness(startIndex,canholdcharSize,lineWidth))
				{
					continue;
				}
				else
				{
					canholdcharSize--;
					break;
				}
			}
		}
		else //需要再次自减长度来判断
		{
			while(true)
			{
				canholdcharSize--;
				if(isFitness(startIndex,canholdcharSize,lineWidth))
				{
					break;
				}
				else
				{
					continue;
				}
			}
		}
		
		ret[0]=startIndex;
		ret[1]=(startIndex+canholdcharSize);
		return ret;
	}
	
	private boolean isOutOfIndex(int startIndex,int linecharSize)
	{
		return startIndex+linecharSize>mText.length();
	}
	
	private boolean isFitness(int startIndex,int canholdcharSize,int lineWidth)
	{
		return mPaint.measureText(mText, startIndex, startIndex+canholdcharSize)<=lineWidth;
	}
	
	public class LineParams
	{
		public int startIndex;
		public int endIndex;
		
		public LineParams(int startIndex, int endIndex) 
		{
			this.startIndex = startIndex;
			this.endIndex = endIndex;
		}
		
		public boolean isInnerRange(int testNum)
		{
			return (testNum>=startIndex&&testNum<=endIndex);
		}

		@Override
		public String toString() 
		{
			return "LineParams [startIndex=" + startIndex + ", endIndex="+ endIndex + "]";
		}
	}
}

Demo地址:http://download.csdn.net/detail/zz7zz7zz/6015937

邮箱:zz7zz7zz@163.com

微博http://weibo.com/u/3209971935

抱歉!评论已关闭.