Android Kotlin中触摸指定View(如TradingView图表)时如何禁用页面滚动?
触摸特定View时禁用ScrollView滚动(解决TradingView图表滚动不流畅问题)
嘿,这个问题我之前做TradingView嵌入ScrollView的时候也踩过坑!本质就是要让ScrollView在触摸到图表的时候“放手”,别抢触摸事件,这样图表就能自己处理X/Y轴的滚动了。下面给你两个实用的Kotlin实现方案:
方案一:自定义ScrollView(推荐,逻辑更清晰)
我们可以自己写个ScrollView的子类,重写事件拦截的方法,判断当前触摸的是不是目标图表,如果是就不拦截事件,让图表自己处理。
class CustomScrollView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : ScrollView(context, attrs, defStyleAttr) { private var targetView: View? = null // 传入需要禁用ScrollView滚动的目标View(比如你的TradingView图表) fun setTargetView(view: View) { this.targetView = view } override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { targetView?.let { chartView -> // 获取图表在屏幕上的坐标范围 val location = IntArray(2) chartView.getLocationOnScreen(location) val chartLeft = location[0] val chartTop = location[1] val chartRight = chartLeft + chartView.width val chartBottom = chartTop + chartView.height // 判断当前触摸点是不是在图表范围内 val touchX = ev.rawX.toInt() val touchY = ev.rawY.toInt() val isTouchOnChart = touchX in chartLeft..chartRight && touchY in chartTop..chartBottom // 如果触摸在图表上,就不拦截事件,让图表自己处理滚动 if (isTouchOnChart) { return false } } // 其他情况正常让ScrollView处理滚动 return super.onInterceptTouchEvent(ev) } }
然后在你的Fragment/Activity里这么用:
// 先找到自定义ScrollView和TradingView图表实例 val scrollView = view.findViewById<CustomScrollView>(R.id.your_scroll_view) val tradingChart = view.findViewById<View>(R.id.your_trading_view_chart) // 设置目标View,这样触摸图表时ScrollView就会暂停滚动 scrollView.setTargetView(tradingChart)
方案二:给图表设置触摸监听(更轻量,不用自定义View)
如果不想改ScrollView的代码,直接给TradingView图表加个触摸监听,告诉ScrollView什么时候别抢事件就行。
val tradingChart = view.findViewById<View>(R.id.your_trading_view_chart) val scrollView = view.findViewById<ScrollView>(R.id.your_scroll_view) tradingChart.setOnTouchListener { _, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { // 手指按下图表时,让ScrollView别拦截触摸事件 scrollView.requestDisallowInterceptTouchEvent(true) } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { // 手指抬起或触摸取消时,恢复ScrollView的滚动能力 scrollView.requestDisallowInterceptTouchEvent(false) } } // 返回false,让图表自己处理触摸逻辑(如果返回true,图表可能接收不到事件) false }
小提醒
- 如果你是在Fragment里用,记得在
onViewCreated方法里初始化这些视图,别在onCreate里找,容易空指针。 - 方案二里一定要返回
false,不然TradingView自己的滚动逻辑会被拦截掉,还是不流畅。
我当时用方案二快速解决了问题,图表的X/Y轴滚动立刻就流畅了,亲测有效😎
内容的提问来源于stack exchange,提问作者JoshSY




