首页 > 代码库 > android 滑动侧边栏 SlideMenu 源码分析 以及使用手册

android 滑动侧边栏 SlideMenu 源码分析 以及使用手册

android 滑动侧边栏 SlideMenu 源码分析 以及使用手册




我们先看使用方案:




首先
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


android 滑动侧边栏 SlideMenu 源码分析 以及使用手册