文本長按選中邏輯

這篇文章講述一下,長按文本的時候:選中文字、兩個selection的圖片如何加載的、複製粘貼(floatingtoolbar)如何顯示的。

一切都是從textview開始的,在textview之前的就不分析了。


一、長按文本觸發

長按文本,則必然是textview的performLongClick

    @Override
    public boolean performLongClick() {
        boolean handled = false;

        if (mEditor != null) {
            mEditor.mIsBeingLongClicked = true;
        }

        if (super.performLongClick()) {
            handled = true;
        }

        if (mEditor != null) {
            handled |= mEditor.performLongClick(handled);//調用到editor的長按處理
            mEditor.mIsBeingLongClicked = false;
        }
二、核心處理:Editor中

    public boolean performLongClick(boolean handled) {
        // Long press in empty space moves cursor and starts the insertion action mode.根據註釋,看到,這個if裏面是處理:長按沒有文本的空白地方的處理邏輯
        if (!handled && !isPositionOnText(mLastDownPositionX, mLastDownPositionY) &&
                mInsertionControllerEnabled) {//判斷點擊的位置(x,y)是否在text上
            final int offset = mTextView.getOffsetForPosition(mLastDownPositionX,
                    mLastDownPositionY);//根據點擊位置(x,y)獲取offset位置,在Layout.java中的函數:getOffsetForHorizontal具體實現
            Selection.setSelection((Spannable) mTextView.getText(), offset);//設置selection,關於selection不在詳細講述,這裏沒人改過,比較穩定。
            getInsertionController().show();//這裏就是顯示圖片,所調用code。---需要後需分析A.
            mIsInsertionActionModeStartPending = true;
            handled = true;
        }

        if (!handled && mTextActionMode != null) {//選中文本範圍的邏輯
            if (touchPositionIsInSelection()) {//是否有文本可以選中,有啓動拖拽;這裏也是見在左右兩個範圍圖片的邏輯。 ---需要分析B
                startDragAndDrop();
            } else {//拖拽不再第一次選中的文本範圍內,重新開始選擇單詞並開始拖拽
                stopTextActionMode();
                selectCurrentWordAndStartDrag();//初始化
            }
            handled = true;
        }

        // Start a new selection
        if (!handled) {
            handled = selectCurrentWordAndStartDrag();
        }

        return handled;
    }

看一下,選中範圍的兩個圖片:分析A  getInsertionController().show()

    InsertionPointCursorController getInsertionController() {
 ...

        if (mInsertionPointCursorController == null) {
            mInsertionPointCursorController = new InsertionPointCursorController();//這裏new的

            final ViewTreeObserver observer = mTextView.getViewTreeObserver();
            observer.addOnTouchModeChangeListener(mInsertionPointCursorController);
        }

        return mInsertionPointCursorController;
    }
new對象是InsertionPointCursorController,那麼getInsertionController().show()
就是下面這段邏輯:

        public void show() {
            getHandle().show();//這裏show,那麼拿圖片的邏輯肯定在getHandle裏了
...
        }
        private InsertionHandleView getHandle() {
            if (mSelectHandleCenter == null) {
                mSelectHandleCenter = mTextView.getContext().getDrawable(
                        mTextView.mTextSelectHandleRes);//這裏就是拿圖片了,根據名字可以看出,這裏是中間的圖片,也就是移動cursor時候使用的圖片
            }
            if (mHandle == null) {
                mHandle = new InsertionHandleView(mSelectHandleCenter);
            }
            return mHandle;
        }

看一下mTextSelectHandleRes的定義,在textview中

case com.android.internal.R.styleable.TextView_textSelectHandle:
                mTextSelectHandleRes = a.getResourceId(attr, 0);
如果有定義主題只是: 點擊打開鏈接,就明白,這裏是style.xml中的定義

/frameworks/base/core/res/res/values/styles.xml

489    <style name="Widget.TextView">
490        <item name="textAppearance">?attr/textAppearanceSmall</item>
491        <item name="textSelectHandleLeft">?attr/textSelectHandleLeft</item>//左邊的圖片
492        <item name="textSelectHandleRight">?attr/textSelectHandleRight</item>//右邊
493        <item name="textSelectHandle">?attr/textSelectHandle</item>//這是中間的
themes_holo.xml

590        <!-- Text selection handle attributes -->
591        <item name="textSelectHandleLeft">@drawable/text_select_handle_left_material</item>
592        <item name="textSelectHandleRight">@drawable/text_select_handle_right_material</item>
593        <item name="textSelectHandle">@drawable/text_select_handle_middle_material</item>
這裏就可以看到圖片的定義了.


就是上面這三張。

下面分析下B,做與兩個圖片夾在的邏輯:

editor中的函數:

    private boolean touchPositionIsInSelection() {
...

        SelectionModifierCursorController selectionController = getSelectionController();//加載兩張圖片
...

        return ((minOffset >= selectionStart) && (maxOffset < selectionEnd));
    }

    SelectionModifierCursorController getSelectionController() {
        if (!mSelectionControllerEnabled) {
            return null;
        }

        if (mSelectionModifierCursorController == null) {
            mSelectionModifierCursorController = new SelectionModifierCursorController();

            final ViewTreeObserver observer = mTextView.getViewTreeObserver();
            observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
        }

        return mSelectionModifierCursorController;
    }




發佈了71 篇原創文章 · 獲贊 22 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章