我知道在{x}中为android:textIsSelectable="true"
设置TextView
将显示本机文本选择弹出窗口,我一直在我的应用程序中使用它。但是当我尝试在附加到RecyclerView
的视图中设置相同的属性时,我发现它不再起作用了。
每当我尝试选择文本时,都会出现以下日志 -
TextView: TextView does not support text selection. Action mode cancelled.
我不知道为什么?为什么它适用于其他屏幕而不适用于RecyclerView
。我看了很多帖子 -
TextView with android:textIsSelectable="true" not working in listview
textview textIsSelectable="true" not working in Listview
android:textIsSelectable="true" for TextView inside Listview does not work
但后来我遇到了这篇文章 -
Android: "TextView does not support text selection. Action mode cancelled"
@hungkk
的回复对我有用。他的解决方案建议将TextView
宽度从wrap_content
更改为match_parent
。
我知道我可以这样做,但我的问题是如何解决这个问题,因为它对我来说很奇怪。而且,如果我想将宽度保持为match_parent
,那么解决方案是什么。
欢迎任何意见。
答案 0 :(得分:3)
如果您在android:descendantFocusability="blocksDescendants"
或recyclerview
中添加listview
,请将其删除。
检查完毕后
答案 1 :(得分:3)
在recyclerview的主 - 父布局中添加属性
android:descendantFocusability="beforeDescendants"
然后在rowitem布局的TextView中添加
android:textIsSelectable="true"
答案 2 :(得分:1)
似乎有很多人对此有疑问,并且有迹象表明它可能是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>
答案 3 :(得分:1)
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..
答案 4 :(得分:1)
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
yourTextView.fixTextSelection()
}
fun TextView.fixTextSelection() {
setTextIsSelectable(false)
post { setTextIsSelectable(true) }
}
答案 5 :(得分:0)
我发现RecyclerView中的TextView可以选择第一次,但是当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());
}
您可以在仿真器中调试并跟踪此代码。
答案 6 :(得分:0)
如果您的TextView
在ConstraintLayout
内,请确保宽度不是wrap_content
。使用TextView
宽度0dp
或match_parent
可以正常工作。
答案 7 :(得分:0)
我发现我必须在一段时间后设置 TextView
文本及其宽度。因此,我将此属性 (android:textIsSelectable="true"
) 放在 TextView
的 xml 布局中,并将 post{}
宽度和文本放在 onBindViewHolder
适配器的 recyclerView
方法中,如下所示:
class ContentAdapter(): ListAdapter<Verse, ContentAdapter.ViewHolder>(DiffCallback()) {
.
.
.
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = getItem(position)
holder.bind(item)
}
class ViewHolder(val binding: ItemBinding): RecyclerView.ViewHolder(binding.root) {
fun bind(item: Verse){
binding.myTextView.apply{
val params = layoutParams as ConstraintLayout.LayoutParams
params.width = 100 /*any value you want for the width of your TextView*/
post{
layoutParams = params
text = item.text
}
}
}
companion object {
fun from(parent: ViewGroup): ViewHolder{
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ItemBinding.inflate(layoutInflater, parent, false)
return ViewHolder(binding)
}
}
}
}
答案 8 :(得分:0)
最终和可行的解决方案
在你的 onBindView 中像这样写你的代码!
textView.text = "the content"
textView.setTextIsSelectable(false)
textView.post { txtContent.setTextIsSelectable(true) }
或者高级版本可以在 TextView 上编写扩展函数
fun TextView.fixTextSelection(){
setTextIsSelectable(false)
post { setTextIsSelectable(true) }
}
并像这样使用它
textView.text = "the content"
textView.fixTextSelection()