本文主要說明一個簡易的英文文章閱讀器實現邏輯(^^)
一:基本邏輯
整體邏輯爲TextView+ViewFlipper
1:實現頁面中單詞點擊選中
2:實現分頁功能
3:實現簡單的翻頁動畫
原文地址
第一步:實現頁面中單詞點擊選中功能。
自定義閱讀頁面ReaderPage extends TextView
因爲要有單詞點擊事件,需要設置setMovementMethod(LinkMovementMethod.getInstance());
但這樣會有TextView的滑動和點擊單詞文本的衝突。 原因及解決方案地址
1獲取文本分詞
/**
*英文文本獲取所有單詞
*/
public List<String> splitWord(@NonNull String text) {
if (TextUtils.isEmpty(text)) {
return new ArrayList<>();
}
List<String> words= new ArrayList<>();
Pattern pattern = Pattern.compile("[a-zA-Z-']+");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
words.add(matcher.group(0));
}
return words;
}
2獲取單詞在文本中的位置
private List<WordInfo> getWordInfos(String text) {
List<String> words = splitWord(text);
List<WordInfo> wordInfos = new ArrayList<>(words.size());
int startIndex = 0;
for (int i = 0; i < words.size(); i++) {
String word = words.get(i);
int start = text.indexOf(word, startIndex);
int end = start + word.length();
startIndex = end;
WordInfo wordInfo = new WordInfo();
wordInfo.setStart(start);
wordInfo.setEnd(end);
wordInfo.setWord(word);
wordInfos.add(wordInfo);
}
return wordInfos;
}
3設置單詞點擊事件
private void setClickableSpans() {
for (int i = 0; i < mWordInfos.size(); i++) {
WordInfo info = mWordInfos.get(i);
mSpannableString.setSpan(new WordClickableSpan(info),
info.getStart(), info.getEnd(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
第二步:實現分頁功能
閱讀器 Reader extends ViewFlipper
通過readerPage 對所用文本進行測量,計算總行數和每頁顯示行數,可以得到總頁數。(此方法不適合數據量特別多的文本,有合適的思路,請多多指教)
耗時操作,建議在新線程中處理
public void computeBookTextInfo(Context context, String allText {
ReaderPage readerPage = new ReaderPage (context);
readerPage .setText(allText );
//這裏根據實際需求進行測量
readerPage .measure(widthMeasureSpec, heightMeasureSpec);
Layout layout = readerPage .getLayout();
int offset = readerPage .getMeasuredHeight() - readerPage .getPaddingBottom() - readerPage .getPaddingTop();
//總行數
mAllLines = layout.getLineCount();
//每一頁行數
mPerPageLines = layout.getLineForVertical(offset) - 1;
//總頁數
mTotalPages= mPerPageLines == 0 ? 0 : mAllLines / mPerPageLines + 1;
if (mTotalPages<= 0) {
return;
}
mPageInfos = new ArrayList<>(mTotalPages);
int start = 0;
int endLine;
//計算每頁信息
for (int index = 0; index < mTotalPages; index++) {
PageInfo pageInfo = new PageInfo();
pageInfo.setPageNum(index);
pageInfo.setStart(start);
if (index + 1 < mTotalPages) {
endLine = mPerPageLines * (index + 1) - 1;
start = layout.getLineStart(endLine + 1);
} else {
endLine = mAllLines - 1;
}
pageInfo.setEnd(layout.getLineEnd(endLine));
pageInfo.setText(allText .substring(pageInfo.getStart(), pageInfo.getEnd()));
mPageInfos.add(pageInfo);
}
}
第三步:實現簡單的翻頁動畫
父類爲ViewFlipper,根據滑動事件進行左滑右滑,滑進滑出動畫的動態添加。
1處理點擊事件在子View中
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = event.getX();
mDownY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
if (event.getX() - mDownX > THRESHOLD) {
fromLeftToRight();
} else if (event.getX() - mDownX < -THRESHOLD) {
romRightToLeft();
}
break;
default:
}
return super.onInterceptTouchEvent(event);
}
2點擊事件在自身
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = event.getX();
mDownY = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
if (Math.abs(event.getX() - mDownX) < mTouchSlop) {
if (mListener != null) {
mListener .onClickWord(this, Empty);
}
} else {
if (event.getX() - mDownX > THRESHOLD) {
fromLeftToRight();
} else if (event.getX() - mDownX < -THRESHOLD) {
fromRightToLeft();
}
}
break;
default:
}
return super.onTouchEvent(event);
}