在android中ScrollView嵌套ScrollView
原文:
ScrollView嵌套ScrollView
http://www.eoeandroid.com/thread-240709-1-1.html
大家好,众所周知,android 里两个相同方向的ScrollView是不能嵌套的,那要是有这样的需求怎么办?(这个需求一般都是不懂android的人提出来的)
难道就真的不能嵌套吗? 当然可以,只要你再写一个ScrollView,在里面做点脚,它就支持嵌套了。
目前做的这个只支持两个ScrollView嵌套,两个以上还有待改进,能套两个就已经能满足很多需求了,呵呵,另外现在只做了纵向scrollview的支持,横向的还没来的急做哦。
效果截图:
先上核心代码吧。代码里头我加了注释,方便大家阅读
package com.sun.shine.study.innerscrollview.view; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.ScrollView; public class InnerScrollView extends ScrollView { /** */ public ScrollView parentScrollView; public InnerScrollView(Context context, AttributeSet attrs) { super(context, attrs); } private int lastScrollDelta = 0; public void resume() { overScrollBy(0, -lastScrollDelta, 0, getScrollY(), 0, getScrollRange(), 0, 0, true); lastScrollDelta = 0; } int mTop = 10; /** * 将targetView滚到最顶端 */ public void scrollTo(View targetView) { int oldScrollY = getScrollY(); int top = targetView.getTop() - mTop; int delatY = top - oldScrollY; lastScrollDelta = delatY; overScrollBy(0, delatY, 0, getScrollY(), 0, getScrollRange(), 0, 0, true); } private int getScrollRange() { int scrollRange = 0; if (getChildCount() > 0) { View child = getChildAt(0); scrollRange = Math.max(0, child.getHeight() - (getHeight())); } return scrollRange; } int currentY; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (parentScrollView == null) { return super.onInterceptTouchEvent(ev); } else { if (ev.getAction() == MotionEvent.ACTION_DOWN) { // 将父scrollview的滚动事件拦截 currentY = (int)ev.getY(); setParentScrollAble(false); return super.onInterceptTouchEvent(ev); } else if (ev.getAction() == MotionEvent.ACTION_UP) { // 把滚动事件恢复给父Scrollview setParentScrollAble(true); } else if (ev.getAction() == MotionEvent.ACTION_MOVE) { } } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { View child = getChildAt(0); if (parentScrollView != null) { if (ev.getAction() == MotionEvent.ACTION_MOVE) { int height = child.getMeasuredHeight(); height = height - getMeasuredHeight(); // System.out.println("height=" + height); int scrollY = getScrollY(); // System.out.println("scrollY" + scrollY); int y = (int)ev.getY(); // 手指向下滑动 if (currentY < y) { if (scrollY <= 0) { // 如果向下滑动到头,就把滚动交给父Scrollview setParentScrollAble(true); return false; } else { setParentScrollAble(false); } } else if (currentY > y) { if (scrollY >= height) { // 如果向上滑动到头,就把滚动交给父Scrollview setParentScrollAble(true); return false; } else { setParentScrollAble(false); } } currentY = y; } } return super.onTouchEvent(ev); } /** * 是否把滚动事件交给父scrollview * * @param flag */ private void setParentScrollAble(boolean flag) { parentScrollView.requestDisallowInterceptTouchEvent(!flag); } }
标签:
android开发
, ScrollView
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构