没有合适的资源?快使用搜索试试~ 我知道了~
首页android阅读器长按选择文字功能实现代码
前言: 有时候我们需要实现长按选择文字功能,比如阅读器一般都有这个功能,有时候某个自定义控件上可能就有这种需求,如何实现呢?正好最近还算闲,想完善一下自己写的那个轻量级的txt文件阅读器(比如这个长按选择文字的功能就想加进去)。于是花了两三天时间,实现了这个功能,效果还是不错的。 首先先看看效果图吧: 授人以鱼不如授人以渔,下面具体实现原理的教程。 1.实现原理 原理其实也不难,简单总结就是:绘制文字时把显示的文字的坐标记录下来(记录文字的左上右上左下右下四个点坐标),作用就是为了计算滑动范围。执行了长按事件后,通过按的坐标,在当前显示的文字数据中根据点的坐标查找到按着的字,得到长按后选择的
资源详情
资源评论
资源推荐

android阅读器长按选择文字功能实现代码阅读器长按选择文字功能实现代码
前言: 有时候我们需要实现长按选择文字功能,比如阅读器一般都有这个功能,有时候某个自定义控件上可能就有这种需
求,如何实现呢?正好最近还算闲,想完善一下自己写的那个轻量级的txt文件阅读器(比如这个长按选择文字的功能就想加
进去)。于是花了两三天时间,实现了这个功能,效果还是不错的。
首先先看看效果图吧:
授人以鱼不如授人以渔,下面具体实现原理的教程。
1.实现原理实现原理
原理其实也不难,简单总结就是:绘制文字时把显示的文字的坐标记录下来(记录文字的左上右上左下右下四个点坐标),作

用就是为了计算滑动范围。执行了长按事件后,通过按的坐标,在当前显示的文字数据中根据点的坐标查找到按着的字,得到
长按后选择的位置与文字。当执行滑动选择时,根据手指滑动的位置坐标与当前显示的文字数据匹配来确定选择的范围与文
字。
2.具体实现具体实现
a.封装封装
为了便于操作,首先对显示可见的字符、显示的行数据进行封装。
ShowChar:
public class ShowChar {//可见字符数据封装
public char chardata ;//字符数据
public Boolean Selected =false;//当前字符是否被选中
public Point TopLeftPosition = null;
public Point TopRightPosition = null;
public Point BottomLeftPosition = null;
public Point BottomRightPosition = null;
public float charWidth = 0;//字符宽度
public int Index = 0;//当前字符位置
}
ShowLine :
public class ShowLine {//显示的行数据
public List<ShowChar> CharsData = null;
/**
*@return
*--------------------
*TODO 获取该行的数据
*--------------------
*/
public String getLineData(){
String linedata = "";
if(CharsData==null||CharsData.size()==0) return linedata;
for(ShowChar c:CharsData){
linedata = linedata+c.chardata;
}
return linedata;
}
}
说明:阅读器显示数据是一行一行的,每行都有不确定数量的字符,每个字符有自己的信息,比如字符宽度、字符在数据集合
中的下标等。绘制时,通过绘制ShowLine 去绘制每行的数据。
b.数据转化数据转化
绘制前,我们需要先要把数据转化为上面封装的格式数据以便我们使用。这个要怎么做?因为我们需要将字符串转化为一行一
行的数据,同时每个字符的字符宽度需要测量出来。如果对绘制比较熟悉的话,应该会知道系统有个paint.measureText可以
用来测量字符的宽度,这里可以借助这个来实现测量字符的宽度,同时转化为我们想要行数据。
首先,写个方法,可以将传入的字符串转化为行数据:
/**
*@param cs
*@param medsurewidth 行测量的最大宽度
*@param textpadding 字符间距
*@param paint 测量的画笔
*@return 如果cs为空或者长度为0,返回null
*--------------------
*TODO
*--------------------
*/
public static BreakResult BreakText(char[] cs, float medsurewidth, float textpadding, Paint paint) {
if(cs==null||cs.length==0){return null;}
BreakResult breakResult = new BreakResult();

breakResult.showChars = new ArrayList<ShowChar>();
float width = 0;
for (int i = 0, size = cs.length; i < size; i++) {
String mesasrustr = String.valueOf(cs[i]);
float charwidth = paint.measureText(mesasrustr);
if (width <= medsurewidth && (width + textpadding + charwidth) > medsurewidth) {
breakResult.ChartNums = i;
breakResult.IsFullLine = true;
return breakResult;
}
ShowChar showChar = new ShowChar();
showChar.chardata = cs[i];
showChar.charWidth = charwidth;
breakResult.showChars.add(showChar);
width += charwidth + textpadding;
}
breakResult.ChartNums = cs.length;
return breakResult;
}
public static BreakResult BreakText(String text, float medsurewidth, float textpadding, Paint paint) {
if (TextUtils.isEmpty(text)) {
int[] is = new int[2];
is[0] = 0;
is[1] = 0;
return null;
}
return BreakText(text.toCharArray(), medsurewidth, textpadding, paint);
}
说明: BreakResult 是对测量结果的简单封装:
public class BreakResult {
public int ChartNums = 0;//测量了的字符数
public Boolean IsFullLine = false;//是否满一行了
public List<ShowChar> showChars = null;//测量了的字符数据
public Boolean HasData() {
return showChars != null && showChars.size() > 0;
}
}
完成了上面的工作后,我们可以实现将我们显示的数据转化为需要的数据了。
下面是我们测试显示的字符串:
String TextData = "jEh话说天下大势,分久必合,合久必分。周末七国分争,并入于秦。及秦灭之后,楚、汉分争,又并入于汉。汉朝自高祖斩白蛇而起
义,一统天下,后来光武中兴,传至献帝,遂分为三国。推其致乱之由,殆始于桓、灵二帝。桓帝禁锢善类,崇信宦官。及桓帝崩,灵帝即位,大将军窦
武、太傅陈蕃共相辅佐。时有宦官曹节等弄权,窦武、陈蕃谋诛之,机事不密,反为所害,中涓自此愈横"
+
"建宁二年四月望日,帝御温德殿。方升座,殿角狂风骤起。只见一条大青蛇,从梁上飞将下来,蟠于椅上。帝惊倒,左右急
救入宫,百官俱奔避。须臾,蛇不见了。忽然大雷大雨,加以冰雹,落到半夜方止,坏却房屋无数。建宁四年二月,洛阳地
震;又海水泛溢,沿海居民,尽被大浪卷入海中。光和元年,雌鸡化雄。六月朔,黑气十余丈,飞入温德殿中。秋七月,有虹
现于玉堂;五原山岸,尽皆崩裂。种种不祥,非止一端。帝下诏问群臣以灾异之由,议郎蔡邕上疏,以为堕鸡化,乃妇寺干政
之所致,言颇切直。帝览奏叹息,因起更衣。曹节在后窃视,悉宣告左右;遂以他事陷邕于罪,放归田里。后张让、赵忠、
封、段、曹节、侯览、蹇硕、程旷、夏恽、郭胜十人朋比为奸,号为“十常侍”。帝尊信张让,呼为“阿父”。朝政日非,以致天
下人心思乱,盗贼蜂起。";
我们需要将这段字符串转化为行数据,在初始化数据的操作,下面是初始化数据的方法initData:
List<ShowLine> mLinseData = null;
private void initData(int viewwidth, int viewheight) {
剩余10页未读,继续阅读

















安全验证
文档复制为VIP权益,开通VIP直接复制

评论0