SlidingMenu 合成原理分析

       碰巧用到了 SlidingMenu和ViewPagerIndicator,为了做效果,研究了一下两个框架的原理。ViewPagerIndicator改的源码比较多,放下次说明。 不太会用代码段,最后用了截图,感觉自己瞬间土了不少。
SlidingMenu的使用步骤如下:
1.  自己创建一个Activity,继承SlidingFragmentActivity,使用自己的一个空视图,指定一个ID
2.  创建一个空视图,使用setBehindContentView,同样指定一个ID
3.  创建2 Fragment,分别repalce到对应的id上。 一个就是所谓的“首页”,一个就是所谓的“侧滑菜单”。

通过以上步骤,侧滑菜单的架构就完成了,上个源码 。
/**
 * 主页面容器
 * 
 * @author  Michael Chen 140602
 */
public class MainActivity extends SlidingFragmentActivity
{
    /**
     * 侧边菜单对象
     */
    private SlidingMenu slidingMenu;
    
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);  // 右边的“主页”布局
        initMenu();
    }
    
    private void initMenu()
    {
        setBehindContentView(R.layout.activity_main_menu_container); //设置侧滑菜单容器
        slidingMenu = getSlidingMenu();    // 获取SlidingMenu对象
        slidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
        slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
        
        // 将菜单fragment设置到behindview上 
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        MenuFragment menuFragment = new MenuFragment();
        fragmentTransaction.replace(R.id.menu, menuFragment);
        
         // 将主页fragment设置到主页布局上
        MainTabContainerFragment mainTabFragment = new MainTabContainerFragment();
        fragmentTransaction.replace(R.id.container, mainTabFragment);
        fragmentTransaction.commit();
        
    }
        
}

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</FrameLayout>

activity_main_menu_container.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/menu"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
</LinearLayout>

提问: 
1. 2个fragment,1个activity,为什么2个就能一起拖动了?onTouch事件是从activity开始分发的,但是却能和fragment同时出发?
2. 设置的behindView怎么和主界面关联起来的? 
3. 前提:我没有使用lib的方式使用,而是抽取源码到工程中,此时必须导入一个叫slidingmenu_main的layout ,为什么SlidingMenu就一定要一个layout?

解答:
        第一步,先看SlidingMenu类 ,为什么?回到我代码中的initMenu方法,有很多和SlidingMenu相关的参数都是用这个对象设置的,所以先看它。


         可以看到,SlidingMenu是一个相对布局,想起第3个问题,那个布局干什么用的?-->第一反应,合成视图!
既然是ViewGroup,那么就先找实现最多的 那个构造方法。



        OK,注意看图中框起来的部分,先假定CustomViewBehind和CustomViewAbove两个对象是空的ViewGroup(空是假设,他们其实有做事情),他们先后被添加到了SlidngMenu这个 布局上,那么就应该是现在这么一个情况: 三层是完全一样大小,然后叠起来的(RelativeLayout是后加的View会叠加在前面的View上的)。


        嗯~ 到这里看上去好像什么都不错,但是出现了一个新问题,添加上去的View都是空的。那就回到了问题1和2,依旧是试图关联的问题,下面就讲讲SlidingMenu的一个偷天换日的动作。

       这里插一句,Activity有两个平时可能不太会用到的回调方法,onPostResume,onPostCreate。SlidingMenu主要是用到了
onPostCreate:after onStart() and onRestoreInstanceState(Bundle) have been called。

      通过查看SlidingFragmentActivity的onCreate和setContentView就会发现,SlidingFragmentActivity在这两个方法中做了些非常重要的事情,而帮手是一个叫SlidingActivityHelper类。
       onCreate:创建了SlidingMenu对象
       setContent:把我们设置布局给了SlidingHelper的aboveview 
       在onPostCreate之前,我们必须调用set
setBehindContentView,来设置菜单的部分
       onPostCreate:偷天换日,整合布局。

onCreate :  此时我们拥有了整个视图最大的容器--SlidingMenu.







setContent: 将我们设置给Activity的视图注册给了helper,helper自然很开心的把主页作为顶层视图存了起来(above)。




       在我们初始化自己的Activity的时候,是需要在这段时间之内调用setBehindContentView来设置“菜单”部分的视图的,因为前面
也说到,SlidingMenu是在onPostCreate时进行的最终视图合成。(如果你不调,Slindingmenu也会报一个错误给你。)setBehindContentView方法很简单,就是单纯的把我们给的layout实例成视图,然后添加到了前面的CustomViewBehind上,轻松的合成上去了。

     



onPostCreate:在Activity完全展示出来的时候,SlidingMenuHelper 将3层最终合成在了一起。




偷天换日:全屏替换或者只是局部替换都只是看心情的事情了。  视图中addView的对象都是SlidingMenu,So...
1. 全屏:把DecorView拿出来,找出根节点(就是整个屏幕),把它设置给Slindingmenu的above,然后把原来的从PhoneWidow上删掉,把自己加进去。嗯~ 全屏都能成了移动的一部分
2. 部分:那就是找到activity内容的根节点,actionbar什么的都还在,不动。后面一样。




总结成一张图:


        至此,整个替换和合成过程就完成了,剩下的就是手势、特效。第一次写博客,加之本身也是个菜鸟,估计被吐槽在所难免~ 吐可以,请大家文明用语就好。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
slidingmenu包含slidingmenuDemo跟两个slidingmenu_lib,slidingmenu_actionbar,直接可以用。slidingmenu_lib是开源项目ActionBarSherlock-master的library类库,slidingmenu_actionbar是开源项目ActionBarSherlock-master的actionbarsherlock类库,只是重命名了,slidingmenuDemo是开源项目ActionBarSherlock-maste的Example。注意:(已修改) 1.可能报找不到getSupportActionBar等ActionBarSherLock的方法。原因是使用ActionBarSherLock的Activity需继承于SherlockActivity,修改SlidingMenu liberary(slidingmenu_lib)中的 SlidingFragmentActivity,让它继承于SherlockFragmentActivity,重新编译liberary导入。 2.项目红叉或红叹号,删除support_v4包,ActionBarSherLock(slidingmenu_actionbar)已包含此包,会冲突。也有可能是主题问题,注意appication theme是否正确,参照exsample。 3.注意把ActionBar、某些Fragment等替换成ActionBarSherLock包中的类。 SlidingMenu依赖ActionBarSherlock。可以去官网下载最新的ActionBarSherlock。在导入的时候SlidingMenu-master/library中的 SlidingActivity.java、SlidingFragmentActivity.java SlidingPreferenceActivity.java三个文件作如下修改就好了。 SlidingActivity extends Activity SlidingFragmentActivity extends FragmentActivity SlidingPreferenceActivity extends PreferenceActivity 分别替换成 SlidingActivity extends SherlockActivity SlidingFragmentActivity extends SherlockFragmentActivity SlidingPreferenceActivity extends SherlockPreferenceActivity
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值