朋友们,你们在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. zabbix2.4升级到2.5 --考虑升级到zabbix3.0

    现在zabbix服务器,zabbix服务日志频繁出现MySQL server  has gone away,经搜索,此问题在zabbix2.5之前是zabbix的一个bug,zabbix2.5后已经修 ...

  2. [git 学习篇]删除文件

    1 现在本地文件管理器删除了readme.txt(这个readme.txt已经在创库存在的) rm -rf readme.txt 2 此时git status查看 $ git status # On ...

  3. List容器——LinkedList及常用API,实现栈和队列

    LinkedList及常用API ①   LinkedList----链表 ②   LinkedList类扩展AbstractSequentialList并实现List接口 ③   LinkedLis ...

  4. SPFA ----模板 O(kE) (k一般不超过2)

    原理:若一个点入队的次数超过顶点数V,则存在负环: #include "bits/stdc++.h" using namespace std; ; struct Edge { in ...

  5. 九度oj 1005

    题目1005:Graduate Admission 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6182 解决:1791 题目描述:                        It ...

  6. Hibernate的简单封装Session(方便调用)

    因为每次用增删改查时都需要用到hibernate的配置来生成session工厂进而生成session,比较麻烦,所以我们直接封装一个可以调用的类,需要的时候只需要调用即可. 新建一个Hibernate ...

  7. Redis 复制功能的几个重要方面

    Redis 复制功能的几个重要方面:1. 一个Master可以有多个Slave:2. Redis使用异步复制.从2.8开始,Slave会周期性(每秒一次)发起一个Ack确认复制流(replicatio ...

  8. CTSC 1999 家园 【网络流24题】星际转移

    直接把每一个点,每一天拆成一个点. 然后每个点到下一天连$inf$的边. 然后把飞船的路径用容量为飞船容量的边连接. 然后跑网络流判断是否满流. #include <queue> #inc ...

  9. java面试题之为什么hashmap的数组初始化大小都是2的N次方?

    当数组长度为2的N次方时,不同的key算出的index相同的几率小,数据在数组上分配均匀,hash碰撞的几率小,提升查询效率,从大O(N)提升至O(1):

  10. 标准C程序设计七---44

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...