論TextView的超鏈接使用、顯示錶情、Html語法支持、跑馬燈效果的實現

傳送門:在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:ellipsize實現跑馬燈效果總結

  • 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
    */
    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.
      */

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章