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

前端 未结 7 1032
甜味超标
甜味超标 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 <i>intrinsic</i> 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.

    0 讨论(0)
  • 2021-01-01 10:03

    If you add android:descendantFocusability="blocksDescendants"​ in the recyclerview or listview, then remove it. And after check this

    0 讨论(0)
  • 2021-01-01 10:05

    There seems to be many that have problems with this and indications that it may be a bug in the Android code but I don't have a problem. This is what works for me both for an OnClickListener() and the native selection popup. (Tested on KitKat 4.4, Lollipop 5.1 and Nougat 7.1)

    In the adapter

    class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView textView;
        ImageView imageView;
    
        MyViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.my_text_view);
            imageView = (ImageView) itemView.findViewById(R.id.my_image_view);
    
            itemView.setOnClickListener(this);
            textView.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View view) {
            // this shows 'my_text_view' when the text is clicked or 
            //     'my_item' if elsewhere is clicked
            Log.d(TAG, "view = " + view.toString());
            switch (view.getId()) {
                case R.id.my_item:
                    break;
                case R.id.my_text_view:
                    break;
            }
        }
    }
    

    And my item layout

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/my_item"
        >
    
        <ImageView
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:background="@color/colorPrimary"
            android:id="@+id/my_image_view"
            />
    
        <!-- this works for me with either "match_parent" or "wrap_content" for width -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:text="My text view"
            android:textIsSelectable="true"
            android:id="@+id/my_text_view"
            />
    </LinearLayout>
    
    0 讨论(0)
  • 2021-01-01 10:06

    In the main-parent layout of recyclerview add attribute

    android:descendantFocusability="beforeDescendants"

    and then in TextView of rowitem layout add

    android:textIsSelectable="true"
    
    0 讨论(0)
  • 2021-01-01 10:06

    Add In Your RecyclerView Adapter:

    public ViewHolder(View itemView) {
                super(itemView);
                txtDate = (TextView) itemView.findViewById(R.id.txtDate);
                txtDate.setTextIsSelectable(true);
    }
    

    its worked for me..

    0 讨论(0)
  • 2021-01-01 10:10
    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
        yourTextView.fixTextSelection()
    }
    
    fun TextView.fixTextSelection() {
        setTextIsSelectable(false)
        post { setTextIsSelectable(true) }
    }
    
    0 讨论(0)
提交回复
热议问题