文本长按选中逻辑

这篇文章讲述一下,长按文本的时候:选中文字、两个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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章