Fragment内Scrollable TextView区域无法点击,求原因解析
嘿,这个问题我之前做项目时也碰到过!核心原因很简单:你的可滚动TextView把触摸事件“抢”走了。
当你把TextView设置成可滚动状态(不管是通过代码加ScrollingMovementMethod,还是用ScrollView包裹),这个视图会优先把触摸事件截留下来,用来处理滚动逻辑。这样一来,点击事件就没法传递到Fragment的根布局了,所以滚动TextView所在的区域点了没反应。
下面给你几个实用的解决方案,既能保留TextView的滚动功能,又能让整个Fragment区域都能响应点击:
方案1:自定义一个可点击的滚动TextView
写个继承自TextView的自定义控件,让它处理完滚动事件后,把点击事件传给父布局:
public class ClickableScrollTextView extends AppCompatTextView { public ClickableScrollTextView(Context context) { super(context); init(); } public ClickableScrollTextView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setMovementMethod(new ScrollingMovementMethod()); // 保留滚动能力 } @Override public boolean onTouchEvent(MotionEvent event) { // 先让TextView处理滚动相关的触摸事件 boolean handled = super.onTouchEvent(event); // 如果是抬手动作(说明是点击),通知父布局处理点击 if (event.getAction() == MotionEvent.ACTION_UP) { if (getParent() instanceof View) { ((View) getParent()).performClick(); } } return handled; } }
之后把你布局里的滚动TextView换成这个自定义控件就行,记得替换成自己项目的包名:
<com.your.app.package.ClickableScrollTextView android:id="@+id/tv_scrollable" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="vertical" />
方案2:不用自定义控件,直接给滚动TextView加触摸监听
如果不想改控件,直接在Fragment的代码里给滚动TextView加个OnTouchListener,判断是点击动作就触发根布局的点击:
// 先找到滚动TextView和Fragment的根布局 TextView scrollableTv = view.findViewById(R.id.tv_scrollable); View fragmentRoot = view.findViewById(R.id.fragment_root); // 开启TextView的滚动功能 scrollableTv.setMovementMethod(new ScrollingMovementMethod()); // 设置触摸监听 scrollableTv.setOnTouchListener((v, event) -> { if (event.getAction() == MotionEvent.ACTION_UP) { // 手动触发根布局的点击事件 fragmentRoot.performClick(); } // 返回false,让TextView继续处理滚动逻辑 return false; });
这里要注意给Fragment的根布局加个idfragment_root,并且你已经给根布局设置好点击事件啦。
方案3:如果滚动TextView不需要单独响应点击,直接禁止它拦截非滚动事件
要是你的滚动TextView只需要滚动,不需要自己处理点击,那可以这么写:
scrollableTv.setMovementMethod(new ScrollingMovementMethod()); scrollableTv.setOnTouchListener((v, event) -> { // 滚动时让父布局别抢事件 v.getParent().requestDisallowInterceptTouchEvent(true); if (event.getAction() == MotionEvent.ACTION_UP) { // 抬手时放开拦截,同时触发父布局点击 v.getParent().requestDisallowInterceptTouchEvent(false); ((View)v.getParent()).performClick(); } // 让TextView自己处理滚动事件 return v.onTouchEvent(event); });
另外提一句:如果你是用ScrollView包裹TextView实现的滚动,问题本质是一样的——ScrollView会拦截触摸事件,这时候把上面代码里的TextView换成ScrollView就行,逻辑完全通用。
内容的提问来源于stack exchange,提问作者parfum
相关产品推荐
相关产品推荐

