android ScrollView实现原理,求助

能解释下ScrollView滚动显示的原理吗?就比如说你的ScollView有LinearLayout然后LinearLayout内有100个Button(id=1,2,... 能解释下ScrollView滚动显示的原理吗?就比如说你的ScollView有LinearLayout然后LinearLayout内有100个Button(id=1,2,3,4......),创建初,屏幕显示id=1~10的Button,当你向下拖的时候如何重新绘制控件,显示id=3~12的Button,我看ScrollView的源代码,并没有找到这部分功能,不知道能否解释下到底是怎么实现的,在哪里实现的?多谢!! 展开
 我来答
浅浅半4dab
推荐于2016-03-26 · TA获得超过617个赞
知道小有建树答主
回答量:352
采纳率:100%
帮助的人:375万
展开全部
视图的滚动过程,其实是在不断修改原点坐标。当手指触摸后,ScrollView会暂时拦截触摸事件,使用一个计时器。
假如在计时器到点后没有发生手指移动事件,那么ScrollView发送tracking events到被点击的subView;若是在计时器到点后发生了移动事件,那么ScrollView取消tracking自己促发滚动。
其子类可以重载
touchesShouldBegin: withEvent: inContentView: 决定自己是否接收touch事件。
pagingEnabled: 当值是YES会自动滚动到subView的边界,默认是NO。
touchesShouldCancelInContentView: 开始发送tracking messages消息给subView的时候会调用这个方法。以决定是否发送tracking messages消息到subView。假如返回NO,发送。YES则不发送。若是canCancelContentTouches属性是NO,则不调用这个方法来影响如何处理滚动手势。
ScrollView还可处理缩放和平移手势,要实现这必须实现委托viewForZoomingInScrollView:和scrollViewDidEndZooming: withView: atScale:两个方法。另外maximumZoomScale和minimumZoomScale两个属性要不一样。
常用属性介绍
maximumZoomScale 能放大的最大倍数,是浮点数。
minimumZoomScale 能缩小的最小倍数,是浮点数。
pagingEnabled 是否自动滚动到subView边界
scrollEnabled 是否可以滚动
contentSize 里面内容的大小,即可以滚动的大小,默认是0,没有滚动效果
showsHorizontalScrollIndicator 滚动时是否显示水平滚动条
showsVerticalScrollIndicator 滚动时是否显示垂直滚动条
bounces 默认是YES,就是滚动超过边界会反弹,即有反弹回来的效果。若是NO,则滚动到达边界会立刻停止
bouncesZoom 与bounces类似,只是反映在缩放效果上。
directionalLockEnabled 默认是NO,可以在垂直和水平方向同时运动。当值是YES时,视哪个方向开始则锁定另外一个方向的滚动。
indicatorStyle 滚动条的样式。总共3色:默认、黑、白
scrollIndicatorInsets 设置滚动条位置
tracking 当touch后还没有拖动的时候是YES,否则NO
zoomBouncing 当内容放大到最大或者最小的时候值是YES,否则NO
zooming 当正在缩放的时候值是YES,否则NO
decelerating 当滚动后,手指放开但还在继续滚动中。此时是YES,其它时候都是NO
decelerationRate 设置手指放开后的减速率
基本使用方法:
初始化:一般的控件初始化都是可以用alloc和init来初始化的。
UIScrollView *sv = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0,0.0,self.view.frame.size.width, 400)];
关于控件添加与初始化,建议都采用代码调用合适的初始化方法来操作,虽然IB布局能够节省时间,但不能哪过很好了解整个代码执行流程。
委托方法:UIScrollView也要指定委托对象,该委托对象的控制器同样也要遵循UIScrollViewDelegate协议,实现其相应的代理方法。
scrollViewDidScroll:
scrollViewWillBeginDragging:
scrollViewDidEndDragging:
scrollViewDidEndDecelerating:

属性作用CGPoint contentOffSet监控目前滚动的位置CGSize contentSize滚动范围的大小UIEdgeInsets contentInset视图在scrollView中的位置id<UIScrollerViewDelegate>
delegate设置协议BOOL directionalLockEnabled指定控件是否只能在一个方向上滚动BOOL bounces控制控件遇到边框是否反弹BOOL alwaysBounceVertical控制垂直方向遇到边框是否反弹BOOL alwaysBounceHorizontal控制水平方向遇到边框是否反弹BOOL pagingEnabled控制控件是否整页翻动BOOL scrollEnabled控制控件是否能滚动BOOL showsHorizontalScrollIndicator控制是否显示水平方向的滚动条BOOL
showsVerticalScrollIndicator控制是否显示垂直方向的滚动条UIEdgeInsets scrollIndicatorInsets指定滚动条在scrollerView中的位置UIScrollViewIndicatorStyle
indicatorStyle设定滚动条的样式float decelerationRate改变scrollerView的减速点位置BOOL tracking监控当前目标是否正在被跟踪BOOL dragging监控当前目标是否正在被拖拽BOOL decelerating监控当前目标是否正在减速BOOL delaysContentTouches控制视图是否延时调用开始滚动的方法BOOL canCancelContentTouches控制控件是否接触取消touch的事件float minimumZoomScale缩小的最小比例float maximumZoomScale放大的最大比例float zoomScale设置变化比例BOOL bouncesZoom控制缩放的时候是否会反弹BOOL zooming判断控件的大小是否正在改变BOOL zoomBouncing判断是否正在进行缩放反弹BOOL scrollsToTop控制控件滚动到顶部

这里把UIScrollView的几个要点总结下:
从你的手指touch屏幕开始,scrollView开始一个timer,如果:
1. 150ms内如果你的手指没有任何动作,消息就会传给subView。
2. 150ms内手指有明显的滑动(一个swipe动作),scrollView就会滚动,消息不会传给subView,这里就是产生问题二的原因。
3. 150ms内手指没有滑动,scrollView将消息传给subView,但是之后手指开始滑动,scrollView传送touchesCancelled消息给subView,然后开始滚动。
观察下tableView的情况,你先按住一个cell,cell开始高亮,手不要放开,开始滑动,tableView开始滚动,高亮取消。

delaysContentTouches的作用:
这个标志默认是YES,使用上面的150ms的timer,如果设置为NO,touch事件立即传递给subView,不会有150ms的等待。

cancelsTouches的作用:
这个标准默认为YES,如果设置为NO,这消息一旦传递给subView,这scroll事件不会再发生。
唯夜TGBUS
2013-11-26 · TA获得超过568个赞
知道小有建树答主
回答量:124
采纳率:0%
帮助的人:140万
展开全部
1. scrollview使用的时候里面都要放一个linearlayout,这是第一步。
2. 我们先不管linearlayout里面有什么,就假设有100个button,这时候linearlayout的显示长度肯定大于屏幕尺寸,这是第二步。
3. 这里就是重点了,scrollview通过实现手势监听器接口响应滑动事件,接收到滑动消息以后通过改变内部的linearlayout的margin参数来改变显示。重点就是改变其内部的linearlayout的layoutparams参数实现移动linearlayout。方法是:首先调用getLayoutParams获取linearlayout的布局参数,然后强转为MarginLayoutparams类型,然后改变它的marginTop即可实现上下滑动效果。

参考,如果感兴趣的话可以百度下滑动菜单,我是看过那个代码以后产生的灵感。
希望能够帮到你!
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
xupeiying
推荐于2016-11-24 · TA获得超过468个赞
知道小有建树答主
回答量:553
采纳率:0%
帮助的人:568万
展开全部

参考scrollView的 onTouchEvent 的。。

从 scrollBy--> invalidate();----->  p.invalidateChild(this, r);


最终通过调用 scrollView的 父View来重绘 scrollView的特定范围(r)实现的。

450             case MotionEvent.ACTION_DOWN:
451                 /*
452                 * If being flinged and user touches, stop the fling. isFinished
453                 * will be false if being flinged.
454                 */
455                 if (!mScroller.isFinished()) {
456                     mScroller.abortAnimation();
457                 }
458 
459                 // Remember where the motion event started
460                 // 记录开始的点击坐标
                    mLastMotionY = y;
461                 break;
462             case MotionEvent.ACTION_MOVE:
463                 // Scroll to follow the motion event
                 // 手指移动时的点击坐标
464                 final int deltaY = (int) (mLastMotionY - y);
                 // 更新点击坐标
                     mLastMotionY = y;
466 
                    // 往下滚动
467                 if (deltaY < 0) {
468                     if (mScrollY > 0) {
469                         scrollBy(0, deltaY);
470                     }
                    // 往上滚动
471                 } else if (deltaY > 0) {
472                     final int bottomEdge = getHeight() - mPaddingBottom;
473                     final int availableToScroll = getChildAt(0).getBottom() - mScrollY - bottomEdge;
474                     if (availableToScroll > 0) {
475                         scrollBy(0, Math.min(availableToScroll, deltaY));
476                     }
477                 }
478                 break;
追问
如果触摸点中有子控件的话,ScrollView是不会调用onTouchEvent()的,只调用了onIntercepEvent(),但是onIntercepEvent()并没有调用任何方法。。
追答
你参考一下 触摸消息派发
http://androidfanlf.blogspot.jp/2013/06/android-13-view.html.

另外 onInterceptTouchEvent 事件是确定是否打断当前view的 onTouchEvent。

所有的触摸事件,都是从顶层的view一层一层派发下来的。 所以,父控件肯定比子控件先接触到
onTouchEvent。

下面有android各个版本的源代码。
http://grepcode.com/project/repository.grepcode.com/java/ext/com.google.android/android/
开源的东西,你可以设置断点一点一点进去看一下就明白了。
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(1)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式