android提供的TextView控件可以自动换行,对于纯英文来说很好用,如果既有中文字符又有英文字符和特殊字符,全角字符和半角字符混在一块,就会出现经常一行没显示完就跳转到下一行显示了,文字排版参差不齐,超级难看,通过自定义TextView来实现我们需要的显示方式。
自定义MyTextView类代码如下:
package com.example.user.helloworld.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.TextView;
import com.example.user.helloworld.R;
/**
* 解决textView 排版换行
* @author
*
*/
public class MyTextView extends TextView {
private String text;
private float textSize;
private float paddingLeft;
private float paddingRight;
private int textColor;
private Paint paint1 = new Paint();
private float textShowWidth;
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
text = this.getText().toString();
textSize = this.getTextSize();
textColor = getResources().getColor(R.color.accent);
paddingLeft = this.getPaddingLeft();
paddingRight = this.getPaddingRight();
paint1.setTextSize(textSize);
paint1.setColor(textColor);
paint1.setAntiAlias(true);
}
/**
* 设置画笔颜色
* @param color
*/
public void setPaintColor(int color){
paint1.setColor(color);
}
@Override
public void onDraw(Canvas canvas) {
textShowWidth = this.getMeasuredWidth() - paddingLeft - paddingRight;
int lineCount = 0;
text = this.getText().toString();
if (text == null)
return;
char[] textCharArray = text.toCharArray();
float drawedWidth = 0;
float charWidth;
for (int i = 0; i < textCharArray.length; i++) {
charWidth = paint1.measureText(textCharArray, i, 1);
if (textCharArray[i] == '\n') {
lineCount++;
drawedWidth = 0;
continue;
}
if (textShowWidth - drawedWidth < charWidth) {
lineCount++;
drawedWidth = 0;
}
canvas.drawText(textCharArray, i, 1, paddingLeft + drawedWidth,
(lineCount + 1) * textSize, paint1);
drawedWidth += charWidth;
}
}
}
使用方法:在Activity类对应的布局文件main.xml中:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.user.helloworld.activity.MyTextViewActivity">
<com.example.user.helloworld.view.MyTextView
android:id="@+id/mtv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
在Activity类中:
MyTextView mTV_content = (MyTextView)findViewById(R.id.mtv_content);
調用mTV_content的setPaintColor可以设置文字颜色。
你可以觉得文字行间距太小,视觉上太紧凑了。可以通过修改onDraw方法中这一行
canvas.drawText(textCharArray, i, 1, paddingLeft + drawedWidth,
(lineCount + 1) * textSize, paint1);
改成:canvas.drawText(textCharArray, i, 1, paddingLeft + drawedWidth,(lineCount + 1) * textSize*1.2f, paint1);
我当时测试使用+6.0f的形式没有效果,使用*1.2f的方式有效果,至于为什么,我也不清楚。
TextView再学习(2016-11-24)
本期项目开发时,有这样的需求:1)能识别TextView中的手机号,使用蓝色标识出来; 2)点击手机号,出现弹窗显示手机号,点击手机号可拨打电话。
TextView文本中识别超链接(邮件地址、手机号和网址),最常用的是在TextView所在的布局文件中TextView节点添加属性android:autoLink="all",这样网
址、电话号码和邮件地址自动识别为超链接,这也是系统提供的。
但是系统提供的超链接包含下划线,超链接字体颜色,点击超链接文本的点击事件如何自定义呢?
我对这两天的学习进行总结,如下:
1)如果使用xml中autoLink方式设置超链接,可以去除超超链接下划线/超链接文本颜色。
xml中添加android:autoLink="phone"
public class UseSystemTextViewActivity extends Activity {
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_use_system_text_view);
mTextView = (TextView)findViewById(R.id.tvTelephone);
String webLinkText = "我的手机号是18916961696" ;
mTextView.setText(webLinkText);
NoUnderlineSpan mNoUnderlineSpan = new NoUnderlineSpan();
if (mTextView.getText() instanceof Spannable) {
Spannable s = (Spannable) mTextView.getText();
s.setSpan(mNoUnderlineSpan, 0, s.length(), Spanned.SPAN_MARK_MARK);
}
//设置超链接文本颜色
mTextView.setLinkTextColor(getResources().getColor(R.color.red));
}
public static class NoUnderlineSpan extends UnderlineSpan {
public NoUnderlineSpan() {}
public NoUnderlineSpan(Parcel src) {}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
}
}
通过这种方式可以去除超链接下划线,改文本颜色,但无法自定义点击超链接的点击事件。
通过自定义类继承ClickableSpan重写onClick和updateDrawState也不能达到效果。
2)那么如何自定义超链接点击事件呢?
**需要自定义类继承ClickableSpan类,重写updateDrawState和onClick方法。onClick实现自定义点击事件,updateDrawState 实现字体颜色和下划线设置。
**将SpannableString包装一个字符串,调用setSpan方法设置字符片段为ClickableSpan。
自定义类代码如下:
private class NoLineClickSpan extends ClickableSpan {
String text;
public NoLineClickSpan(String text) {
this.text = text;
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(ds.linkColor);
ds.setUnderlineText(false); //去掉下划线
}
@Override
public void onClick(View widget) {
processHyperLinkClick(text); //点击超链接时调用
}
}
使用Spannable的setSpan设置超链接,代码如下:
由此可见,如果想自定义点击事件,不能使用在xml中添加android:autoLink方式。String linkText = "TextView设置超链接文本颜色"; SpannableString spStr = new SpannableString(linkText); ClickableSpan clickSpan = new NoLineClickSpan(spStr.toString()); //设置超链接 spStr.setSpan(clickSpan, 0, spStr.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); mTextView.append(spStr); mTextView.setMovementMethod(LinkMovementMethod.getInstance());
最后我参考这篇文章,Android Custom Hyperlinked TextView理解了怎么去实现,这篇写的非常好!!!
TextLinkClickListener 内部监听器
ClickableSpan - 负责点击事件
gatherLinksForText() 一般在Activity中调用LinkEnabledTextView的gatherLinksForText方法,传入要识别超链接的字符串即可。
文字背景会出现淡蓝色的背景参考 http://www.mincoder.com/article/4466.shtml
有关SpannableStringBuilder SpannableString区别可以看看:
http://blog.csdn.net/harvic880925/article/details/38984705
http://qiita.com/sutchan/items/5153e6a21ad30dc9e3cd
对超链接各种实现方式总结的文章,也非常好!http://souly.cn/%E6%8A%80%E6%9C%AF%E5%8D%9A%E6%96%87/2016/01/29/TextView%E8%B6%85%E9%93%BE%E6%8E%A5%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F%E6%80%BB%E7%BB%93/
3)我也试着在解决文字排版不整齐的MyTextView中去集成识别自定义正则匹配字符是超链接,实现自定义点击事件。由于MyTextView重写了onDraw方法,TextView设置LinkMovementMethod,LinkMovementMethod类的onTouchEvent于MyTextView的触屏事件存在冲突,出现了点击超链接事件不起作用。这个作为todo以后再研究吧!