“android:textIsSelectable=”true" not working for TextView in RecyclerView

前端 未结 7 1082
甜味超标
甜味超标 2021-01-01 09:31

I know that setting android:textIsSelectable=\"true\" in xml for the TextView will show the native text selection popup and I\'ve been using that i

7条回答
  •  無奈伤痛
    2021-01-01 10:01

    I found TextView in RecyclerView can select first time ,but when ViewHolder was recycled or adapter notifyDataSetChanged,all text view will can't be selected. And I found this solution was working for me.

    yourTextView.setText("your text");
    yourTextView.setTextIsSelectable(false);
    yourTextView.measure(-1, -1);//you can specific other values.
    yourTextView.setTextIsSelectable(true);
    

    Why do this? because I have debugged and found some logic in android source code:

    TextView.java:

    public void setTextIsSelectable(boolean selectable) {
        if (!selectable && mEditor == null) return; // false is default value with no edit data
    
        createEditorIfNeeded();
        if (mEditor.mTextIsSelectable == selectable) return;
    
        mEditor.mTextIsSelectable = selectable;
        setFocusableInTouchMode(selectable);
        setFocusable(FOCUSABLE_AUTO);
        setClickable(selectable);
        setLongClickable(selectable);
    
        // mInputType should already be EditorInfo.TYPE_NULL and mInput should be null
    
        setMovementMethod(selectable ? ArrowKeyMovementMethod.getInstance() : null);
        setText(mText, selectable ? BufferType.SPANNABLE : BufferType.NORMAL);
    
        // Called by setText above, but safer in case of future code changes
        mEditor.prepareCursorControllers();
    }
    

    Editor.java

    void prepareCursorControllers() {
        boolean windowSupportsHandles = false;
    
        ViewGroup.LayoutParams params = mTextView.getRootView().getLayoutParams();
        if (params instanceof WindowManager.LayoutParams) {
            WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
            windowSupportsHandles = windowParams.type < WindowManager.LayoutParams.FIRST_SUB_WINDOW
                    || windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW;
        }
    
        boolean enabled = windowSupportsHandles && mTextView.getLayout() != null;
        mInsertionControllerEnabled = enabled && isCursorVisible();
        **mSelectionControllerEnabled = enabled && mTextView.textCanBeSelected();**
    
        if (!mInsertionControllerEnabled) {
            hideInsertionPointCursorController();
            if (mInsertionPointCursorController != null) {
                mInsertionPointCursorController.onDetached();
                mInsertionPointCursorController = null;
            }
        }
    
        if (!mSelectionControllerEnabled) {
            stopTextActionMode();
            if (mSelectionModifierCursorController != null) {
                mSelectionModifierCursorController.onDetached();
                mSelectionModifierCursorController = null;
            }
        }
    }
    

    ---> TextView.java

    /**
     * Test based on the intrinsic charateristics of the TextView.
     * The text must be spannable and the movement method must allow for arbitary selection.
     *
     * See also {@link #canSelectText()}.
     */
    boolean textCanBeSelected() {
        // prepareCursorController() relies on this method.
        // If you change this condition, make sure prepareCursorController is called anywhere
        // the value of this condition might be changed.
        if (mMovement == null || !mMovement.canSelectArbitrarily()) return false;
        return isTextEditable()
                || (isTextSelectable() && mText instanceof Spannable && isEnabled());
    }
    

    you can debug in Emulator and trace this code.

提交回复
热议问题