碰巧用到了 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之前,我们必须调用setsetBehindContentView,来设置菜单的部分
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什么的都还在,不动。后面一样。
总结成一张图:
至此,整个替换和合成过程就完成了,剩下的就是手势、特效。第一次写博客,加之本身也是个菜鸟,估计被吐槽在所难免~ 吐可以,请大家文明用语就好。