Подтвердить что ты не робот

"android: textIsSelectable =" true "не работает для TextView в RecyclerView

Я знаю, что установка android:textIsSelectable="true" в xml для TextView покажет всплывающее окно с исходным текстом, и я использовал его в своем приложении. Но я обнаружил, что он больше не работает, когда я пытаюсь установить тот же атрибут в представлении, прикрепленном к RecyclerView. Всякий раз, когда я пытаюсь выбрать текст, появляется следующий журнал -

TextView: TextView does not support text selection. Action mode cancelled.

И я не знаю почему? Почему он работает на других экранах, а не с RecyclerView. Я читаю несколько сообщений -

TextView с android: textIsSelectable = "true" не работает в списке просмотров

textview textIsSelectable = "true" не работает в Listview

android: textIsSelectable = "true" для TextView внутри Listview не работает

Но потом я столкнулся с этим сообщением -

Android: "TextView не поддерживает выбор текста. Действие отменено"

И ответ для меня был @hungkk. Его решение предложило, чтобы ширина TextView изменилась на wrap_content от match_parent.

Я знаю, что могу это сделать, но мой вопрос заключается в том, как это устранило проблему, потому что это выглядит странно для меня. А также, каково решение, если я хочу, чтобы ширина была match_parent.

Любые входы приветствуются.

4b9b3361

Ответ 1

Если добавить android:descendantFocusability="blocksDescendants"​ в recyclerview или listview, а затем удалить его. И после проверки это

Ответ 2

В макете основного родителя атрибута recyclerview add

android:descendantFocusability="beforeDescendants"

а затем в TextView макета rowitem добавьте

android:textIsSelectable="true"

Ответ 3

Кажется, что есть много проблем с этим и признаки того, что это может быть ошибка в коде Android, но у меня нет проблем. Это то, что работает для меня как для OnClickListener(), так и для всплывающего всплывающего окна. (Протестировано на KitKat 4.4, Lollipop 5.1 и Nougat 7.1)

В адаптере

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;
        }
    }
}

И мой макет элемента

<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>

Ответ 4

Добавьте в свой адаптер RecyclerView:

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

это сработало для меня..

Ответ 5

Я обнаружил, что TextView в RecyclerView можно выбрать первый раз, но когда ViewHolder был переработан или адаптер notifyDataSetChanged, все текстовое представление не может быть выбрано. И я обнаружил, что это решение работает на меня.

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

Зачем это делать? потому что я отладил и нашел некоторую логику в исходном коде Android:

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());
}

Вы можете отлаживать в эмуляторе и отслеживать этот код.