传送门:在Android實作HTML TextView與AutoLink使用的建議方式
-
Android的TextView除了可以显示文字,还可以使用HTML语法来调整文字样式,无需特地使用WebView。
textView.setText(Html.fromHtml("HTML语法字符串"));
-
小白普及:另外,需要学习HTML语言(tv1)
<font> - 设置颜色与字体
<big> - 设置大号字体
<small> - 设置小号字体
<i>\<b> - 设置斜体、粗体
<a> - 设置链接地址
<img> - 插入图片
-
android:autolink 属性(tv2)
None - 不匹配任何链接(默认)
web - 网址
email - 邮箱
phone - 电话
map - 匹配映射地址
all - 匹配所有链接 -
TextView还可以显示表情图像与文本(tv3)、点击图像4可跳转链接(www.baidu.com)
-
TextView实现文字链接跳转Activity(tv4)
利用TextView的一些属性:android:ellipsize="start" 省略号在开头
android:ellipsize="middle" 省略号在中间
android:ellipsize="end" 省略号在结尾
android:ellipsize="marquee" 跑马灯显示
外加一个android:focusable="true" android:focusableModel
但是存在Bug,一旦失去焦点则无法继续滚动了
可以尝试重写TextView,isFocuse()方法,return true;可以解决一般失去焦点的问题。
但是该种方式在 ReBornForTextViewHTML 项目中运行后并没有这样的效果,初步认为是无法获取到焦点,如果需要实现,使用重写TextView的方法会更好,本项目里面重写的TextView点击可暂停,再次点击可继续滚动。
-
Android Studio项目实战 - ReBornForTextViewHTML
主要代码:
MainActivity:private void initView() {
tv1 = (TextView) findViewById(R.id.tv1);//使用HTML
tv2 = (TextView) findViewById(R.id.tv2);//使用autoLink属性
tv3 = (TextView) findViewById(R.id.tv3);//使用HTML+反射机制获取资源id
tv4 = (MarqueeTextView) findViewById(R.id.tv4);//使用3个属性实现跑马灯效果
//tv1
String strTv1HTML = "<font color='red'>RebornForTextViewHTML</font><br>";
strTv1HTML += "<font color='#0000ff'><big><i>I love android</i></big></font><p>";
strTv1HTML += "<big><a href='http://www.baidu.com'>百度</a><big>";
CharSequence charSequence = Html.fromHtml(strTv1HTML);
tv1.setText(charSequence);
tv1.setMovementMethod(LinkMovementMethod.getInstance());//点击时候产生超链接
//tv2
String strTv2 = "我的URL: http://www.sina.com\n";
strTv2 += "我的email:532612578@qq.com\n";
strTv2 += "我的电话:+ 86 010-2131233";
tv2.setText(strTv2);
tv2.setMovementMethod(LinkMovementMethod.getInstance());
//tv3
tv3.setTextColor(Color.BLACK);
String strTv3HTML = "图像1<img src='image1'/>图像2<img src='image2'/>图像3<img src='image3'/>";
strTv3HTML += "图像4<a href='http://www.baidu.com'><img src='image4'></a>图像5<img src='image5'/>";
//底部有该方法源码
CharSequence chtv3 = Html.fromHtml(strTv3HTML, new Html.ImageGetter() {
public Drawable getDrawable(String source) {
//获得系统资源信息
Drawable drawable = getResources().getDrawable(getResourceId(source));
//将第三张图片按比例压缩成原宽高的50%
if (source.equals("image3")) {
drawable.setBounds(0, 0, drawable.getIntrinsicWidth() / 2, drawable.getIntrinsicHeight() / 2);
} else {//按比例压缩成原宽高的25%
drawable.setBounds(0, 0, drawable.getIntrinsicWidth() / 4, drawable.getIntrinsicHeight() / 4);
}
return drawable;
}
}, null);
tv3.setText(chtv3);
tv3.setMovementMethod(LinkMovementMethod.getInstance());
String strTv4 = "《档案》是北京电视台推出的纪实栏目,于2009年2月4日开播。节目定位为演播室节目,由一个特定的,极具个性化的讲述者(主持人)现场讲述和展示为基本形态,节目形式以案件和事";
CharSequence charSequence4 = Html.fromHtml(strTv4);
tv4.setText(charSequence4);
tv4.setMovementMethod(LinkMovementMethod.getInstance());
tv4.init(getWindowManager());
tv4.startScroll();
}
```getResourceId方法:
/**
* 根据name获取资源id
*
* @param name
* @return
*/
public int getResourceId(String name) {
//根据资源ID变量名获得Field对象,使用反射机制
try {
Field field = R.drawable.class.getField(name);
//取得并返回资源id字段(静态变量)的值
return Integer.parseInt(field.get(null).toString());
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
``` MarqueeTextView:
public class MarqueeTextView extends TextView implements View.OnClickListener {
public final static String TAG = MarqueeTextView.class.getSimpleName();
private float textLength = 0f;//文本长度
private float viewWidth = 0f;
private float step = 0f;//文字的横坐标
private float y = 0f;//文字的纵坐标
private float temp_view_plus_text_length = 0.0f;//用于计算的临时变量
private float temp_view_plus_two_text_length = 0.0f;//用于计算的临时变量
public boolean isStarting = false;//是否开始滚动
private Paint paint = null;//绘图样式
private String text = "";//文本内容
public MarqueeTextView(Context context) {
super(context);
initView();
}
public MarqueeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public MarqueeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
private void initView() {
setOnClickListener(this);
}
public void init(WindowManager windowManager) {
paint = getPaint();
text = getText().toString();
textLength = paint.measureText(text);
viewWidth = getWidth();
if (viewWidth == 0) {
if (windowManager != null) {
Display display = windowManager.getDefaultDisplay();
viewWidth = display.getWidth();
}
}
step = textLength;
temp_view_plus_text_length = viewWidth + textLength;
temp_view_plus_two_text_length = viewWidth + textLength * 2;
y = getTextSize() + getPaddingTop();
}
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.step = step;
ss.isStarting = isStarting;
return ss;
}
public void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
step = ss.step;
isStarting = ss.isStarting;
}
public static class SavedState extends BaseSavedState {
public boolean isStarting = false;
public float step = 0.0f;
SavedState(Parcelable superState) {
super(superState);
}
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeBooleanArray(new boolean[]{isStarting});
out.writeFloat(step);
}
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
public SavedState[] newArray(int size) {
return new SavedState[size];
}
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
};
private SavedState(Parcel in) {
super(in);
boolean[] b = null;
in.readBooleanArray(b);
if (b != null && b.length > 0)
isStarting = b[0];
step = in.readFloat();
}
}
public void startScroll() {
isStarting = true;
invalidate();
}
public void stopScroll() {
isStarting = false;
invalidate();
}
public void onDraw(Canvas canvas) {
canvas.drawText(text, temp_view_plus_text_length - step, y, paint);
if (!isStarting) {
return;
}
step += 0.5;//0.5为文字滚动速度。
if (step > temp_view_plus_two_text_length)
step = textLength;
invalidate();
}
public void onClick(View v) {
if (isStarting)
stopScroll();
else
startScroll();
}
}
布局文件:
<TextView
android:id="@+id/tv2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv1"
android:autoLink="all"
android:text="@string/link_text"
android:textSize="12sp" />
<TextView
android:id="@+id/tv3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv2"
android:background="#FFF"
android:text="tv3-img+HTML"
android:textSize="12sp" />
<com.rdc.rebornfortextviewhtml.view.MarqueeTextView
android:id="@+id/tv4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv3"
android:background="#FFF"
android:textColor="@android:color/black"
/>
最后附上fromHtml 方法源码解析:
- fromHtml(String source, ImageGetter imageGetter, TagHandler tagHandler)方法源码解析
/**- Returns displayable styled text from the provided HTML string.
- Any <img> tags in the HTML will use the specified ImageGetter
- to request a representation of the image (use null if you don’t
- want this) and the specified TagHandler to handle unknown tags
- (specify null if you don’t want this).
-
-
This uses TagSoup to handle real HTML, including all of the brokenness found in the wild.
*/