实现TextView中link的点击效果
朋友们,你们在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的点击效果的更多相关文章
- css上传图片中等待不可点击效果
<!DOCTYPE html> <html> <head> <title>上传中</title> <style type=" ...
- 让低版本的 Android 项目显示出 Material 风格的点击效果
每天都被不同的需求纠缠的生活是幸福而又不幸的,这不我们家亲爱的设计师们又让我们在低版本的 Android 平台上实现一下类似于 Material Design 的点击效果. 虽然大家都知道 Mater ...
- TextView中超链接拦截
TextView中的超链接点击时,其实是通过Intent方式的,因此会调用Activity中的startActivity(Intent intent)方法,所以可在此方法中做些简单的拦截操作 例如拦截 ...
- android selector设置button点击效果(具体)以及常见问题
button的点击效果学习起来其实比較easy,此点对开发人员来说也是使用的比較频繁的一个知识点,与它相关的还有编辑框的获取焦点时改变背景颜色.选择button选择时改变字体颜色等等.这些其实都是用到 ...
- 自定义可点击的ImageSpan并在TextView中内置“View“
有的时候可能想在TextView中添加一些图片,比如下图,发短信输入联系人时,要把联系人号码换成一个图片,但这个图片无法用固定的某张图,而是根据内容进行定制的,这更像一个view. 当然,如果你不是v ...
- AndroidRichText 让Textview轻松的支持富文本(图像ImageSpan、点击效果等等类似QQ微信聊天)
代码地址:https://github.com/Luction/AndroidRichText AndroidRichText帮助实现像QQ,微信一样的,一个TextView里既有文字又有表情又有图片 ...
- Android TextView中实现点击文本超链接(无下划线)的封装类
android中有的时候须要在TextView上设置一些超链接,点击这些超链接时进行一些操作.比如新浪微博上的一些keyword,点击时会跳转到对应的页面. 怎样实现我们就直接看源代码吧. /** * ...
- Android TextView点击效果
在Android开发中,我们有时候需要单独的点击某一段文本,如图所示: 如上图,我们要求点击新用户注册这个TextView,为了有更好的用户体验,我们肯定要设置该TextView的点击效果.下面介绍如 ...
- robot framework程序运行过程中,遇到点击事件之后,未出现点击之后的效果(求解)
1.click Element操作,在实际过程中偶然会出现,日志显示已点击成功,但是实际自动化页面,没有点击成功之后的操作 现象: 现象描述:程序执行到点击侧边栏的[人员信息]之后,日志显示已经点击成 ...
随机推荐
- css中可继承和不可继承属性
一.无继承性的属性 1.display:规定元素应该生成的框的类型 2.文本属性: vertical-align:垂直文本对齐 text-decoration:规定添加到文本的装饰 text-shad ...
- Leetcode 451.根据字符出现频率排序
根据字符出现频率排序 给定一个字符串,请将字符串里的字符按照出现的频率降序排列. 示例 1: 输入: "tree" 输出: "eert" 解释: 'e'出现两次 ...
- 从几率到logisitic函数
odds 几率,又称事件的优势比.几率和概率的关系如下: o=p1−pp=o1+o Logistic 回归模型的因变量只有 1/0 两种取值.假设在 p 个独立自变量 x1,x2,…,xp 作用下,记 ...
- Eclipse调试程序及项目的导入导出
Eclipse调试程序 调试概述: ① 调试就是测试程序的方法,主要的目的就是解决程序的逻辑问题,流程是:发现问题.修改问题.正确执行; ② 以前我们可以使用System.out.printl ...
- 静态方法,Arrays类,二维数组
一.静态方法 静态方法属于类的,可以直接使用类名.方法名()调用. 静态方法的声明 访问修饰符 static 类型 方法名(参数列表) { //方法体 } 方法的作用:一个程序分解成几个方法,有利于快 ...
- iOS学习笔记29-系统服务(二)通讯录
一.通讯录 iOS中的通讯录是存储在数据库中的,由于iOS的权限设计,开发人员是不允许直接访问通讯录数据库的,实现通讯录操作需要使用到AddressBook.framework框架. AddressB ...
- 性能学习之六---socket接口测试
socket协议较底层,所以是一个万能协议.socket发的是数据包,所以较难看懂. 下面我们来讲解socket接口测试. 大致思路为:新建sever端和client端---建立连接---发送数据 一 ...
- BZOJ-2829 信用卡凸包
凸包题. 我们先把所有信用卡的四个定点的坐标求出来,然后计算凸包长度,最后加上一个圆的周长就行. #include <cstdlib> #include <cstdio> #i ...
- Android2.2源码init机制分析
1 源码分析必备知识 1.1 linux内核链表 Linux内核链表的核心思想是:在用户自定义的结构A中声明list_head类型的成员p,这样每个结构类型为A的变量a中,都拥有同样的成员p,如下: ...
- docker学习路线
http://www.simapple.com/320.html DOCKER 官网 :https://docs.docker.com/docker-for-mac/