Android SlidingMenu源码初步分析,实现大致滑动效果

来源:互联网 发布:mysql 多条select语句 编辑:程序博客网 时间:2024/05/18 06:25

最近一直想搞清楚SlidingMenu是怎么做的,一来网上基本找不到相关分析,全是怎么用;二来时间比较紧,所以大致分析了一下,还望指教,正所谓授之以鱼,不如授之以渔。我在看到 这个东西的时候,有几个疑问,首先它是怎么为我的Activity界面提供滑动的,其次它的滑动是怎么实现的,还有后一个界面是怎么出来的。
下到源码后,里面有SlidingMenuActivity,SlidingMenuFragmentActivity等类,这些类都有SlidingMenuActivityHelper,这个helper主要管理SlidingMenu,所以SlidingMenu类是精华所在,这个类继承于RelativeLayout,包含CustomViewAbove,CustomViewBehind(这两个类的名字似乎说明了什么)继承至ViewGroup,我等会再说这两个关键类,从大致结构来看,它是先添加了CustomViewAbove,CustomViewBehind,然后在添加到Activity里面去,这里面代码较多,我简单贴一下:(这些不是重点)

public SlidingMenu(Activity activity, int slideStyle) {        this(activity, null);        this.attachToActivity(activity, slideStyle);    }    public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        LayoutParams behindParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);        mViewBehind = new CustomViewBehind(context);        addView(mViewBehind, behindParams);        LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);        mViewAbove = new CustomViewAbove(context);        addView(mViewAbove, aboveParams);        ...        }

这里先说第一个它是怎么把我的Activity对应界面添加的,注意到上面构造方法之后还有个一方法,就是attachToActivity,这个方法里面做了三件事,第一将Activity上窗口的界面移除,再将自己也就是SlidingMenu添加到这个窗口上,最后将移除的界面注入(就是set)到CustomViewAbove实例里面(为什么这么多ViewGroup?SlidingMenu添加CustomViewAbove,CustomViewAbove再去添加View)。从而,我们看到的界面已经不再是开始在Activity setContent的界面了,而是SlidingMenu,显示的是CustomViewAbove。为什么不是CustonViewBehind?注意在SlidingMenu初始化时添加这两个View的先后顺序,从形式上看,这个效果误导了我,它似乎是将Behind添加在左边或右边,然后将Above放在中间,后来我发现不是这样,现在大家可以从名字上来看,Above上面,Behind后面,它们是层叠的关系。

重点来了,它是怎么滑动的,不用说,这个滑动的事件肯定与OnTouchEvent有关,它自己是没有覆盖OnTouchEvent方法的,那么肯定在CustomViewAbove或CustomViewBehind,在Above里面找到了关键代码,在此之前还有一个onInterceptTouchEvent(),拦截所以的触摸事件,大家可以去百度一下。在OnTouchEvent方法里面根据getAction的不同来区分不同的事件,在ACTION_MOVE里面看到了一行最关键的代码:scrollTo((int) scrollX, getScrollY());看到这里我似乎明白了,Above是当前界面响应OnTouchEvent,自己根据方向去滑动,多出来的空间在然Behind滑出来(其实Behind没有滑动,Behind在Above的下面,Above滑走了,Behind自然显示出来了)
现在问题基本差不多了,就是这个scrollTo()或者srcollBy(),啥也别说赶紧谢谢代码来测试一下,一测试就出问题了!
现在问大家一个问题一个Button执行了scrollTo方法,真的是Button移动了吗?其实不然而是Button里面的内容移动了,这是一个很奇怪的地方,也就是说如果你想去移动一个Button,你需要调用其父容器的scrollTo方法,下面的btn是放在rl里面的,如:

        rl=(RelativeLayout) findViewById(R.id.id_ll);        btn=(Button) findViewById(R.id.id_btn);        msg=(MyScrollViewGroup) findViewById(R.id.id_my);        btn.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                rl.scrollBy(10, 10);                // try to add the code below and run//              btn.scrollBy(10, 10);            }        });

我试着去解释这个事情,但是在跟踪源码时遇到了attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);这行代码,跟踪不下去了。这里我自己解释一下(不保证一定正确),在调用scrollTo()的时候,改变了mScrollX和mScrollY的值,然后上面代码让View重绘,在ViewGroup重绘的时候通过mScrollX和Y去改变子View的位置。这里写图片描述
这里写图片描述
下面上一个我写的小例子。还有一个Behind的打开和关闭动画我没有做,大家可以看看Scroller.
下载地址:http://download.csdn.net/detail/q421505375/8621753

0 0
原创粉丝点击