通过SlidingMenu+Viewpager实现当前最流行的侧滑

通过SlidingMenu+Viewpager实现当前最流行的侧滑_第1张图片
内容简介:

通过SlidingMenu库与Fragment来实现当前最为流行的侧滑模式。其实涉及到的知识点有:

1.SlidingMenu
2.Fragment

通过layout构建一个Fragment
通过preference 来构建Fragment

 
准备工作:

1. SlidingMenu 下载地址: https://github.com/jfeinstein10/SlidingMenu
2.下载好后,导入到我们eclipse(也可以新建一个项目,将SlidingMenu项目拷进去)
3. 需要将SlidingMenu设置成is libray.因为我们需要在我们的demo中导入SlidingMenu。

当然,以上步骤,如果你下载了我的源码,你可以不用做啦。呵呵

接下来就是建立我们自己的demo项目啦。
(新建项目过程省略200字,如果你下载了我的源码,你只需要需要入项目即可)

首先我们需要准备两个界面的布局,一个是SlidingMenu的布局,也就是我们侧边栏的。另外一个为我们右边正文的显示布局。
在这里需要说明一下的是, 这两个布局为Activity布局(我们可以理解成为框架的布局文件),而我们真正的Sliding和右边正文显示的内容是由Fragment提供的,那时 Fragment也有自己的布局文件,在 Fragment显示在Activity中时,会将自己的Fragment布局嵌入到Activity布局中。
对于Fragment 的内容,大家自行学习一下就行了,特别是他的生命周期千万别与Activity混淆。

frame_menu.xml

 
  
  1. xml version="1.0" encoding="utf-8"?>
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/menu"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent" />

frame_content.xml

 
  
  1. xml version="1.0" encoding="utf-8"?>
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/content"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent" />

Activity布局文件准备好了后,我们需要新建一个 Activity来继承SlidingActivity,则这个activity将会提供一个 sliding 菜单 ,和正文的显示 。

MainActivity.java

 
  
  1. public class MainActivity extends SlidingActivity {
  2.  
  3. @Override
  4. public void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setTitle("SlidingMenu Demo");
  7. setContentView(R.layout.frame_content);
  8. // set the Behind View
  9. setBehindContentView(R.layout.frame_menu);
  10. FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
  11. MenuFragment menuFragment = new MenuFragment();
  12. fragmentTransaction.replace(R.id.menu, menuFragment);
  13. fragmentTransaction.replace(R.id.content, new ContentFragment("Welcome"));
  14. fragmentTransaction.commit();
  15.  
  16. // customize the SlidingMenu
  17. SlidingMenu sm = getSlidingMenu();
  18. sm.setShadowWidth(50);
  19. sm.setShadowDrawable(R.drawable.shadow);
  20. sm.setBehindOffset(60);
  21. sm.setFadeDegree(0.35f);
  22. //设置slding menu的几种手势模式
  23. //TOUCHMODE_FULLSCREEN 全屏模式,在content页面中,滑动,可以打开sliding menu
  24. //TOUCHMODE_MARGIN 边缘模式,在content页面中,如果想打开slding ,你需要在屏幕边缘滑动才可以打开slding menu
  25. //TOUCHMODE_NONE 自然是不能通过手势打开啦
  26. sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
  27.  
  28. //使用左上方icon可点,这样在onOptionsItemSelected里面才可以监听到R.id.home
  29. getActionBar().setDisplayHomeAsUpEnabled(true);
  30. }
  31.  
  32. @Override
  33. public boolean onCreateOptionsMenu(Menu menu) {
  34. // Inflate the menu; this adds items to the action bar if it is present.
  35. getMenuInflater().inflate(R.menu.activity_main, menu);
  36. return true;
  37. }
  38. @Override
  39. public boolean onOptionsItemSelected(MenuItem item) {
  40. switch (item.getItemId()) {
  41. case android.R.id.home:
  42. //toggle就是程序自动判断是打开还是关闭
  43. toggle();
  44. // getSlidingMenu().showMenu();// show menu
  45. // getSlidingMenu().showContent();//show content
  46. return true;
  47. }
  48. return super.onOptionsItemSelected(item);
  49. }
  50. }

解释:
代码中有详细的解释,就不再多说了。下面有几个需要注意的地方:

1.setContentView() 设置我们正文的显示布局,这和我们正常的Activity是一样的。
2.setBehindContentView() 设置SlidingMeni的布局。
3.FragmentTransaction类主要用于管理Fragment,有添加,替换,删除等操作。尤其是beginTransaction()与commit()方法与SQL中的事务有点类似。相信大家理解不难。如果需要更多详细信息,自行搜索。
4.SlidingMenu 可以设置Sliding的一些属性,像shadowwidth , shadowDrable等等根据英语解释大家都应该知道用处。可以自行设置看看效果。
5.SlidingMenu.setTouchModeAbove().其中一共包含三中手势模式:

TOUCHMODE_FULLSCREEN 全屏模式,在正文布局中通过手势也可以打开SlidingMenu
TOUCHMODE_MARGIN 边缘模式,在正文布局的边缘处通过手势可以找开SlidingMenu
TOUCHMODE_NONE 自然是不能通过手势打开SlidingMenu了

6.toggle() 是SldingMenu自动判断当前是打开还是关闭。
7.需要注意的是继承了SlidingActivity后,需要把oncreate修改成public
8.setBehindOffset()为设置SlidingMenu打开后,右边留下的宽度。大家可以把这个值写在dimens里面去:

这样就可以带上dp单位,可以适应多分辨率了。不然有些手机上面右边留出的多,有的少。

注意:SlidingMenu非常的强大 ,可以为左右同时设置SlidingMenu,也可以设置打开Menu时的动画 。具体可以参与SlidingMenu 的源码。我们要信息,在源码面前没有秘密 。

在MainActivity中,我们看到了我们的正文是由ContentFragment来填充内容的。SlidingMenu是由MenuFragment来填充内容的。
在这里需要说明一下的是,在ContentFragment中我们是通过一般的layout文件来构成的Fragment .
MenuFragment是由prefrence Fragment来完成我们的菜单内容的。

关于这两个Fragment的布局文件也直接跳过了,帖出来也是占用我们宝贵的网络资源。我们先来看看MenuFragment代码 :

MenuFragment.java

 
  
  1. public class MenuFragment extends PreferenceFragment implements OnPreferenceClickListener{
  2. int index = -1;
  3. @Override
  4. public void onCreate(Bundle savedInstanceState) {
  5. // TODO Auto-generated method stub
  6. super.onCreate(savedInstanceState);
  7. //set the preference xml to the content view
  8. addPreferencesFromResource(R.xml.menu);
  9. //add listener
  10. findPreference("a").setOnPreferenceClickListener(this);
  11. findPreference("b").setOnPreferenceClickListener(this);
  12. findPreference("n").setOnPreferenceClickListener(this);
  13. }
  14.  
  15. @Override
  16. public boolean onPreferenceClick(Preference preference) {
  17. String key = preference.getKey();
  18. if("a".equals(key)) {
  19. //if the content view is that we need to show . show directly
  20. if(index == 0) {
  21. ((MainActivity)getActivity()).getSlidingMenu().toggle();
  22. return true;
  23. }
  24. //otherwise , replace the content view via a new Content fragment
  25. index = 0;
  26. FragmentManager fragmentManager = ((MainActivity)getActivity()).getFragmentManager();
  27. fragmentManager.beginTransaction()
  28. .replace(R.id.content, new ContentFragment("This is A Menu"))
  29. .commit();
  30. }else if("b".equals(key)) {
  31. if(index == 1) {
  32. ((MainActivity)getActivity()).getSlidingMenu().toggle();
  33. return true;
  34. }
  35. index = 1;
  36. FragmentManager fragmentManager = ((MainActivity)getActivity()).getFragmentManager();
  37. fragmentManager.beginTransaction()
  38. .replace(R.id.content, new ContentFragment("This is B Menu"))
  39. .commit();
  40. }else if("n".equals(key)) {
  41.  
  42. if(index == 2) {
  43. ((MainActivity)getActivity()).getSlidingMenu().toggle();
  44. return true;
  45. }
  46. index = 2;
  47. FragmentManager fragmentManager = ((MainActivity)getActivity()).getFragmentManager();
  48. fragmentManager.beginTransaction()
  49. .replace(R.id.content, new ContentFragment("This is N Menu"))
  50. .commit();
  51. }
  52. //anyway , show the sliding menu
  53. ((MainActivity)getActivity()).getSlidingMenu().toggle();
  54. return false;
  55. }
  56. }

 

代码解释:

1.onCreate中完成了Preference布局的添加与设置各个选项的监听
2.在onPreferenceClick()方法中,我们先判断当前正文显示的是不是该选项的内容,如果是,则不用再去跳转了。如果不是,再从FragmentManager里面看能否找出已经存在的可用的fragment。如果没有,再创建新的fragment

ContentFragment就比较简单了,我们主要是在onCreateView()方法中创建我们的view ,并返回就可以了
ContentFragment.java

 
  
  1. public class ContentFragment extends Fragment {
  2. String text = null;
  3.  
  4. public ContentFragment() {
  5. }
  6.  
  7. public ContentFragment(String text) {
  8. Log.e("Krislq", text);
  9. this.text = text;
  10. }
  11.  
  12. @Override
  13. public void onCreate(Bundle savedInstanceState) {
  14. super.onCreate(savedInstanceState);
  15. setRetainInstance(true);
  16. Log.e("Krislq", "onCreate:"+text);
  17. }
  18.  
  19. @Override
  20. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  21. Log.e("Krislq", "onCreateView:"+ text);
  22. //inflater the layout
  23. View view = inflater.inflate(R.layout.fragment_text, null);
  24. TextView textView =(TextView)view.findViewById(R.id.textView);
  25. if(!TextUtils.isEmpty(text)) {
  26. textView.setText(text);
  27. }
  28. return view;
  29. }
  30. }

-------------------------------------加入Viewpager-------------------------------------------------

通过SlidingMenu+Viewpager实现当前最流行的侧滑_第2张图片

 

而我们很多实际的应用场景中我们需要一个更复杂的场景,比如说需要在一个菜单选项中集成多个tab来集中显示信息。这个时候 Viewpager就派上用场了。

我们点击么二个菜单,只是显示一个简单的fragment ,这次我们将把它改造成Viewpager+Fragment模式。在运行实例的时候,可以通过点击“Menu:ViewPager”菜单来看具体的效果。

首先我们需要添加一个PagerAdapter来自动适配Tab里面的Fragment ,就像ListView中的BaseAdapter差不多,只是需要实现的方法有一些区别。

DemoFragmentAdapter.java

 
  
  1. public class DemoFragmentAdapter extends PagerAdapter {
  2. private final FragmentManager mFragmentManager;
  3. private FragmentTransaction mTransaction = null;
  4. private List<ContentFragment> mFragmentList = new ArrayList<ContentFragment>(4);
  5. public DemoFragmentAdapter(FragmentManager fm) {
  6. mFragmentManager = fm;
  7. mFragmentList.add(new ContentFragment("ViewPager#Frist"));
  8. mFragmentList.add(new ContentFragment("ViewPager#Second"));
  9. mFragmentList.add(new ContentFragment("ViewPager#Third"));
  10. }
  11. @Override
  12. public int getCount() {
  13. return mFragmentList.size();
  14. }
  15.  
  16. @Override
  17. public boolean isViewFromObject(View view, Object object) {
  18. return ((Fragment) object).getView() == view;
  19. }
  20.  
  21. @Override
  22. public Object instantiateItem(ViewGroup container, int position) {
  23. if (mTransaction == null) {
  24. mTransaction = mFragmentManager.beginTransaction();
  25. }
  26. String name = getTag(position);
  27. Fragment fragment = mFragmentManager.findFragmentByTag(name);
  28. if (fragment != null) {
  29. mTransaction.attach(fragment);
  30. } else {
  31. fragment = getItem(position);
  32. mTransaction.add(container.getId(), fragment,
  33. getTag(position));
  34. }
  35. return fragment;
  36. }
  37.  
  38. @Override
  39. public void destroyItem(ViewGroup container, int position, Object object) {
  40. if (mTransaction == null) {
  41. mTransaction = mFragmentManager.beginTransaction();
  42. }
  43. mTransaction.detach((Fragment) object);
  44. }
  45. @Override
  46. public void finishUpdate(ViewGroup container) {
  47. if (mTransaction != null) {
  48. mTransaction.commitAllowingStateLoss();
  49. mTransaction = null;
  50. mFragmentManager.executePendingTransactions();
  51. }
  52. }
  53. public Fragment getItem(int position){
  54. return mFragmentList.get(position);
  55. }
  56. public long getItemId(int position) {
  57. return position;
  58. }
  59. protected String getTag(int position){
  60. return mFragmentList.get(position).getText();
  61. }
  62. }

 

代码解释:

instantiateItem 此方法返回一个对象,告诉PagerAdapter选择哪一个对象
destroyItem 此方法是移当前Object
finishUpdate 是在UI更新完成后的动作
isViewFromObject 判断是否由对象生成 view ,一般写法都比较固定

适配器写完了,接下来就是如何使用它了。我们知道在显示的时候是通过第二个菜单点击的。
我们重点来看一下第二个菜单点击后的动作即可:

 
  
  1. else if("b".equals(key)) {
  2. if(index == 1) {
  3. ((MainActivity)getActivity()).getSlidingMenu().toggle();
  4. return true;
  5. }
  6. index = 1;
  7. mFrameLayout.setVisibility(View.GONE);
  8. mViewPager.setVisibility(View.VISIBLE);
  9. DemoFragmentAdapter demoFragmentAdapter = new DemoFragmentAdapter(mActivity.getFragmentManager());
  10. mViewPager.setOffscreenPageLimit(5);
  11. mViewPager.setAdapter(demoFragmentAdapter);
  12. mViewPager.setOnPageChangeListener(onPageChangeListener);
  13. ActionBar actionBar = mActivity.getActionBar();
  14. actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
  15. actionBar.removeAllTabs();
  16. actionBar.addTab(actionBar.newTab()
  17. .setText("First Tab")
  18. .setTabListener(tabListener));
  19.  
  20. actionBar.addTab(actionBar.newTab()
  21. .setText("Second Tab")
  22. .setTabListener(tabListener));
  23. actionBar.addTab(actionBar.newTab()
  24. .setText("Third Tab")
  25. .setTabListener(tabListener));

代码解释:

1. 先还是判断,如果当前Content里面显示的就是该菜单的内容,则直接显示内容。
2.接下来是把Viewpager显示出来。在这里需要注意的是,我们的Viewpager是单独定义的,与其它 Menu显示区域是不同的,并且也是不能同时显示的。具体的布局变化请看frame_content.xml,在这里就不再列出来了。
3.紧接着就是初始化DemoFragmentAdapter,并且设置给Viewpager
4.当然我们需要将我们的ActionBar设置成TAB模式,并且 添加上TAB的标题。

在上面过程中有两个listener需要注意一下:

1. SimpleOnPageChangeListener.该监听是当我们的viewpager页面切换的时候会触发 ,在里面我们会去改变 tab的聚焦情况 。因为实现上viewpager与actionbar是独立的,需要我们手动同步 。代码如下:

 
  
  1.  
  2. ViewPager.SimpleOnPageChangeListener onPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
  3. @Override
  4. public void onPageSelected(int position) {
  5. getActivity().getActionBar().setSelectedNavigationItem(position);
  6. switch (position) {
  7. case 0:
  8. getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
  9. break;
  10. default:
  11. getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
  12. break;
  13. }
  14. }
  15.  
  16. };

代码解释:

setSelectedNavigationItem 方法用于设置ActionBar的聚焦tab .
在接下来我们判断了SLidingMenu的手势力模式,如果ViewPager已经滑到了最左边,则我们把手势设置成全屏的,这样更往左滑动的时候,就会打开Menu .

2.tabListener 主要是用来监听当我们自己点击tab改变页面的时候,那么我们Viewpager的内容也得随着改变。代码如下:

 
  
  1. ActionBar.TabListener tabListener = new ActionBar.TabListener() {
  2. @Override
  3. public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
  4. if (mViewPager.getCurrentItem() != tab.getPosition())
  5. mViewPager.setCurrentItem(tab.getPosition());
  6. }
  7.  
  8. @Override
  9. public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
  10.  
  11. }
  12.  
  13. @Override
  14. public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
  15.  
  16. }
  17. };
  18.  

代码解释:

Viewpager可以直接设置当前的Item .

到这里我们的讲解就算到了一段落了。
希望大用能经常使用这种模式。另外在3.0以下的系统中,support里面也提供了FragmentPagerAdapter ,使用方法比这个简单,大家就自己学着试用吧!

代码:http://download.csdn.net/detail/u011127787/5758527
 
  

你可能感兴趣的:(Android开源)