在TextView 中设置autoLink 属性可以自动识别Web URL,电话号码,电子邮件地址添加下划线改变字体颜色并实现点击事件,支持自动识别的类型:

android:autoLink=“web” 匹配Web URL。

android:autoLink=“phone” 匹配电话号码

android:autoLink=“email” 匹配电子邮件地址

android:autoLink=“map” 匹配地理位置

android:autoLink=“all” 匹配所有可用的模式

android:autoLink=“none” 不匹配任何类型

也可以类似这样的设置 android:autoLink=“web|phone” 表示匹配web URL 和手机号

上面的属性也可以通过java 代码的形式对TextView 设置

setAutoLinkMask(int mask) 进行设置

设置的参数分别是:

Linkify.WEB_URLS 匹配Web UR

Linkify.PHONE_NUMBERS 匹配电话号码

Linkify.EMAIL_ADDRESSES 匹配电子邮件地址

Linkify.MAP_ADDRESSES 地理位置匹配

Linkify.ALL 匹配所有可用的模式

设置完antoLink属性,点击TextView中的链接时会跳转的对应的界面,比如点击网页的链接会跳转到系统的默认的浏览器界面,点击手机号会进入拨打电话界面,但是这都是系统默认的,我们可不可以进行拦截处理,跳转到我们指定的界面呢,当然是可以的。下面是我的拦截处理的方法。

继承 MovementMethod ,这里我们先看一下MovementMethod的源码,它的源码比较少

public class LinkMovementMethod extends ScrollingMovementMethod {    private static final int CLICK = 1;    private static final int UP = 2;    private static final int DOWN = 3;    @Override    public boolean canSelectArbitrarily() {        return true;    }    @Override    protected boolean handleMovementKey(TextView widget, Spannable buffer, int keyCode,            int movementMetaState, KeyEvent event) {        switch (keyCode) {            case KeyEvent.KEYCODE_DPAD_CENTER:            case KeyEvent.KEYCODE_ENTER:                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {                    if (event.getAction() == KeyEvent.ACTION_DOWN &&                            event.getRepeatCount() == 0 && action(CLICK, widget, buffer)) {                        return true;                    }                }                break;        }        return super.handleMovementKey(widget, buffer, keyCode, movementMetaState, event);    }    @Override    protected boolean up(TextView widget, Spannable buffer) {        if (action(UP, widget, buffer)) {            return true;        }        return super.up(widget, buffer);    }            @Override    protected boolean down(TextView widget, Spannable buffer) {        if (action(DOWN, widget, buffer)) {            return true;        }        return super.down(widget, buffer);    }    @Override    protected boolean left(TextView widget, Spannable buffer) {        if (action(UP, widget, buffer)) {            return true;        }        return super.left(widget, buffer);    }    @Override    protected boolean right(TextView widget, Spannable buffer) {        if (action(DOWN, widget, buffer)) {            return true;        }        return super.right(widget, buffer);    }    private boolean action(int what, TextView widget, Spannable buffer) {        Layout layout = widget.getLayout();        int padding = widget.getTotalPaddingTop() +                      widget.getTotalPaddingBottom();        int areaTop = widget.getScrollY();        int areaBot = areaTop + widget.getHeight() - padding;        int lineTop = layout.getLineForVertical(areaTop);        int lineBot = layout.getLineForVertical(areaBot);        int first = layout.getLineStart(lineTop);        int last = layout.getLineEnd(lineBot);        ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class);        int a = Selection.getSelectionStart(buffer);        int b = Selection.getSelectionEnd(buffer);        int selStart = Math.min(a, b);        int selEnd = Math.max(a, b);        if (selStart < 0) {            if (buffer.getSpanStart(FROM_BELOW) >= 0) {                selStart = selEnd = buffer.length();            }        }        if (selStart > last)            selStart = selEnd = Integer.MAX_VALUE;        if (selEnd < first)            selStart = selEnd = -1;        switch (what) {        case CLICK:            if (selStart == selEnd) {                return false;            }            ClickableSpan[] link = buffer.getSpans(selStart, selEnd, ClickableSpan.class);            if (link.length != 1)                return false;            link[0].onClick(widget);            break;        case UP:            int bestStart, bestEnd;            bestStart = -1;            bestEnd = -1;            for (int i = 0; i < candidates.length; i++) {                int end = buffer.getSpanEnd(candidates[i]);                if (end < selEnd || selStart == selEnd) {                    if (end > bestEnd) {                        bestStart = buffer.getSpanStart(candidates[i]);                        bestEnd = end;                    }                }            }            if (bestStart >= 0) {                Selection.setSelection(buffer, bestEnd, bestStart);                return true;            }            break;        case DOWN:            bestStart = Integer.MAX_VALUE;            bestEnd = Integer.MAX_VALUE;            for (int i = 0; i < candidates.length; i++) {                int start = buffer.getSpanStart(candidates[i]);                if (start > selStart || selStart == selEnd) {                    if (start < bestStart) {                        bestStart = start;                        bestEnd = buffer.getSpanEnd(candidates[i]);                    }                }            }            if (bestEnd < Integer.MAX_VALUE) {                Selection.setSelection(buffer, bestStart, bestEnd);                return true;            }            break;        }        return false;    }    @Override    public boolean onTouchEvent(TextView widget, Spannable buffer,                                MotionEvent event) {        int action = event.getAction();        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {            int x = (int) event.getX();            int y = (int) event.getY();            x -= widget.getTotalPaddingLeft();            y -= widget.getTotalPaddingTop();            x += widget.getScrollX();            y += widget.getScrollY();            Layout layout = widget.getLayout();            int line = layout.getLineForVertical(y);            int off = layout.getOffsetForHorizontal(line, x);            ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);            if (links.length != 0) {                if (action == MotionEvent.ACTION_UP) {                    links[0].onClick(widget);                } else if (action == MotionEvent.ACTION_DOWN) {                    Selection.setSelection(buffer,                        buffer.getSpanStart(links[0]),                        buffer.getSpanEnd(links[0]));                }                return true;            } else {                Selection.removeSelection(buffer);            }        }        return super.onTouchEvent(widget, buffer, event);    }    @Override    public void initialize(TextView widget, Spannable text) {        Selection.removeSelection(text);        text.removeSpan(FROM_BELOW);    }    @Override    public void onTakeFocus(TextView view, Spannable text, int dir) {        Selection.removeSelection(text);        if ((dir & View.FOCUS_BACKWARD) != 0) {            text.setSpan(FROM_BELOW, 0, 0, Spannable.SPAN_POINT_POINT);        } else {            text.removeSpan(FROM_BELOW);        }    }    public static MovementMethod getInstance() {        if (sInstance == null)            sInstance = new LinkMovementMethod();        return sInstance;    }    private static LinkMovementMethod sInstance;    private static Object FROM_BELOW = new NoCopySpan.Concrete();}

在上面的这段代码中处理界面跳转的只有这一行 links[0].onClick(widget);我们要实现自己的跳转只要在自定义的LinkMovementMethod的这一行进行处理就行了。
先定义一个替换links[0].onClick(widget);的接口

public interface LinkClickListener {    /**     * true  表示要自己处理  false 使用系统默认     *     * @param mURL     * @return     */    boolean onLinkClick(String mURL);}

定义一个LinkMovementMethod的子类 LinkMovementMethodEx,在onTouchEvent方法中做了判断,在我们应用自己处理的情况,就不在走系统的默认处理,只有我们自己不处理的情况下才走系统的。

public class LinkMovementMethodEx extends LinkMovementMethod {    private LinkClickListener listener;    public LinkMovementMethodEx(LinkClickListener listener) {        this.listener = listener;    }    @Override    public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {        int action = event.getAction();        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {            int x = (int) event.getX();            int y = (int) event.getY();            x -= widget.getTotalPaddingLeft();            y -= widget.getTotalPaddingTop();            x += widget.getScrollX();            y += widget.getScrollY();            Layout layout = widget.getLayout();            int line = layout.getLineForVertical(y);            int off = layout.getOffsetForHorizontal(line, x);            ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);            if (links.length != 0) {                if (action == MotionEvent.ACTION_UP) {                    if (links[0] instanceof URLSpan) {                        URLSpan url = (URLSpan) links[0];                        if (listener != null && listener.onLinkClick(url.getURL())) {                            return true;                        } else {                            links[0].onClick(widget);                        }                    }                } else if (action == MotionEvent.ACTION_DOWN) {                    Selection.setSelection(buffer,                            buffer.getSpanStart(links[0]),                            buffer.getSpanEnd(links[0]));                }                return true;            } else {                Selection.removeSelection(buffer);            }        }        return super.onTouchEvent(widget, buffer, event);    }}

在项目中的引用

public class MainActivity extends Activity {    private String TAG = MainActivity.class.getSimpleName();    private TextView title;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        title = findViewById(R.id.tv_content);        title.setText(" 10086 中国移动的 这是百度的 https://www.baidu.com/");        title.setMovementMethod(new LinkMovementMethodEx(new LinkClickListener() {            @Override            public boolean onLinkClick(String mURL) {                //在这里执行直接的处理逻辑并将返回值设置为true                Log.i(TAG, "onLinkClick: " + mURL);                return false;            }        }));    }}

源码地址 https://github.com/songdaren123/TextLink

更多相关文章

  1. android 常用 属性
  2. ImageView 常用属性的分析
  3. Android(安卓)Switch属性全记录
  4. android 常用 属性
  5. ANDROID 输入法出现挤压屏幕、ANDROID输入键盘覆盖了屏幕控件的
  6. Android(安卓)模拟器横屏竖屏切换设置
  7. android环境变量的设置及注意问题
  8. (4.2.15)【android开源工具】Android画柱状图
  9. Android(安卓)实现水波纹动效

随机推荐

  1. Android 自定义文本框(带图片)
  2. Android 获取当前语言的方法1
  3. android 自动化测试 monkey
  4. Android的setTag
  5. Android延时执行的几种方法
  6. Android实现倒计时启动功能的实现
  7. Android studio 启动模拟器报错-Turn off
  8. Android录音功能和播放录音功能的示例源
  9. Android Fresco图片处理库用法API英文原
  10. android中调用系统的打电话功能