Ответ 1
Если добавить android:descendantFocusability="blocksDescendants"
в recyclerview
или listview
, а затем удалить его. И после проверки это
Я знаю, что установка 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
.
Любые входы приветствуются.
Если добавить android:descendantFocusability="blocksDescendants"
в recyclerview
или listview
, а затем удалить его. И после проверки это
В макете основного родителя атрибута recyclerview add
android:descendantFocusability="beforeDescendants"
а затем в TextView макета rowitem добавьте
android:textIsSelectable="true"
Кажется, что есть много проблем с этим и признаки того, что это может быть ошибка в коде 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>
Добавьте в свой адаптер RecyclerView:
public ViewHolder(View itemView) {
super(itemView);
txtDate = (TextView) itemView.findViewById(R.id.txtDate);
txtDate.setTextIsSelectable(true);
}
это сработало для меня..
Я обнаружил, что 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());
}
Вы можете отлаживать в эмуляторе и отслеживать этот код.