我们先看使用方案:
首先
public class MainActivity extends SlidingFragmentActivity
继承SlidingFragmentActivity ,这里面在创建时有创建需要的slidemenu等相关数据。
在Oncreate里面添加
private void init_sm() {
sm = getSlidingMenu(); // 获取menu
sm.setMode(SlidingMenu.LEFT_RIGHT);// 设置为左右都有
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);// 设置为右边全屏模式
sm.setTouchModeBehind(SlidingMenu.TOUCHMODE_MARGIN);// 设置为左边边框模式
setBehindContentView(R.layout.slidingmenu_left);//左边布局
sm.setSecondaryMenu(R.layout.slidingmeun_right);//右边布局
sm.setRightBehindWidth(((MyApplication) getApplication())
.GetScreenWidth());// 使用这个将右侧布局到全屏
}
这里我们要详细说明的为TOUCHMODE_FULLSCREEN这个参数,设置为这个参数后,右侧的布局就没法响应滑动消息,因为全屏消息都被slidemenu处理掉了。
因此我们需要修改如下:
sm.addIgnoredView(mPager);
使用此方法忽略点击到mPager view的消息。
设置忽略后这时你就需要使用 setOnTouchListener 来自己接收响应触屏消息
mPager.setOnTouchListener(new OnTouchListener() {
private float startx = -1, starty = -1, OffsetWidth;
private boolean hasdown = false;
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
boolean returns = false;
if (action == MotionEvent.ACTION_DOWN) {
startx = event.getX();
starty = event.getY();
hasdown = true;
} else if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_CANCEL
|| action == MotionEvent.ACTION_MASK) {
float x = event.getX();
float y = event.getY();
float xdiff = Math.abs(x - startx);
float ydiff = Math.abs(y - starty);
if (!(-1 == startx && -1 == starty)) {
if (OffsetWidth < 1)
OffsetWidth = (float) (MyApplication
.getApplication().GetScreenWidth() * 0.15);
if (hasdown && xdiff > ydiff * 2.2
&& xdiff > OffsetWidth) {
if (x > startx)//
{
if (currIndex == 0) {
sm.toggle();
}
returns = false;
}// else if (startx > x)//
// {
// if (currIndex == length - 1
// && !sm.isSecondaryMenuShowing())
// sm.showSecondaryMenu();
// }
}
}
hasdown = false;
startx = starty = -1;
}
return returns;
}
});
当前做法是
if (currIndex == 0) {
sm.toggle();
}
使用这个退出侧边栏。左边是一个menu,简单布局,右边是个viewpage,所以滑动到最左侧时,再滑动退出viewpage,进入主界面。
showMenu 和showSecondaryMenu 来操作显示左右两侧的菜单栏
使用上就这些注意点即可。
mainactivity的xml文件为:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.atemp.MainActivity"
tools:ignore="MergeRootFrame" >
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
</FrameLayout>
代码将container加入布局为:
FragmentTransaction t = this.getSupportFragmentManager()
.beginTransaction();
centerFragment = new SampleListFragment();
centerFragment.setcontext(MainActivity.this);
t.add(R.id.container, centerFragment);
t.commit();
-------------------------
下面来进行剖析源码:
首先,因为我们继承public class MainActivity extends SlidingFragmentActivity 所以先研究这个SlidingFragmentActivity
查看oncreate 函数
mHelper = new SlidingActivityHelper(this);
mHelper.onCreate(savedInstanceState);
这个为关键属性,后续很多接口都是透过它处理的。比如
public SlidingMenu getSlidingMenu() {
return mHelper.getSlidingMenu();
}
所以我们要去看SlidingActivityHelper这个类
看mHelper.onCreate(savedInstanceState);这个函数
public void onCreate(Bundle savedInstanceState) {
mSlidingMenu = (SlidingMenu) LayoutInflater.from(mActivity).inflate(R.layout.slidingmenumain, null);
}
创建了关键属性对象
R.layout.slidingmenumain 内容为:
<?xml version="1.0" encoding="utf-8"?>
<com.jeremyfeinstein.slidingmenu.lib.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/slidingmenumain"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
如此slidingMenu则出现了。
关键第二个函数:
onPostCreate
里面的方法:
mSlidingMenu.attachToActivity(mActivity,
mEnableSlide ? SlidingMenu.SLIDING_WINDOW : SlidingMenu.SLIDING_CONTENT);
将自己挂到activity的根view上去
看这一段:
case SLIDING_CONTENT:
mActionbarOverlay = actionbarOverlay;
// take the above view out of
ViewGroup contentParent = (ViewGroup) activity.findViewById(android.R.id.content);
View content = contentParent.getChildAt(0);
contentParent.removeView(content);
contentParent.addView(this);
setContent(content);
// save people from having transparent backgrounds
if (content.getBackground() == null)
content.setBackgroundResource(background);
break;
这里处理逻辑为:
contentParent.addView(this);
将slidemenu加入到这个contentview里面,将contentview作为当前activity的上下文使用 setContent(content);设置进来。
如此一来,此时slidemenu则会加进主界面。
随后消息则会先传给CustomViewAbove.java 和 CustomViewBehind.java 两个都是继承了viewgroup,所以可以多添加几个view。
因为slideingMenu把mViewAbove添加在后面,所以有优先响应消息权利。然后再依据setContent(content);把有slidemenu的布局设置进来,如此一来,
顶部消息则会传给它
在 CustomViewAbove 的 onInterceptTouchEvent 和 onTouchEvent 会处理各类消息,如此搭配起来,则最终实现左右侧边栏的功能。
主界面的container 触屏流程为:都不响应才会传给Touch up dispatch to com.jeremyfeinstein.slidingmenu.lib.CustomViewAbove