朋友们,你们在TextView处理link的时候是不是一直被苦逼的android默认的方式困扰?每次点击link的时候,点击效果是整个textview来响应。非常烂吧?原因就不多赘述了。

那么以下这个控件就适合你了。 gitbub的链接:https://github.com/zhangjizxc/LinkClickTextView

好用的话。帮忙点个赞。

package com.zhang.linkclick;

import com.test.zhang.R;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Handler;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.TextView; /**
*
* @author zhangji
*
*/
public class LinkClickTextView extends TextView { private static final String TAG = "LinkClickTextView";
private ClickableSpan mSelectedLink;
private boolean mHasPerformedLongPress;
private CheckForLongPress mPendingCheckForLongPress;
private ForegroundColorSpan mForegroundColorSpan;
private UnsetLinkPressedState mUnsetLinkPressedState; public LinkClickTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public LinkClickTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setLinksClickable(false);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LinkClickTextView, defStyle, 0);
ColorStateList titleColor = a.getColorStateList(R.styleable.LinkClickTextView_textColorLinkClick);
if (titleColor != null) {
mForegroundColorSpan =new ForegroundColorSpan(titleColor.getColorForState(EMPTY_STATE_SET, Color.RED));
}
} @Override
public boolean onTouchEvent(MotionEvent event) {
boolean handled = handledLinkTouch(event); if (handled) {
return true;
} else {
return super.onTouchEvent(event);
}
} @Override
public void cancelLongPress() {
removeLongPressCallback();
super.cancelLongPress();
} @Override
protected void onDetachedFromWindow() {
removeLongPressCallback();
super.onDetachedFromWindow();
} private boolean handledLinkTouch(MotionEvent event) { CharSequence text = getText();
int pointCount = event.getPointerCount();
if (!(text instanceof Spannable) || pointCount > 1) {
return false;
}
int action = event.getAction();
Spannable buffer = (Spannable) text;
switch (action) {
case MotionEvent.ACTION_DOWN:
int x = (int) event.getX();
int y = (int) event.getY(); x -= this.getTotalPaddingLeft();
y -= this.getTotalPaddingTop(); x += this.getScrollX();
y += this.getScrollY(); Layout layout = this.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
checkForLongClick(0);
mSelectedLink = link[0];
setLinkPressed(true);
return true;
} else {
mSelectedLink = null;
}
break;
case MotionEvent.ACTION_MOVE:
if (mSelectedLink != null) {
return true;
}
break;
case MotionEvent.ACTION_UP:
if (mSelectedLink != null) {
if (!mHasPerformedLongPress) {
// This is a tap, so remove the longpress check
removeLongPressCallback();
mSelectedLink.onClick(this);
}
if (mUnsetLinkPressedState == null) {
mUnsetLinkPressedState = new UnsetLinkPressedState();
}
postDelayed(mUnsetLinkPressedState,
ViewConfiguration.getPressedStateDuration());
mSelectedLink = null;
return true;
}
break;
case MotionEvent.ACTION_CANCEL:
removeLongPressCallback();
break;
default:
break;
}
return false;
} private void checkForLongClick(int delayOffset) {
if (isLongClickable()) {
mHasPerformedLongPress = false; if (mPendingCheckForLongPress == null) {
mPendingCheckForLongPress = new CheckForLongPress();
}
mPendingCheckForLongPress.rememberWindowAttachCount();
postDelayed(mPendingCheckForLongPress,
ViewConfiguration.getLongPressTimeout() - delayOffset);
}
} private void removeLongPressCallback() {
if (mPendingCheckForLongPress != null) {
removeCallbacks(mPendingCheckForLongPress);
}
} class CheckForLongPress implements Runnable { private int mOriginalWindowAttachCount; public void run() {
if (mOriginalWindowAttachCount == getWindowAttachCount()) {
if (performLongClick()) {
mHasPerformedLongPress = true;
}
}
} public void rememberWindowAttachCount() {
mOriginalWindowAttachCount = getWindowAttachCount();
}
} private void setLinkPressed(boolean pressed) {
if (!(getText() instanceof Spannable) || mForegroundColorSpan == null) {
return;
}
Spannable buffer = (Spannable) getText();
if (buffer == null) {
return;
}
if (pressed) {
buffer.setSpan(mForegroundColorSpan, buffer.getSpanStart(mSelectedLink),
buffer.getSpanEnd(mSelectedLink), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
buffer.removeSpan(mForegroundColorSpan);
}
} private final class UnsetLinkPressedState implements Runnable {
public void run() {
setLinkPressed(false);
}
}
}

实现TextView中link的点击效果的更多相关文章

  1. css上传图片中等待不可点击效果

    <!DOCTYPE html> <html> <head> <title>上传中</title> <style type=" ...

  2. 让低版本的 Android 项目显示出 Material 风格的点击效果

    每天都被不同的需求纠缠的生活是幸福而又不幸的,这不我们家亲爱的设计师们又让我们在低版本的 Android 平台上实现一下类似于 Material Design 的点击效果. 虽然大家都知道 Mater ...

  3. TextView中超链接拦截

    TextView中的超链接点击时,其实是通过Intent方式的,因此会调用Activity中的startActivity(Intent intent)方法,所以可在此方法中做些简单的拦截操作 例如拦截 ...

  4. android selector设置button点击效果(具体)以及常见问题

    button的点击效果学习起来其实比較easy,此点对开发人员来说也是使用的比較频繁的一个知识点,与它相关的还有编辑框的获取焦点时改变背景颜色.选择button选择时改变字体颜色等等.这些其实都是用到 ...

  5. 自定义可点击的ImageSpan并在TextView中内置“View“

    有的时候可能想在TextView中添加一些图片,比如下图,发短信输入联系人时,要把联系人号码换成一个图片,但这个图片无法用固定的某张图,而是根据内容进行定制的,这更像一个view. 当然,如果你不是v ...

  6. AndroidRichText 让Textview轻松的支持富文本(图像ImageSpan、点击效果等等类似QQ微信聊天)

    代码地址:https://github.com/Luction/AndroidRichText AndroidRichText帮助实现像QQ,微信一样的,一个TextView里既有文字又有表情又有图片 ...

  7. Android TextView中实现点击文本超链接(无下划线)的封装类

    android中有的时候须要在TextView上设置一些超链接,点击这些超链接时进行一些操作.比如新浪微博上的一些keyword,点击时会跳转到对应的页面. 怎样实现我们就直接看源代码吧. /** * ...

  8. Android TextView点击效果

    在Android开发中,我们有时候需要单独的点击某一段文本,如图所示: 如上图,我们要求点击新用户注册这个TextView,为了有更好的用户体验,我们肯定要设置该TextView的点击效果.下面介绍如 ...

  9. robot framework程序运行过程中,遇到点击事件之后,未出现点击之后的效果(求解)

    1.click Element操作,在实际过程中偶然会出现,日志显示已点击成功,但是实际自动化页面,没有点击成功之后的操作 现象: 现象描述:程序执行到点击侧边栏的[人员信息]之后,日志显示已经点击成 ...

随机推荐

  1. SDOJ 3740 Graph

    8.9 t3 [描述] 给你一个图,一共有 N 个点,2*N-2 条有向边. 边目录按两部分给出 1. 开始的 n-1 条边描述了一颗以 1 号点为根的生成树,即每个点都可以由 1 号点 到达. 2. ...

  2. Leetcode with Python

    1. Two Sum Given an array of integers, return indices of the two numbers such that they add up to a ...

  3. C#发送邮件异常,返回信息乱码

    发邮件时出现了异常: 在 System.Net.Mail.MailCommand.CheckResponse(SmtpStatusCode statusCode, String response) 在 ...

  4. hdu1599 find the mincost route floyd求出最小权值的环

    find the mincost route Time Limit: 1000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  5. DS博客作业06——图

    1.本周学习总结(0--2分) 1.思维导图 2.谈谈你对图结构的认识及学习体会. 这章学习了图,学习了图的两种存储结构:邻接矩阵和邻接表.这两种存储结构都用到了之前学c时学到的结构体,将结构体充分运 ...

  6. Spring c3p0连接池配置

    数据库连接池 数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”.预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去.我们可以通过设定连接 ...

  7. Hibernate框架简述(转)

    转自:http://www.cnblogs.com/eflylab/archive/2007/01/09/615338.html Hibernate的核心组件在基于MVC设计模式的JAVA WEB应用 ...

  8. bootstrap 中dropmenu不起作用

    今天在使用bootstrap发现dropmenu一直不起作用,代码是从官网拷贝过来. 网上查找可以用的页面进行一点点的去除分析,发现竟然是顺序反了导致的. 在使用dropmenu时需要引入jquery ...

  9. 漫谈登录桩(MockStub)的实现

    2014年6月4日,6月的第一个星期三,我正式入职百度,开始baiduer的工作.这不到2个月的时间,因为人力资源这边原因,我从INF部门离开,拉到了百度Hi-Server团队中来.2个完全不着调的岗 ...

  10. 主机ping不通虚拟机,但是虚拟机能ping通主机

    一.虚拟机网络连接方式选择Nat 二. 关闭Linux防火墙命令:service iptables stop / service firewalld stop 查看Linux防火墙状态命令:servi ...