2.ViewGroup实现上下切换view

本文介绍了一种原创的安卓视图滑动切换方法,通过重写ViewGroup实现了上下视图的平滑切换。该方法涉及自定义ViewGroup类、触摸事件处理、滚动计算等关键技术点。

(已经更新了,请看另外一篇)

一.前提

好久没玩安卓了,把上下切换view的源码跟大家分享,方法为原创,没有参考别人的作品,

可能不是最优的,但效果是一样的,原理跟SlideMenu是相似的,核心代码就是viewgroup

的重构,所以只贴出该核心的代码,及讲解,因为本人已返回去开发arm了,以前觉得简单

没有过多的解析,现在补充上...(核心代码,木有经过润泽,几十行简洁)

二.源码

 

//往这个viewgroup里add两个view就可以了

public class ViewMore extends ViewGroup {
       private Scroller scroller;
       private static float lX,lY,bX,bY,lYY;
       private static boolean Menushowflag,Menuflag=true;
       public ViewMore(Context context) {super(context);scroller = new Scroller(context);}

       public ViewMore(Context context, AttributeSet attrs) {super(context, attrs);}

       public ViewMore(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}
//1.子view的布局
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
       int viewCount = getChildCount();        //得到viewgroup的子view,该viewgroup有上下两个view
       for(int count=0;count<viewCount;count++){
       View child = getChildAt(count);
       int height = child.getMeasuredHeight();
       int width = child.getMeasuredWidth();
       child.layout(0, 0, width, height);
       }
}
public int displaynView(boolean flag){       //显示不同的view
    return flag? 1:0;
}
//2.布局时提供参数,经测试不重写无法正常给子类view布局()
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      int width = MeasureSpec.getSize(widthMeasureSpec);
      int height = MeasureSpec.getSize(heightMeasureSpec);
      setMeasuredDimension(width, height);
      Log.i("MainActivity", "--->>getChildCount:"+getChildCount());
      for (int i = 0; i < getChildCount(); i++) {
             getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
      }
}

//3.重写computeScroll(),处理scroller.startScroll扔过来的数据,(这个才是滑动view的关键方法)
@Override
public void computeScroll() {
  if(scroller.computeScrollOffset()){    //判断上次是否划完了(因为我们是把滑动view的动作分解成n个事件来处理的)
      getChildAt(displaynView(true)).layout(0, scroller.getCurrY(), getWidth(), scroller.getCurrY()+getHeight());
            getChildAt(displaynView(false)).layout(0, -getHeight()+scroller.getCurrY(), getWidth(), scroller.getCurrY());
      Log.i("Mainactivity", "CountL_"+scroller.getCurrY()+"---"+(scroller.getCurrY()+getHeight()));
            postInvalidate();
  }
  super.computeScroll();
}
public void ShowViewSroll(float currN,float currY){

//4.给computeScroll提供数据,这段代码区要简洁,不然会卡屏,因为我们要使用这个方法n次
  scroller.startScroll(0,(int)currN,0,(int)currY-(int)currN);
  invalidate();
  Menushowflag = true;
} 
public void CloseViewSroll(float currN){//关闭menu
  scroller.startScroll(0,(int)currN,0,-(int)currN);
  invalidate();
  Menushowflag = false;
  Menuflag = true;//第一页
}
public void DissViewSroll(float currN){//关闭menu
  scroller.startScroll(0,(int)currN,0,getHeight()-(int)currN);
  invalidate();
  Menushowflag = false;
  Menuflag = false;//第二页
}  

//5.核心的方法,用dispatchTouchEvent捕捉触屏事件,该方法原本是用来分发触屏事件的,经测试后用我的方法

(实现上下view动态切换时,只有该方法才能捕捉到正确的x,y坐标,不知道问题出在哪里,当初觉得可以用此方

法,所以就没去调试问题出在哪里了)
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i("Mainactivity", "dispatchTouchEvent"+event.getY());
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        lYY = event.getY();//捕捉到触屏动作,开始记录y坐标(因为我们要实现上下滑动,所以只捕捉y),初始化时使用
  break;  
  case MotionEvent.ACTION_MOVE:
   if(lYY<=40&&Menuflag){         // 判断开始触屏的位置是不是顶部且尚未滑动上下view
           bY = event.getY();           // (before y简称by )得到真正可以滑动view时的启示y
           ShowViewSroll(bY,lY);    // 开始滑动一小小段(量变到质变),by等变量要为静态的,因为我们要反复使用这些捕捉到的数据
           lY = event.getY();            //记录n毫秒后的y坐标,实现ly-by的差距,然后才能交给scroller的startScroll去滑动
   }else if(((int)getHeight()-40)<lYY&&!Menuflag){
           bY = event.getY();           //处理当上面的view滑下来后的把view滑上去事件
          ShowViewSroll(bY,lY);
          lY = event.getY(); 
   }
   break;
  case MotionEvent.ACTION_UP:
          bY = 0;
          if(Menushowflag&&(event.getY()<getHeight()/2)){        //当手指提起时判断是要划回去还是划回来
          CloseViewSroll(event.getY());
   }else if(Menushowflag&&event.getY()>=getHeight()/2){       
          DissViewSroll(event.getY());
   }
  break;     
  default:
   break;
  }
  return super.dispatchTouchEvent(event);           //把触屏事件分发回给各个组件
}

}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值