[置顶] android 自定义TextView
系统自带的控件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的更多相关文章
- [置顶] android 自定义ListView实现动画特效
通过自定义ListView实现动画特效,被点击元素A向前移,A之前元素往后移动. 重点在于动画的实现: 具体代码如下: package com.open.widget; import java.uti ...
- [置顶] Android EditText/TextView使用SpannableString显示复合文本
在Android中EditText用于编辑文本,TextView用于显示文本,但是有时候我们需要对其中的文本进行样式等方面的设置.Android为我们提供了SpannableString类来对指定文本 ...
- [置顶] android 自定义圆角ImageView以及锯齿的处理
看到很多人开发过程中要使用圆角图片时,解决方法有: 1.重新绘制一张图片 2.通过布局来配置 3.通过重写View来实现 其中1,2在这里就不讲了,重点讲讲方法三的实现. 实现一:通过截取画布一个圆形 ...
- [置顶]
Android RadioButton与TextView浪漫约会?
情景一 今天主要实现一个国家与地区切换,就是当我们选中RadioButton时然后将值设置到TextView中,听着这需求应该不难对吧?那么我们就开始约会吧? 看下原型图 准备条件: 首先需要一个ra ...
- [置顶] Android开发笔记(成长轨迹)
分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ...
- [置顶] Android布局管理器 - 详细解析布局实现
布局管理器都是以ViewGroup为基类派生出来的; 使用布局管理器可以适配不同手机屏幕的分辨率,尺寸大小; 布局管理器之间的继承关系 : 在上面的UML图中可以看出, 绝对布局 帧布局 网格布局 相 ...
- Android 自定义TextView 实现文本间距
Android系统中TextView默认显示中文时会比较紧凑,不是很美观.为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra或android:lineSpacin ...
- [置顶] android开发之来电自动拒接并自动回复短信_上课模式app
上课的时候老师说总是错过电话,对方打来没人接还一遍遍的打,觉得可以有个app在上课期间自动拒接电话,并自动回复短信过去. 当然了,需要权限的. 尝试做了个雏形出来. 界面如下: 主要代码如下: pac ...
- [置顶] Android事件—单选按键和下拉按键
在平常的开发中单选按键和下拉按键是非常常用的2个点击事件.首先介绍下单选按键 1:单选按键,单选的主键是radiogroup 这个主键也是很重要的 首先介绍下主键的布局 <?xml versio ...
随机推荐
- Definitions
Definitions and ODR Definitions are declarations that fully define the entity introduced by the decl ...
- 运行PHP
/usr/local/php/bin/php /home/www/index.php
- foreach遍历对象的属性
<?php class MyClass { public $var1 = 'value 1' ; public $var2 = 'value 2' ; public $var3 = 'value ...
- linq 总结
linq 常用方法: top var query=(from u in User ...).Take(10) dblinq的坑: 时间必须当参数传入,否则会报错 多个left join时,如果jo ...
- Qt浅译:JSON Support in Qt(JSON只有六种数据类型)
JSON Support in Qt Qt5之后开始提供对处理JSON数据的支持,JSON是一种Interter数据交换的数据格式. JSON 用于存储结构化的数据,JSON有6种基本数据类型 ...
- DELPHI编写服务程序总结
DELPHI编写服务程序总结 一.服务程序和桌面程序的区别 Windows 2000/XP/2003等支持一种叫做“系统服务程序”的进程,系统服务和桌面程序的区别是:系统服务不用登陆系统即可运行:系统 ...
- Poj 2499 Binary Tree(贪心)
题目链接:http://poj.org/problem?id=2499 思路分析:结点向左边移动时结点(a, b)变为( a+b, b),向右边移动时( a, b )变为( a, a + b); 为求 ...
- victim是什么意思_victim在线翻译_英语_读音_用法_例句_海词词典
victim是什么意思_victim在线翻译_英语_读音_用法_例句_海词词典 victim
- Sqoop处理Clob与Blob字段
[Author]: kwu Sqoop处理Clob与Blob字段,在Oracle中Clob为大文本.Blob存储二进制文件. 遇到这类字段导入hive或者hdfs须要特殊处理. 1.oracle中的測 ...
- 常用的shell命令整理
工作快一年了,shell命令也玩了一年了.还是有点积累的,下面是本人常用的. 1.pwd | xargs -i basename {} 获取当前所在目录的名称 2.ps -ef|grep -w ...