问题:除非应用程序暂停(例如,在切换应用程序之后),否则选择工作正常.一旦应用程序处于活动状态,选择将停止工作,并在日志中收到以下消息:
W/TextView: TextView does not support text selection. Selection
cancelled.
我的设置:
我有一个带有CoordinatorLayout的Activity和一个带有TextView的Fragment,它包含在RelativeLayout中,如下所示:
<TextView android:id="@+id/text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:scrollbars="vertical" />
在Java代码中我必须这样做:
textView.setMovementMethod(new ScrollingMovementMethod()); textView.setTextIsSelectable(true); textView.setFocusable(true); textView.setFocusableInTouchMode(true);
因为根据this,this和this问题,这是唯一的工作方式.
编辑:
问题出在以下调用中
textView.setMovementMethod(new ScrollingMovementMethod());
如果我删除它有效,但我无法理解.
重现问题的最小步骤:
1)使用以下布局使用TextView创建一个空的Activity.
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text_view" android:text="Some very very very long text..." android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:scrollbars="vertical" /> </android.support.design.widget.CoordinatorLayout>
2)在onStart()方法中设置TextView的可见性参数.
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override protected void onStart() { super.onStart(); TextView textView = findViewById(R.id.text_view); textView.setMovementMethod(new ScrollingMovementMethod()); textView.setTextIsSelectable(true); textView.setFocusable(true); textView.setFocusableInTouchMode(true); } }
3)尝试在暂停应用程序之前和之后使用TextView上的上下文菜单.
编辑2:
删除setMovementMethod(new ScrollingMovementMethod())解决了我的问题,之后功能正常.但是我不太清楚为什么它被添加了,我担心如果我删除它会制造一些东西.知道为什么人们可能会将ScrollingMovementMethod与android结合使用:scrollbars =“vertical”.可能是xml在某些情况下不起作用?想法?我仍然有兴趣使用ScrollingMovementMethod制动器选择功能?
解决方法
android:scrollbars =“vertical”行说如果这个View得到“scrollablility”(例如通过上面的移动方法)那么UI应该只显示垂直滚动条.来自docs:
Defines which scrollbars should be displayed on scrolling or not.
它是View
个文档,特别是TextView,因为很少扩展“种类”的视图可以获得“scolllability”,包括所有ViewGroups,如ScrollView,ListView,RecyclerView等.
最后这行在你的代码中做了什么?在setTextIsSelectable
内你有这条线:
setMovementMethod(selectable ? ArrowKeyMovementMethod.getInstance() : null);
所以实际上它的覆盖移动方法你在自己的代码中设置了几行.我敢打赌,前段时间你的TextView“可以自行分辨”,而且有一天,一些聪明的家伙重写了这个并将TextView放入例如XML中的ScrollView和移动方法保留在代码中.
textIsSelectable工作直到Activity暂停,因为恢复后你(再次)设置ScrollableMovementMethod,但是在setTextIsSelectable里面你有
if (mEditor.mTextIsSelectable == selectable) return;
您在活动暂停之前首次运行时设置了mTextIsSelectable标志,并且此标志已恢复,因此不会触发下面的代码(因此不会使用ArrowKeyMovementMethod重置移动方法,并且您的ScrollableMovementMethod保持不变).所以回答问题,这条线在你的代码中做了什么:它在暂停和恢复Activity之后打破了“可选择性”,除此之外什么都没有
来自ScrollingMovementMethod
和ArrowKeyMovementMethod
的消息来源:仅在ArrowKeyMovementMethod(在上面的setTextIsSelectable中设置为移动方法)中,您已经覆盖了onTouchEvent方法,并在其中部分处理选择的行
编辑:请注意,在setTextIsSelectable中你设置了“focusability”,所以这些行是不必要的:
textView.setFocusable(true); textView.setFocusableInTouchMode(true);
所以你可以将你的代码缩短到一行:
textView.setTextIsSelectable(true);
android:textIsSelectable="true"