傳送門:在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:[email protected]\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.
*/