系统自带的控件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

[置顶] android 自定义TextView的更多相关文章

  1. [置顶] android 自定义ListView实现动画特效

    通过自定义ListView实现动画特效,被点击元素A向前移,A之前元素往后移动. 重点在于动画的实现: 具体代码如下: package com.open.widget; import java.uti ...

  2. [置顶] Android EditText/TextView使用SpannableString显示复合文本

    在Android中EditText用于编辑文本,TextView用于显示文本,但是有时候我们需要对其中的文本进行样式等方面的设置.Android为我们提供了SpannableString类来对指定文本 ...

  3. [置顶] android 自定义圆角ImageView以及锯齿的处理

    看到很多人开发过程中要使用圆角图片时,解决方法有: 1.重新绘制一张图片 2.通过布局来配置 3.通过重写View来实现 其中1,2在这里就不讲了,重点讲讲方法三的实现. 实现一:通过截取画布一个圆形 ...

  4. [置顶] Android RadioButton与TextView浪漫约会?

    情景一 今天主要实现一个国家与地区切换,就是当我们选中RadioButton时然后将值设置到TextView中,听着这需求应该不难对吧?那么我们就开始约会吧? 看下原型图 准备条件: 首先需要一个ra ...

  5. [置顶] Android开发笔记(成长轨迹)

    分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ...

  6. [置顶] Android布局管理器 - 详细解析布局实现

    布局管理器都是以ViewGroup为基类派生出来的; 使用布局管理器可以适配不同手机屏幕的分辨率,尺寸大小; 布局管理器之间的继承关系 : 在上面的UML图中可以看出, 绝对布局 帧布局 网格布局 相 ...

  7. Android 自定义TextView 实现文本间距

    Android系统中TextView默认显示中文时会比较紧凑,不是很美观.为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra或android:lineSpacin ...

  8. [置顶] android开发之来电自动拒接并自动回复短信_上课模式app

    上课的时候老师说总是错过电话,对方打来没人接还一遍遍的打,觉得可以有个app在上课期间自动拒接电话,并自动回复短信过去. 当然了,需要权限的. 尝试做了个雏形出来. 界面如下: 主要代码如下: pac ...

  9. [置顶] Android事件—单选按键和下拉按键

    在平常的开发中单选按键和下拉按键是非常常用的2个点击事件.首先介绍下单选按键 1:单选按键,单选的主键是radiogroup 这个主键也是很重要的 首先介绍下主键的布局 <?xml versio ...

随机推荐

  1. LightOJ 1033 Generating Palindromes(dp)

    LightOJ 1033  Generating Palindromes(dp) 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid= ...

  2. Linux解压缩总结

    看文件名的后缀名,不同的后缀的文件解压和压缩的命令都不一样总结如下: *.tar 用 tar –xvf 解压 *.gz 用 gzip -d或者gunzip 解压 *.tar.gz和*.tgz 用 ta ...

  3. Active MQ C#实现

    原文链接: Active MQ C#实现 内容概要 主要以源码的形式介绍如何用C#实现同Active MQ 的通讯.本文假设你已经正确安装JDK1.6.x,了解Active MQ并有一定的编程基础. ...

  4. Django内置template标签

    html过滤{% autoescape on|off %} {{body}} {% endautoescape %} 注释{% comment %} {% endcomment %} csrf攻击 { ...

  5. 什么是AOI自动光学检测机测试技术

    前言 当印刷电路板的价格以每年六到八个百分点的速度持续滑落,产品的生产良率就成为维持产业竞争力的要素.要获得高的良品率需要有良好的制造控制能力,而要获得良好的制程控制,似乎就必须要在各个制程中执行良好 ...

  6. QT VS检测内存泄漏

    测试程序:http://download.csdn.net/detail/ajaxhe/4085447 vld-2.2.3: http://vld.codeplex.com/releases/view ...

  7. Uva 12569 Planning mobile robot on Tree (EASY Version)

    基本思路就是Bfs: 本题的一个关键就是如何判段状态重复. 1.如果将状态用一个int型数组表示,即假设为int state[17],state[0]代表机器人的位置,从1到M从小到大表示障碍物的位置 ...

  8. fedora21 codeblocks在编辑装态下无法输入

    来自:http://forum.ubuntu.com.cn/viewtopic.php?f=88&t=284409   用codeblocks,突然发现怎么敲键盘都不能输入 搜索后得知: Co ...

  9. AFNetworking 进行网络监测

    AFNetworking 进行网络监测 引入头文件,创建检测判断BOOL值 // 网络请求的头文件 #import <AFNetworking.h> @interface ViewCont ...

  10. ASP.NET身份验证的几种方式

    1.windows身份验证 2.  Forms验证 3.Passport验证 4.none http://www.jb51.net/article/30510.htm