android自定義簡易英文文章閱讀器,支持點擊查單詞

本文主要說明一個簡易的英文文章閱讀器實現邏輯(^^)

一:基本邏輯

整體邏輯爲TextView+ViewFlipper
1:實現頁面中單詞點擊選中
2:實現分頁功能
3:實現簡單的翻頁動畫
原文地址

GitHub測試Demo

第一步:實現頁面中單詞點擊選中功能。

自定義閱讀頁面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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章