0
点赞
收藏
分享

微信扫一扫

Android自定义控件——开源组件SlidingMenu的项目集成


 

      在实际项目开发中,定制一个菜单,能让用户得到更好的用户体验,诚然菜单的样式各种各样,但是有一种菜单——滑动菜单,是被众多应用广泛使用的。关于这种滑动菜单的实现,我在前面的博文中也介绍了如何自定义去实现,请参考Android自定义控件——侧滑菜单,这篇博文描述的是如何从无到有创建一个侧滑菜单的控件,里面的代码不多,但是处理的逻辑和各种效果比较复杂,如果稍有不慎,这种自定义控件就要BUG不断,难以在项目中使用,而且实现的效果比较单一。

       好在有开源力量的存在,在开源世界里,一切常用的实用的东西,都会有大牛帮我们做好了。所以,这种侧滑菜单不难被找到,下面就来介绍一下这个开源的侧滑菜单SlidingMenu。

 

一、SlidingMenu相关介绍

1,获取SlidingMenu

       SlidingMenu在GitHub中可以被找到,下面是GitHub源码的地址,大家可以点进去,下载这个源码。另外,SlidingMenu这个开源组件也是基于另外一个开源组件之上的,这个开源组件是ActionBarSherlock,也需要下载下来。

SlidingMenu项目:https://github.com/jfeinstein10/SlidingMenu

ActionBarSherlock项目:https://github.com/JakeWharton/ActionBarSherlock

PS:关于SlidingMenu的作者Jeremy Feinstein和ActionBarSherlock的作者JakeWharton,都是大牛,前者还是JazzyViewPager的作者,后者更是Android-ViewPagerIndicator、NineOldAndroids、DiskLruCache等等的作者,大家可以注册一下GitHub的账号,选择Follow一下这些大牛,站在巨人的肩膀上进步。

 

2,导入到项目中

      首先解压这个ActionBarSherlock的压缩包,找到actionbarsherlock这个包,这个工程是类库,下面打开eclipse,Import->Android->Android Project from Existing Code,导入这个actionbarsherlock。

     然后解压这个SlidingMenu的压缩包,找到library,同样的方法Import->Android->Android Project from Existing Code,导入SlidingMenu的library,然后右键这个library,Properties->Android->add,选择上面导入的actionbarsherlock。

    接着新建一个Android项目,在这个项目里引用SlidingMenu,同样,右键工程目录->Properties->Android->add,添加上面导入的SlidingMenu的类库library,这样,这个SlidingMenu就算是导入到了工程中了。注意,当导入这个包的时候有可能会报下面的错误:

Android自定义控件——开源组件SlidingMenu的项目集成_ui

引起这个错误的原因是ActionBarSherlock和SlidingMenu以及我们的工程里面的android-support-v4.jar这个包版本不一致,解决的办法是,将我们自己工程libs目录下的android-support-v4.jar复制黏贴到ActionBarSherlock和SlidingMenu的类库的libs目录下,选择同意覆盖,这样这个报错就消除了。

 

3,引用SlidingMenu

      1.你可以通过new SlidingMenu(Context context)的方式把你的activity包含在一个slidingmenu里,然后调用SlidingMenu.attachToActivity(Activity activity, SlidingMenu.SLIDING_WINDOW | SlidingMenu.SLIDING_CONTENT)方法。SLIDING_WINDOW会在SlidingMenu的内容部分包含ActionBar,而SLIDING_CONTENT不会。你可以参加示例项目里的AttachExample。

       2.你可以让你的activity继承SlidingActivity来在activity级别上嵌入SlidingMenu。

           2.1 在你Activity的onCreate()方法里,像平常一样调用setContentView()方法,也要调用setBehindContentView()方法,它和setContentView()方法有同样的语法结构。setBehindContentView()方法会把view放置在SlidingMenu的后面。你也可以使用getSlidingMenu()方法,这样你就可以自定义你链接的slidingMenu了。

           2.2 如果你想使用其它的库,例如ActionBarSherlock,你只需要改变SlidingActivity的继承关系,让它继承SherlockActivity就可以了,原来继承的是Activity。这一点尤为重要,若是在Activity中需要引用ActionBar时,必须修改当前Activity继承于SherlockActivity,不然会产生意想不到的错误。

      3.你可以在Java代码里用编程来使用SlidingMenu,也可以在xml布局文件里使用。你可以把SlidingMenu当成一种其它的视图类型,并可以把它放在一些非常棒的地方,例如ListView的行里。

 

4,相关API介绍

1,下面是SlidingMenu在GitHub主页中的介绍,翻译过来大致的意思如下

Simple Example - 简单示例

    1. public class SlidingExample extends Activity {  
    2.   
    3. @Override  
    4. public void onCreate(Bundle savedInstanceState) {  
    5. super.onCreate(savedInstanceState);  
    6.         setTitle(R.string.attach);  
    7. // set the content view  
    8.         setContentView(R.layout.content);  
    9. // configure the SlidingMenu  
    10. new SlidingMenu(this);  
    11.         menu.setMode(SlidingMenu.LEFT);  
    12.         menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);  
    13.         menu.setShadowWidthRes(R.dimen.shadow_width);  
    14.         menu.setShadowDrawable(R.drawable.shadow);  
    15.         menu.setBehindOffsetRes(R.dimen.slidingmenu_offset);  
    16. 0.35f);  
    17. this, SlidingMenu.SLIDING_CONTENT);  
    18.         menu.setMenu(R.layout.menu);  
    19.     }  
    20.   
    21. }


     

    XML Usage - xml用法

          如果你决定要把SlidingMenu当作一个view,那你可以在xml文件里定义它:



    1. <com.jeremyfeinstein.slidingmenu.lib.SlidingMenu  
    2. xmlns:sliding="http://schemas.android.com/apk/res-auto"  
    3. android:id="@+id/slidingmenulayout"  
    4. android:layout_width="fill_parent"  
    5. android:layout_height="fill_parent"  
    6. sliding:viewAbove="@layout/YOUR_ABOVE_VIEW"  
    7. sliding:viewBehind="@layout/YOUR_BEHIND_BEHIND"  
    8. sliding:touchModeAbove="margin|fullscreen"  
    9. sliding:behindOffset="@dimen/YOUR_OFFSET"  
    10. sliding:behindWidth="@dimen/YOUR_WIDTH"  
    11. sliding:behindScrollScale="@dimen/YOUR_SCALE"  
    12. sliding:shadowDrawable="@drawable/YOUR_SHADOW"  
    13. sliding:shadowWidth="@dimen/YOUR_SHADOW_WIDTH"  
    14. sliding:fadeEnabled="true|false"  
    15. sliding:fadeDegree="float"  
    16. sliding:selectorEnabled="true|false"  
    17. sliding:selectorDrawable="@drawable/YOUR_SELECTOR"/>



    注意:你不能既使用behindOffset,又使用behindWidth。如果你这样做,程序会抛出异常。
            viewAbove : 你想在SlidingMenu上面使用的布局的引用
            viewBehind :你想在SlidingMenu下面使用的布局的引用
            touchModeAbove :一个enum,当上面的视图显示时,它指定了屏幕的哪部分是可触摸的。margin意味着只有左边缘。fullscreen意味着整个屏幕。默认是margin。
            behindOffset :当后面的视图显示时,你想让它上面的view显示的像素尺寸。默认是0。
            behindWidth : 后面视图宽度的尺寸。默认是屏幕的宽度(相当于behindOffset=0)。
            behindScrollScale :一个浮点值,代表了上面view滚动与下面view滚动的关系。如果被设置为0.5f,上面的view每滚动2px,后面的view滚动1px。如果被设置为1.0f,上面的view每滚动1px,后面的view也滚动1px。如果被设置为0.0f,后面的view不会滚动,也就是说它是静态的。这是一个有趣的东东。默认是0.25f。
            shadowDrable :指向上面视图和后面视图落差阴影的drawable的引用。默认没有阴影。
            shadowWidth :代表着阴影drawable宽度的尺寸。默认为0。
            shadowEnable :当SlidingMenu以非fade模式打开,在关闭时是否以fade模式关闭。
            fadeDegree :一个浮点值,代表着fade的“数量”。1.0f意味着当SlidingMenu关闭时,fade会一直存在。0.0f意味着不会有fade。
            selectorEnable :一个布尔值,标识了在上面view的左边是否绘制一个选择项,用于展示后面view被选择的元素。
            selectorDrawable : 用于选择项drawable的引用。注意:为了使得选择项被画出来,在被选择的view上,你必须调用SlidingMenu.setSelectView(View v)方法。在ListView上,列表项极有可能不工作,因为Android会回收它们。

    Caveats - 附加说明
             你的布局必须基于viewgroup,不幸的是,这种做法违背了<merge>的最优化。

     

    2,SlidingMenu类的相关方法

    menu.setMode(SlidingMenu.LEFT);   //设置左滑菜单
    menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);   //设置滑动的屏幕范围,该设置为全屏区域都可以滑动
    menu.setShadowDrawable(R.drawable.shadow);   //设置阴影图片
    menu.setShadowWidthRes(R.dimen.shadow_width);   //设置阴影图片的宽度
    menu.setBehindOffsetRes(R.dimen.slidingmenu_offset);   //SlidingMenu划出时主页面显示的剩余宽度
    menu.setBehindWidth(400);   //设置SlidingMenu菜单的宽度
    menu.setFadeDegree(0.35f);   //SlidingMenu滑动时的渐变程度
    menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);   //使SlidingMenu附加在Activity上
    menu.setMenu(R.layout.menu_layout);   //设置menu的布局文件
    menu.toggle();   //动态判断自动关闭或开启SlidingMenu
    menu.showMenu();   //显示SlidingMenu
    menu.showContent();   //显示内容
    menu.setOnOpenListener(onOpenListener);   //监听slidingmenu打开

    关于关闭menu有两个监听,简单的来说,对于menu close事件,一个是when,一个是after 

    menu.OnClosedListener(OnClosedListener);   //监听slidingmenu关闭时事件
    menu.OnClosedListener(OnClosedListener);   //监听slidingmenu关闭后事件

    左右都可以划出SlidingMenu菜单只需要设置

    menu.setMode(SlidingMenu.LEFT_RIGHT);   //属性,然后设置右侧菜单的布局文件
    menu.setSecondaryShadowDrawable(R.drawable.shadowright);   //右侧菜单的阴影图片

     

    ================================================华丽丽的分割线========================================================

     

    二、在项目中引用SlidingMenu

    1,创建项目,导入library

    首先来看看效果图吧,上图:

    Android自定义控件——开源组件SlidingMenu的项目集成_Android_02

           

    Android自定义控件——开源组件SlidingMenu的项目集成_Android_03

           可以看到效果了,没错,这个Demo用的是SIidingMenu的左右都可以滑出的效果,是不是觉得还可以啊?下面,我们一步步的来,去完成这个简单的SlidingMemuDemo的工程,这个工程非常简单,但是只要实现了这个Demo之后,以后做项目的时候,可以在这个Demo上面扩展,添加不同的界面UI罢了。

           首先,按照上面介绍的步骤,先将下载好的SlidingMenu包解压,找到library,在Eclipse上Import这个library。然后新建这个SlidingMenuDemo,右键选择Properties->Android->Add,添加这个library到工程下。注意:我们在这个工程里面将不会涉及使用ActionBar,所以不需要导入ActionBarSherlock的类库了。

    Android自定义控件——开源组件SlidingMenu的项目集成_Android_04

    2,菜单的布局XML

            接下来,我们先定义好左右菜单的UI,由于这是一个Demo,所以我这个UI做的比较简单,就是写死的一个线性布局,而且左右菜单的布局都是一样的,就偷懒不想写过多的代码,既然只是一个Demo,那大家就不要把美观放在第一位了,着重关注这个功能实现就好了。因为左右菜单的布局都是一样的,所以在这里只贴出左边菜单的布局的XML,以供参考。在实际开发中,菜单可以多种多样的,可以放ListView、GridView等等,根据具体需要来定夺。

    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    3. android:id="@+id/menu_left_frag"  
    4. android:layout_width="match_parent"  
    5. android:layout_height="match_parent" >  
    6.   
    7. <ScrollView  
    8. android:layout_width="match_parent"  
    9. android:layout_height="match_parent" >  
    10.   
    11. <LinearLayout  
    12. android:layout_width="match_parent"  
    13. android:layout_height="match_parent"  
    14. android:background="@drawable/menu_bg"  
    15. android:orientation="vertical" >  
    16.   
    17. <TextView  
    18. android:id="@+id/tab_news"  
    19. style="@style/tab_style"  
    20. android:drawableLeft="@drawable/tab_news"  
    21. android:text="新闻" />  
    22.   
    23. <TextView  
    24. android:id="@+id/tab_read"  
    25. style="@style/tab_style"  
    26. android:drawableLeft="@drawable/tab_read"  
    27. android:text="订阅" />  
    28.   
    29. <TextView  
    30. android:id="@+id/tab_local"  
    31. style="@style/tab_style"  
    32. android:drawableLeft="@drawable/tab_local"  
    33. android:text="本地" />  
    34.   
    35. <TextView  
    36. android:id="@+id/tab_ties"  
    37. style="@style/tab_style"  
    38. android:drawableLeft="@drawable/tab_ties"  
    39. android:text="跟帖" />  
    40.   
    41. <TextView  
    42. android:id="@+id/tab_pics"  
    43. style="@style/tab_style"  
    44. android:drawableLeft="@drawable/tab_pics"  
    45. android:text="图片" />  
    46.   
    47. <TextView  
    48. android:id="@+id/tab_focus"  
    49. style="@style/tab_style"  
    50. android:drawableLeft="@drawable/tab_focus"  
    51. android:text="话题" />  
    52.   
    53. <TextView  
    54. android:id="@+id/tab_vote"  
    55. style="@style/tab_style"  
    56. android:drawableLeft="@drawable/tab_vote"  
    57. android:text="投票" />  
    58.   
    59. <TextView  
    60. android:id="@+id/tab_ugc"  
    61. style="@style/tab_style"  
    62. android:drawableLeft="@drawable/tab_ugc"  
    63. android:text="聚合阅读" />  
    64. </LinearLayout>  
    65. </ScrollView>  
    66.   
    67. </FrameLayout>


    布局中使用的样式:

     

      1. <style name="tab_style">  
      2. <item name="android:layout_width">fill_parent</item>  
      3. <item name="android:layout_height">wrap_content</item>  
      4. <item name="android:background">@drawable/tab_background</item>  
      5. <item name="android:drawablePadding">20dip</item>  
      6. <item name="android:gravity">center_vertical</item>  
      7. <item name="android:padding">10dip</item>  
      8. <item name="android:textColor">@android:color/white</item>  
      9. <item name="android:textSize">18dp</item>  
      10. <item name="android:clickable">true</item>  
      11. </style>


      由于在使用SlidingMenu时,要继承SlidingFragmentActivity,查看SlidingFragmentActivity的继承体系

       



      1. public class SlidingFragmentActivity extends FragmentActivity implements SlidingActivityBase


      会发现SlidingFragmentActivity是继承了FragmentActivity,那么就决定着,接下来的UI界面都是使用Fragment来实现的,包括左右菜单,主页UI都是Fragment。先来看看这个左右菜单的实现,比较简单,直接上主要代码:

       

        1. package com.example.slidingmenudemo;  
        2.   
        3. import com.example.slidingmenudemo.fragment.BaseFragment;  
        4. import com.example.slidingmenudemo.fragment.FocusFragment;  
        5. import com.example.slidingmenudemo.fragment.LocalFragment;  
        6. import com.example.slidingmenudemo.fragment.PicsFragment;  
        7. import com.example.slidingmenudemo.fragment.ReadFragment;  
        8. import com.example.slidingmenudemo.fragment.TiesFragment;  
        9. import com.example.slidingmenudemo.fragment.UgcFragment;  
        10. import com.example.slidingmenudemo.fragment.VoteFragment;  
        11.   
        12. import android.os.Bundle;  
        13. import android.support.v4.app.Fragment;  
        14. import android.view.LayoutInflater;  
        15. import android.view.View;  
        16. import android.view.View.OnClickListener;  
        17. import android.view.ViewGroup;  
        18.   
        19. public class LeftMenuFragment extends Fragment implements OnClickListener {  
        20.   
        21. private MainActivity mAct;  
        22. private View view;  
        23.   
        24. @Override  
        25. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
        26. null);  
        27.         mAct = (MainActivity) getActivity();  
        28. this);  
        29. this);  
        30. this);  
        31. this);  
        32. this);  
        33. this);  
        34. this);  
        35. this);  
        36. return view;  
        37.     }  
        38.   
        39. @Override  
        40. public void onClick(View v) {  
        41. null;  
        42. switch (v.getId()) {  
        43. case R.id.tab_news:  
        44. new HomeFragment();  
        45. break;  
        46. case R.id.tab_read:  
        47. new ReadFragment();  
        48. break;  
        49. case R.id.tab_local:  
        50. new LocalFragment();  
        51. break;  
        52. case R.id.tab_ties:  
        53. new TiesFragment();  
        54. break;  
        55. case R.id.tab_pics:  
        56. new PicsFragment();  
        57. break;  
        58. case R.id.tab_focus:  
        59. new FocusFragment();  
        60. break;  
        61. case R.id.tab_vote:  
        62. new VoteFragment();  
        63. break;  
        64. case R.id.tab_ugc:  
        65. new UgcFragment();  
        66. break;  
        67. default:  
        68. break;  
        69.         }  
        70.         mAct.switchContent(fragment);  
        71. null;  
        72.     }  
        73.   
        74. }


         

        3,内容Fragment的创建

        由于右边菜单的主要代码跟左边菜单的代码很相似,限于篇幅,这里就不贴了,有兴趣的请点击下面的源码链接,下载源码。看源码里面可以发现,当点击菜单上某一个标签时,要将标签代表的内容放到主页上去显示,可以看出这个所谓的“内容”都是一个个的Fragment实现的,要让这些Fragment在FragmentActivity上不停的切换来达到主页内容变化的效果,下面是内容的代码段,很简单,只贴出一段了,不同的内容页不同的布局,在项目按照需求定夺,我这里是简单的处理。

        1,Fragment布局XML



        1. <?xml version="1.0" encoding="utf-8"?>  
        2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        3. android:layout_width="match_parent"  
        4. android:layout_height="match_parent" >  
        5.   
        6. <include layout="@layout/frag_title" />  
        7.   
        8. <TextView  
        9. android:layout_width="wrap_content"  
        10. android:layout_height="wrap_content"  
        11. android:layout_centerInParent="true"  
        12. android:text="这是网易话题频道"  
        13. android:textColor="#FFFF0000"  
        14. android:textSize="22dp" />  
        15.   
        16. </RelativeLayout>


        2,include的标题XML

         



        1. <?xml version="1.0" encoding="utf-8"?>  
        2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        3. android:id="@+id/rl_maincenter_title"  
        4. android:layout_width="match_parent"  
        5. android:layout_height="50dp"  
        6. android:background="@drawable/top_bar_bg" >  
        7.   
        8. <ImageButton  
        9. android:id="@+id/ib_menu_left"  
        10. android:layout_width="wrap_content"  
        11. android:layout_height="wrap_content"  
        12. android:layout_centerVertical="true"  
        13. android:layout_marginLeft="15dp"  
        14. android:background="@drawable/left_menu_button" />  
        15.   
        16. <TextView  
        17. android:id="@+id/tv_load_course"  
        18. android:layout_width="wrap_content"  
        19. android:layout_height="wrap_content"  
        20. android:layout_centerInParent="true"  
        21. android:gravity="center"  
        22. android:text="网易新闻"  
        23. android:textColor="@android:color/white"  
        24. android:textSize="18dp" />  
        25.   
        26. <ImageButton  
        27. android:id="@+id/ib_menu_right"  
        28. android:layout_width="wrap_content"  
        29. android:layout_height="wrap_content"  
        30. android:layout_alignParentRight="true"  
        31. android:layout_centerVertical="true"  
        32. android:layout_marginRight="15dp"  
        33. android:background="@drawable/right_menu_button" />  
        34.   
        35. </RelativeLayout>


        3,Fragment的抽象基类——BaseFragment


          1. package com.example.slidingmenudemo.fragment;  
          2.   
          3. import com.example.slidingmenudemo.MainActivity;  
          4. import com.example.slidingmenudemo.R;  
          5. import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;  
          6.   
          7. import android.app.Activity;  
          8. import android.content.Context;  
          9. import android.os.Bundle;  
          10. import android.support.v4.app.Fragment;  
          11. import android.view.LayoutInflater;  
          12. import android.view.View;  
          13. import android.view.ViewGroup;  
          14. import android.view.View.OnClickListener;  
          15. import android.widget.ImageButton;  
          16.   
          17. public abstract class BaseFragment extends Fragment implements OnClickListener {  
          18. protected Context ct;  
          19. /** SlidingMenu对象 */  
          20. protected SlidingMenu sm;  
          21. public View rootView;  
          22. protected Activity MenuChangeHome;  
          23. /** 左菜单按钮 */  
          24. private ImageButton leftMenuBtn;  
          25. /** 右菜单按钮 */  
          26. private ImageButton rightMenuBtn;  
          27.   
          28. @Override  
          29. public void onActivityCreated(Bundle savedInstanceState) {  
          30.   
          31. super.onActivityCreated(savedInstanceState);  
          32.         sm = ((MainActivity) getActivity()).getSlidingMenu();  
          33.         initData(savedInstanceState);  
          34.     }  
          35.   
          36. @Override  
          37. public void onCreate(Bundle savedInstanceState) {  
          38. super.onCreate(savedInstanceState);  
          39.         ct = getActivity();  
          40.     }  
          41.   
          42. @Override  
          43. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
          44.         rootView = initView(inflater);  
          45.         leftMenuBtn = (ImageButton) rootView.findViewById(R.id.ib_menu_left);  
          46.         rightMenuBtn = (ImageButton) rootView.findViewById(R.id.ib_menu_right);  
          47. this);  
          48. this);  
          49.         setListener();  
          50. return rootView;  
          51.     }  
          52.   
          53. public View getRootView() {  
          54. return rootView;  
          55.     }  
          56.   
          57. @Override  
          58. public void onClick(View v) {  
          59. // TODO Auto-generated method stub  
          60. switch (v.getId()) {  
          61. case R.id.ib_menu_left: // 点击左边的按钮,左菜单收放  
          62.             sm.toggle();  
          63. break;  
          64. case R.id.ib_menu_right: // 点击右边按钮,右菜单缩放  
          65.             sm.showSecondaryMenu();  
          66. break;  
          67. default:  
          68. break;  
          69.         }  
          70.     }  
          71.   
          72. /**
          73.      * 初始化UI
          74.      * 
          75.      * @param inflater
          76.      * @return
          77.      */  
          78. protected abstract View initView(LayoutInflater inflater);  
          79.   
          80. /**
          81.      * 初始化数据
          82.      * 
          83.      * @param savedInstanceState
          84.      */  
          85. protected abstract void initData(Bundle savedInstanceState);  
          86.   
          87. /**
          88.      * 设置监听
          89.      */  
          90. protected abstract void setListener();  
          91.   
          92. }


          4,其中的一个Fragment主要代码,其实里面什么也没有

           

           

          1. public class FocusFragment extends BaseFragment {  
          2.   
          3. @Override  
          4. protected View initView(LayoutInflater inflater) {  
          5. // TODO Auto-generated method stub  
          6. return inflater.inflate(R.layout.frag_focus, null);  
          7.     }  
          8.   
          9. @Override  
          10. protected void initData(Bundle savedInstanceState) {  
          11. // TODO Auto-generated method stub  
          12.     }  
          13.   
          14. @Override  
          15. protected void setListener() {  
          16. // TODO Auto-generated method stub  
          17.     }  
          18. }

          4,主要代码,MainActivity

          最后,来重点看一下这个MainActivity里面的代码,在这里才是构建一个侧滑菜单效果的主要代码,源代码如下,可以参考注释来看:

           

            1. package com.example.slidingmenudemo;  
            2.   
            3. import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;  
            4. import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.CanvasTransformer;  
            5. import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity;  
            6.   
            7. import android.graphics.Canvas;  
            8. import android.os.Bundle;  
            9. import android.support.v4.app.Fragment;  
            10. import android.view.animation.Interpolator;  
            11.   
            12. public class MainActivity extends SlidingFragmentActivity {  
            13.   
            14. /** 侧滑菜单 */  
            15. private SlidingMenu sm;  
            16. /** 左边菜单 */  
            17. private LeftMenuFragment mLeftMenu;  
            18. /** 右边菜单 */  
            19. private RightMenuFragment mRightMenu;  
            20. /** 主界面 */  
            21. private HomeFragment mHomeFragment;  
            22. /** 动画类 */  
            23. private CanvasTransformer mTransformer;  
            24. /** 保存Fragment的状态 */  
            25. private Fragment mContent;  
            26.   
            27. @Override  
            28. public void onCreate(Bundle savedInstanceState) {  
            29. // TODO Auto-generated method stub  
            30. super.onCreate(savedInstanceState);  
            31.         initAnimation();  
            32.         sm = getSlidingMenu();  
            33.         setContentView(R.layout.content_frame);  
            34.         setBehindContentView(R.layout.menu_left_frag);  
            35.         sm.setSecondaryMenu(R.layout.menu_right_frag);  
            36. if (savedInstanceState == null) {  
            37. new LeftMenuFragment();  
            38. new RightMenuFragment();  
            39. new HomeFragment();  
            40. "Left").commit();  
            41. "Home").commit();  
            42. "Right").commit();  
            43.         }  
            44. // 设置右边菜单的阴影  
            45. // 设置阴影图片  
            46. // 设置阴影图片的宽度  
            47. // 显示主界面的宽度  
            48. // SlidingMenu滑动时的渐变程度  
            49.         sm.setBehindScrollScale(0f);  
            50. // 设置滑动的屏幕范围,该设置为全屏区域都可以滑动  
            51. // 设置菜单同时兼具左右滑动  
            52. // 设置动画  
            53.     }  
            54.   
            55. /**
            56.      * 初始化菜单滑动的效果动画
            57.      */  
            58. private void initAnimation() {  
            59. new CanvasTransformer() {  
            60. @Override  
            61. public void transformCanvas(Canvas canvas, float percentOpen) {  
            62. 2, canvas.getHeight() / 2);  
            63. // canvas.translate(0, canvas.getHeight() * (1 -  
            64. // interp.getInterpolation(percentOpen)));  
            65.             }  
            66.   
            67.         };  
            68.     }  
            69.   
            70. private static Interpolator interp = new Interpolator() {  
            71. @Override  
            72. public float getInterpolation(float t) {  
            73. 1.0f;  
            74. return t * t * t + 1.0f;  
            75.         }  
            76.     };  
            77.   
            78. /**
            79.      * 切换到主界面
            80.      * 
            81.      * @param fragment
            82.      */  
            83. public void switchContent(Fragment fragment) {  
            84.         mContent = fragment;  
            85.         getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).commit();  
            86.         getSlidingMenu().showContent();  
            87.     }  
            88.   
            89. /**
            90.      * 保存Fragment的状态
            91.      */  
            92. @Override  
            93. protected void onSaveInstanceState(Bundle outState) {  
            94. // TODO Auto-generated method stub  
            95. super.onSaveInstanceState(outState);  
            96. "Home", mContent);  
            97.     }  
            98.   
            99. }


                   上面的代码里关于Fragment使用以及Fragment的API不是这篇博文的重点,如果看不明白就先学习一下Fragment。我们关注这个菜单的实现即可,我使用的方式是Activity继承SlidingFragmentActivity,这种方式是很常见的,也很好维护,只要理解Fragment使用即可。诚然,我的这个Demo里没有使用SlidingMenu的依赖库ActionBarSherlock,是因为这个Demo已经自己定义了左右菜单导航按钮,无需使用ActionBar。

             

             

            5,SlidingMenu的动画

                   关于代码中的初始化动画,有必要解释一下。这个初始化动画可以不设置,默认就是左右水平方向的平移,这样比较死板,但是SlidingMenu的作者考虑到了我们的担忧,很“t贴心”的为我们写好了实现菜单滑动效果动画的接口,不得不说这外国大牛想的还真细腻。

            sm.setBehindCanvasTransformer(mTransformer); // 设置动画

            其中mTransformer是SlidingMenu类下的内部接口CanvasTransformer对象,源码如下:

             


              1. /**
              2.      * The Interface CanvasTransformer.
              3.      */  
              4. public interface CanvasTransformer {  
              5.   
              6. /**
              7.          * Transform canvas.
              8.          *
              9.          * @param canvas the canvas
              10.          * @param percentOpen the percent open
              11.          */  
              12. public void transformCanvas(Canvas canvas, float percentOpen);  
              13.     }


              实现这个接口,复写这个transformCanvas方法,使用该方法中提供的Canvas对象来实现相应的动画效果。当SlidingMenu触发了setBehindCanvasTransformer(mTransformer)时,这个方法会触发SlidingMenu下的自定义View对象的dispatchDraw(Canvas canvas)方法,即每次菜单界面重绘的时候,这个动画就会被调用。关于动画的写法,我提供两个吧,实际情况得根据项目需求来定夺。

               

              SlidingMemu的缩放动画:

               

              1. /**
              2.      * 初始化菜单滑动的效果动画
              3.      */  
              4. private void initAnimation() {  
              5. new CanvasTransformer() {  
              6. @Override  
              7. public void transformCanvas(Canvas canvas, float percentOpen) {  
              8. 2, canvas.getHeight() / 2);  
              9.             }  
              10.   
              11.         };  
              12.     }  
              13.   
              14. private static Interpolator interp = new Interpolator() {  
              15. @Override  
              16. public float getInterpolation(float t) {  
              17. 1.0f;  
              18. return t * t * t + 1.0f;  
              19.         }  
              20.     };

               

              SlidingMenu的平移动画:

               

              1. /**
              2.      * 初始化菜单滑动的效果动画
              3.      */  
              4. private void initAnimation() {  
              5. new CanvasTransformer() {  
              6. @Override  
              7. public void transformCanvas(Canvas canvas, float percentOpen) {  
              8. 0, canvas.getHeight() * (1 - interp.getInterpolation(percentOpen)));  
              9.             }  
              10.   
              11.         };  
              12.     }  
              13.   
              14. private static Interpolator interp = new Interpolator() {  
              15. @Override  
              16. public float getInterpolation(float t) {  
              17. 1.0f;  
              18. return t * t * t + 1.0f;  
              19.         }  
              20.     };

              SlidingMenu的拉伸动画:

               

               

               

              1. private void initAnimation() {  
              2. new CanvasTransformer() {  
              3. @Override  
              4. public void transformCanvas(Canvas canvas, float percentOpen) {  
              5. 1, 0, 0);  
              6.             }  
              7.   
              8.         };  
              9.     }

               

              6,SlidingMenu的背景

              最后一点,需要注意的是,在给SlidingMenu添加了动画效果后,运行时会看见菜单的背景处是一片“白色”或者“透明色”的,这样的用户体验非常的不好,那么怎么解决呢?这个很简单的,第一个考虑到是SlidingMenu本身没有设置背景,所以我们要手动的给SlidingMenu控件设置一下背景,打开SlidingMenu的类库library,在res/layout目录下找到slidingmenumain.xml的文件,打开看见这里就简单的定义了一个SlidingMenu,其它什么都没有,此时我们就可以在这个slidingmenumain.xml的节点下设置一下drawable属性即可。

              library/res/layout/slidingmenumain.xml:

               

              1. <?xml version="1.0" encoding="utf-8"?>  
              2. <com.jeremyfeinstein.slidingmenu.lib.SlidingMenu   
              3. xmlns:android="http://schemas.android.com/apk/res/android"  
              4. android:id="@+id/slidingmenumain"  
              5. android:layout_width="fill_parent"  
              6. android:layout_height="fill_parent" />

              源码请在这里下载

              举报

              相关推荐

              0 条评论