论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: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
    */
    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.
      */

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值