当前位置: 移动技术网 > 移动技术>移动开发>Android > Android继承ViewGroup实现Scroll滑动效果的方法示例

Android继承ViewGroup实现Scroll滑动效果的方法示例

2019年07月24日  | 移动技术网移动技术  | 我要评论

本文实例讲述了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程序设计有所帮助。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网