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

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

好用的话。帮忙点个赞。

  1. package com.zhang.linkclick;
  2.  
  3. import com.test.zhang.R;
  4.  
  5. import android.content.Context;
  6. import android.content.res.ColorStateList;
  7. import android.content.res.TypedArray;
  8. import android.graphics.Color;
  9. import android.os.Handler;
  10. import android.text.Layout;
  11. import android.text.Selection;
  12. import android.text.Spannable;
  13. import android.text.style.ClickableSpan;
  14. import android.text.style.ForegroundColorSpan;
  15. import android.util.AttributeSet;
  16. import android.util.Log;
  17. import android.view.MotionEvent;
  18. import android.view.ViewConfiguration;
  19. import android.widget.TextView;
  20.  
  21. /**
  22. *
  23. * @author zhangji
  24. *
  25. */
  26. public class LinkClickTextView extends TextView {
  27.  
  28. private static final String TAG = "LinkClickTextView";
  29. private ClickableSpan mSelectedLink;
  30. private boolean mHasPerformedLongPress;
  31. private CheckForLongPress mPendingCheckForLongPress;
  32. private ForegroundColorSpan mForegroundColorSpan;
  33. private UnsetLinkPressedState mUnsetLinkPressedState;
  34.  
  35. public LinkClickTextView(Context context, AttributeSet attrs) {
  36. this(context, attrs, 0);
  37. }
  38.  
  39. public LinkClickTextView(Context context, AttributeSet attrs, int defStyle) {
  40. super(context, attrs, defStyle);
  41. setLinksClickable(false);
  42. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LinkClickTextView, defStyle, 0);
  43. ColorStateList titleColor = a.getColorStateList(R.styleable.LinkClickTextView_textColorLinkClick);
  44. if (titleColor != null) {
  45. mForegroundColorSpan =new ForegroundColorSpan(titleColor.getColorForState(EMPTY_STATE_SET, Color.RED));
  46. }
  47. }
  48.  
  49. @Override
  50. public boolean onTouchEvent(MotionEvent event) {
  51. boolean handled = handledLinkTouch(event);
  52.  
  53. if (handled) {
  54. return true;
  55. } else {
  56. return super.onTouchEvent(event);
  57. }
  58. }
  59.  
  60. @Override
  61. public void cancelLongPress() {
  62. removeLongPressCallback();
  63. super.cancelLongPress();
  64. }
  65.  
  66. @Override
  67. protected void onDetachedFromWindow() {
  68. removeLongPressCallback();
  69. super.onDetachedFromWindow();
  70. }
  71.  
  72. private boolean handledLinkTouch(MotionEvent event) {
  73.  
  74. CharSequence text = getText();
  75. int pointCount = event.getPointerCount();
  76. if (!(text instanceof Spannable) || pointCount > 1) {
  77. return false;
  78. }
  79. int action = event.getAction();
  80. Spannable buffer = (Spannable) text;
  81. switch (action) {
  82. case MotionEvent.ACTION_DOWN:
  83. int x = (int) event.getX();
  84. int y = (int) event.getY();
  85.  
  86. x -= this.getTotalPaddingLeft();
  87. y -= this.getTotalPaddingTop();
  88.  
  89. x += this.getScrollX();
  90. y += this.getScrollY();
  91.  
  92. Layout layout = this.getLayout();
  93. int line = layout.getLineForVertical(y);
  94. int off = layout.getOffsetForHorizontal(line, x);
  95.  
  96. ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
  97. if (link.length != 0) {
  98. checkForLongClick(0);
  99. mSelectedLink = link[0];
  100. setLinkPressed(true);
  101. return true;
  102. } else {
  103. mSelectedLink = null;
  104. }
  105. break;
  106. case MotionEvent.ACTION_MOVE:
  107. if (mSelectedLink != null) {
  108. return true;
  109. }
  110. break;
  111. case MotionEvent.ACTION_UP:
  112. if (mSelectedLink != null) {
  113. if (!mHasPerformedLongPress) {
  114. // This is a tap, so remove the longpress check
  115. removeLongPressCallback();
  116. mSelectedLink.onClick(this);
  117. }
  118. if (mUnsetLinkPressedState == null) {
  119. mUnsetLinkPressedState = new UnsetLinkPressedState();
  120. }
  121. postDelayed(mUnsetLinkPressedState,
  122. ViewConfiguration.getPressedStateDuration());
  123. mSelectedLink = null;
  124. return true;
  125. }
  126. break;
  127. case MotionEvent.ACTION_CANCEL:
  128. removeLongPressCallback();
  129. break;
  130. default:
  131. break;
  132. }
  133. return false;
  134. }
  135.  
  136. private void checkForLongClick(int delayOffset) {
  137. if (isLongClickable()) {
  138. mHasPerformedLongPress = false;
  139.  
  140. if (mPendingCheckForLongPress == null) {
  141. mPendingCheckForLongPress = new CheckForLongPress();
  142. }
  143. mPendingCheckForLongPress.rememberWindowAttachCount();
  144. postDelayed(mPendingCheckForLongPress,
  145. ViewConfiguration.getLongPressTimeout() - delayOffset);
  146. }
  147. }
  148.  
  149. private void removeLongPressCallback() {
  150. if (mPendingCheckForLongPress != null) {
  151. removeCallbacks(mPendingCheckForLongPress);
  152. }
  153. }
  154.  
  155. class CheckForLongPress implements Runnable {
  156.  
  157. private int mOriginalWindowAttachCount;
  158.  
  159. public void run() {
  160. if (mOriginalWindowAttachCount == getWindowAttachCount()) {
  161. if (performLongClick()) {
  162. mHasPerformedLongPress = true;
  163. }
  164. }
  165. }
  166.  
  167. public void rememberWindowAttachCount() {
  168. mOriginalWindowAttachCount = getWindowAttachCount();
  169. }
  170. }
  171.  
  172. private void setLinkPressed(boolean pressed) {
  173. if (!(getText() instanceof Spannable) || mForegroundColorSpan == null) {
  174. return;
  175. }
  176. Spannable buffer = (Spannable) getText();
  177. if (buffer == null) {
  178. return;
  179. }
  180. if (pressed) {
  181. buffer.setSpan(mForegroundColorSpan, buffer.getSpanStart(mSelectedLink),
  182. buffer.getSpanEnd(mSelectedLink), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  183. } else {
  184. buffer.removeSpan(mForegroundColorSpan);
  185. }
  186. }
  187.  
  188. private final class UnsetLinkPressedState implements Runnable {
  189. public void run() {
  190. setLinkPressed(false);
  191. }
  192. }
  193. }

实现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. Numpy ndarray 的高级索引存在 "bug" ?

    Numpy ndarray 高级索引 "bug" ? 话说一天,搞事情,代码如下 import numpy as np tmp = [1, 2, 3, 4] * 2 a, b = ...

  2. Leetcode 475.供暖气

    供暖气 冬季已经来临. 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖. 现在,给出位于一条水平线上的房屋和供暖器的位置,找到可以覆盖所有房屋的最小加热半径. 所以,你的输入将会是房屋和供暖器 ...

  3. 【bzoj1778】[Usaco2010 Hol]Dotp 驱逐猪猡 矩阵乘法+概率dp+高斯消元

    题目描述 奶牛们建立了一个随机化的臭气炸弹来驱逐猪猡.猪猡的文明包含1到N (2 <= N <= 300)一共N个猪城.这些城市由M (1 <= M <= 44,850)条由两 ...

  4. LibreOJ2042 - 「CQOI2016」不同的最小割

    Portal Description 给出一个给出一个\(n(n\leq850)\)个点\(m(m\leq8500)\)条边的无向图.定义\(cut(s,t)\)等于\(s,t\)的最小割的容量,求在 ...

  5. 兼容ie8 rgba()写法

    background: rgba(255,255,255,.1); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#1 ...

  6. MongoDb C# 驱动操作示例

    c#操作mongo数据库 驱动采用http://www.oschina.net/p/mongo-csharp-driver C#驱动的基本数据库连接,增删改查操作 //定义对象 public clas ...

  7. 网络流24题-最长k可重线段集问题

    最长k可重线段集问题 时空限制1000ms / 128MB 题目描述 给定平面 x−O−y 上 n 个开线段组成的集合 I,和一个正整数 k .试设计一个算法,从开线段集合 I 中选取出开线段集合 S ...

  8. 【CF1017A】The Rank(签到)

    题意:给定n个人的4门课成绩,排名按总分,保证总分互不相同,求1号名次 n<=1e3,a[i],b[i],c[i],d[i]<=1e2 思路: #include<cstdio> ...

  9. 浅谈MVP设计模式

    最近公司在做一个医疗项目,使用WinForm界面作为客户端交互界面.在整个客户端解决方案中.使用了MVP模式实现.由于之前没有接触过该设计模式,所以在项目完成到某个阶段时,将使用MVP的体会写在博客里 ...

  10. FFT题集

    FFT学习参考这两篇博客,很详细,结合这看,互补. 博客一 博客二 很大一部分题目需要构造多项式相乘来进行计数问题. 1. HDU 1402 A * B Problem Plus 把A和B分别当作多项 ...