Android继承ViewGroup实现Scroll滑动效果的方法示例
本文实例讲述了android继承viewgroup实现scroll滑动效果的方法。分享给大家供大家参考,具体如下:
extends viewgroup需要重写onmeasure和onlayout方法
onmeasure方法是去测量viewgroup需要的大小以及包含的子view需要的大小。
执行完上面的方法后,再执行onlayout方法去设置子view的摆放位置。
实现scroll滑动效果需要去检测滑动速率,即要知道每个单位时间滑动了多少像素值,根据这个像素值去判断scroll滑动到下一页还是上一页。
android为我们提供了velocitytracker这个类检测速率
使用mvelocitytracker = velocitytracker.obtain();
来初始化
使用mvelocitytracker.addmovement(event);
将touch事件添加进去检测。注意每个touch事件都要添加进去
使用mvelocitytracker.computecurrentvelocity(1000);
计算每个单位时间内滑动了多少像素,这里传入的是1000ms即1s。
然后使用float pxsec = mvelocitytracker.getxvelocity();
获取到x轴滑动的像素值,必须在执行了上面方法只会再调用。
最后需要mvelocitytracker.recycle();mvelocitytracker = null;
回收掉这个对象。
完整代码是:
public class myscrolllayout extends viewgroup{ private int curscreen; private int defaultscreen = 0; private scroller mscroller; private float mlastmotionx = 0; private velocitytracker mvelocitytracker; public myscrolllayout(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); init(context); } public myscrolllayout(context context, attributeset attrs) { super(context, attrs); init(context); } public myscrolllayout(context context) { super(context); init(context); } private void init(context context){ curscreen = defaultscreen; mscroller = new scroller(context); } @override public void computescroll() { if(mscroller.computescrolloffset()){ scrollto(mscroller.getcurrx(), mscroller.getcurry()); postinvalidate(); } } @override public boolean ontouchevent(motionevent event) { // todo auto-generated method stub int action = event.getaction(); float x = event.getx(); switch (action) { case motionevent.action_down: if(mvelocitytracker==null){ mvelocitytracker = velocitytracker.obtain(); mvelocitytracker.addmovement(event); } if(!mscroller.isfinished()){ mscroller.abortanimation(); } mlastmotionx = event.getx(); break; case motionevent.action_move: float delt = mlastmotionx-x; if(iscanmove((int)delt)){ if(mvelocitytracker!=null){ mvelocitytracker.addmovement(event); } mlastmotionx = x; scrollby((int)delt, 0); } break; case motionevent.action_up: if(mvelocitytracker!=null){ mvelocitytracker.addmovement(event); mvelocitytracker.computecurrentvelocity(1000); float pxsec = mvelocitytracker.getxvelocity(); if(pxsec>600 && curscreen >0){ snaptoscreen(curscreen-1); }else if(pxsec<-600 && curscreen<getchildcount()-1){ snaptoscreen(curscreen+1); }else{ //主要是用来获取该滑动到哪个界面,最终调用的是invalid调用draw方法然后draw调用computescroll方法,然后使用scroller对象 snaptodestination(); } mvelocitytracker.recycle(); mvelocitytracker = null; } break; default: break; } return true; } private void snaptoscreen(int screen){ int whichscreen = math.max(0, math.min(screen, getchildcount()-1)); if(getscrollx()!=(whichscreen*getwidth())){ final int delat = whichscreen*getwidth() - getscrollx(); mscroller.startscroll(getscrollx(), 0, delat, 0, math.abs(delat)*2); curscreen = whichscreen; invalidate(); } } private void snaptodestination(){ int screen = (getscrollx()+getwidth()/2)/getwidth(); snaptoscreen(screen); } private boolean iscanmove(int delat){ /*if(getscrollx()<0 && delat<0){ return false; }*/ if(getscrollx()>=(getchildcount()-1)*getwidth() && delat>0){ return false; } return true; } @override protected void onlayout(boolean changed, int l, int t, int r, int b) { if(changed){ int totalheight = 0; int totalwidth = 0; int childcount = getchildcount(); for(int i=0; i<childcount; i++){ view childview = getchildat(i); int childwidth = childview.getmeasuredwidth(); int childheight = childview.getmeasuredheight(); childview.layout(totalwidth, t, totalwidth+childwidth, b); totalheight += childheight; totalwidth += childwidth; } } } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { // todo auto-generated method stub measurechildren(widthmeasurespec, heightmeasurespec); super.onmeasure(widthmeasurespec, heightmeasurespec); } }
很多人会以为viewgroup的滑动是scroller的功劳,其实不然,scroller在这里扮演的角色我认为更像是一个用来计算x和y轴单位时间移动像素的工具类而已,仅此而已没有特别的能力。
真正在这里实现scroll滑动效果的是viewgroup里的scrollto和scrollby方法,scrollto是滑动到,scrollby是滑动了。
scroller.startscroll(getscrollx(), 0, delat, 0, math.abs(delat)*2);
scroller这个类的startscroll方法传入了五个参数,分别对应,x轴起滑的偏移像素,y轴起滑的偏移像素,x轴滑动像素,y轴滑动像素,滑动过程需要的时间。
看源码如果不传时间参数的方法有个默认的时间250ms。
scroller.startscroll之后需要调用invalidate方法,然后调用viewgroup的draw方法,然后调用computescroll方法,在computescroll方法里面调用scroller.computescrolloffset()
方法去判断有没有计算完,没计算完返回true,然后scrollto方法,再postinvalidate();
方法重新执行computescroll方法。
更多关于android相关内容感兴趣的读者可查看本站专题:《android开发入门与进阶教程》、《android开发动画技巧汇总》、《android多媒体操作技巧汇总(音频,视频,录音等)》、《android基本组件用法总结》、《android视图view技巧总结》、《android布局layout技巧总结》及《android控件用法总结》
希望本文所述对大家android程序设计有所帮助。