SlidingMenu+ViewPager实现侧滑菜单效果

来源:互联网 发布:游迅网软件下载 编辑:程序博客网 时间:2024/05/01 11:21

先简单介绍下SlidingMenu和ViewPager.

ViewPager就是一个官方提供的多页面滑动组件,需要一个适配器来构建多个页面.

先来看看ViewPager对应的基本适配器PageAdapter,需要实现以下方法

getCount() 
这个方法,是获取当前窗体界面数
isViewFromObject() 
判断是否由对象生成 的view ,一般写法都比较固定
如:return object == view;
instantiateItem(ViewGroup, int) 
这个方法,return一个对象,这个对象表明了PagerAdapter适配器选择哪个对象放在当前的ViewPager中 
destroyItem(ViewGroup, int, Object) 
这个方法,是从ViewGroup中移出当前View
finishUpdate(ViewGroup container)
在UI更新后完成的动作

ViewPager对应的监听器是PageChangeListner 
当页面改变时触发

一般使用一个简单的子类监听器是SimpleOnPageChangeListener

onPageSelected(int position)
页卡选中的方法

平常使用FragmentPagerAdapter和FragmentStatePagerAdapter来构建ViewPager
FragmentPagerAdapter更多的用于少量界面的ViewPager,比如Tab划过的fragment会保存在内存中,尽管已经划过。
而FragmentStatePagerAdapter和ListView有点类似,会保存当前界面,以及下一个界面和上一个界面(如果有),最多保存3个,其他会被销毁掉。
注意的是FragmentStatePagerAdapter可能不经意间会造成内存未正常回收,严重导致内存溢出,比如图片资源没有释放,资源引用问题

setOffscreenPageLimit(int) 
设置预加载TAB页卡数量,默认是1,就是当前页卡显示的时候,预先加载下一个页卡.数量不能太大.设为0即不進行预加载



SlidingMenu

使用方法:

 首先,Activity要继承自SlidingFragmentActivity,而SlidingFragmentActivity又继承自SherlockFragmentActivity并实现SlidingActivityBase接口提供相应方法


左侧、右侧和两边
在BaseActivity中将SlidingMenu默认设置左面菜单,全屏可拉动及其他一些属性,下面看代码:
   // 设置menu布局,根据模式决定是从左侧还是右侧拉出
        setBehindContentView(R.layout.menu_frame);
        FragmentTransaction t = this.getSupportFragmentManager().beginTransaction();
        mFrag = new SampleListFragment();
        t.replace(R.id.menu_frame, mFrag);
        t.commit();
        //SlidingMenu控件的初始化
        SlidingMenu sm = getSlidingMenu();
        sm.setShadowWidthRes(R.dimen.shadow_width);//阴影宽度
        sm.setShadowDrawable(R.drawable.shadow);//阴影Drawable
        sm.setBehindOffsetRes(R.dimen.slidingmenu_offset);//拉开后离边框距离
        sm.setFadeDegree(0.35f); //颜色渐变比例
        sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); //拉动事件区域 --全屏
        getSupportActionBar().setDisplayHomeAsUpEnabled(true); //ActionBar返回启用


设置SlidingMenu的模式: 
        // 设置左侧menu
        sm.setMode(SlidingMenu.LEFT);      
      // 设置右侧menu
        sm.setMode(SlidingMenu.RIGHT);
当设置左右两侧时要注意,因为前面只添加了一个菜单布局,所以这里我们要另外再设置一个: 
        // 设置左右侧都有
        sm.setMode(SlidingMenu.LEFT_RIGHT);
        // 此时要再次添加布局菜单,上一个为左侧,这个为右侧
        sm.setSecondaryMenu(R.layout.menu_frame_two);
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.menu_frame_two,
                  new SampleListFragment()).commit();
        sm.setSecondaryShadowDrawable(R.drawable.shadowright);


可拉动触控范围
这个更简单,不多说:
        switch (checkedId) {
           case R.id.touch_above_full:
            // 设置触摸拖动模式--全屏
            getSlidingMenu().setTouchModeAbove(
                     SlidingMenu.TOUCHMODE_FULLSCREEN);
            break;
           case R.id.touch_above_margin:
            // 设置触摸拖动模式--边缘
            getSlidingMenu().setTouchModeAbove(
                     SlidingMenu.TOUCHMODE_MARGIN);
            break;
           case R.id.touch_above_none:
            // 设置触摸拖动模式--关闭
            getSlidingMenu().setTouchModeAbove(
                     SlidingMenu.TOUCHMODE_NONE);
            break;
        }


放缩比例
// 放缩比例
                getSlidingMenu().setBehindScrollScale(
                         (float) seekBar.getProgress() / seekBar.getMax());


拉出菜单宽度
// 菜单宽度(源码中作者把该操作隐藏)
                getSlidingMenu().setBehindWidth(
                         (int) (percent * getSlidingMenu().getWidth()));
                getSlidingMenu().requestLayout();


阴影
有无阴影
if (isChecked)
// 是否有阴影
   getSlidingMenu()
        .setShadowDrawable(
            getSlidingMenu().getMode() == SlidingMenu.LEFT ? R.drawable.shadow: R.drawable.shadowright);
 else
   getSlidingMenu().setShadowDrawable(null);


阴影宽度
// 设置阴影宽度
getSlidingMenu().setShadowWidth(width);
getSlidingMenu().invalidate();


颜色渐变


有无渐变
getSlidingMenu().setFadeEnabled(isChecked);


渐变比率
// 颜色渐变比例
getSlidingMenu().setFadeDegree(
        (float) seekBar.getProgress() / seekBar.getMax());


代码部分

package com.light.android.study;import com.light.android.study.fragment.ContentFragment;import com.light.android.study.fragment.MenuFragment;import com.slidingmenu.lib.SlidingMenu;import com.slidingmenu.lib.app.SlidingActivity;import android.os.Bundle;import android.view.MenuItem;import android.app.ActionBar;import android.app.FragmentTransaction;public class MainActivity extends SlidingActivity{    private FragmentTransaction transaction;private ContentFragment contentFragment;private MenuFragment menuFragment;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.content_page);setBehindContentView(R.layout.menu_page);menuFragment = new MenuFragment();contentFragment = new ContentFragment("welcome!Kris Light!");transaction = getFragmentManager().beginTransaction();transaction.replace(R.id.menu,menuFragment,"menu");transaction.replace(R.id.content,contentFragment,"content");transaction.commit();//設置ActionBar為TAB頁簽模式getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);//初始化SlidingMenuinitSlidingMenu();}private void initSlidingMenu() {        //SlidingMenu控件的初始化 使用默認的Right模式,菜單在右邊        SlidingMenu sm = getSlidingMenu();      //阴影宽度        sm.setShadowWidth(50);      //阴影Drawable        sm.setShadowDrawable(R.drawable.shadow);      //拉开后离边框距离        sm.setBehindOffset(80);      //颜色渐变比例        sm.setFadeDegree(0.35f);                //设置slding menu的几种手势模式        //TOUCHMODE_FULLSCREEN 全屏模式,在content页面中,滑动,可以打开sliding menu        //TOUCHMODE_MARGIN 边缘模式,在content页面中,如果想打开slding ,你需要在屏幕边缘滑动才可以打开slding menu        //TOUCHMODE_NONE 自然是不能通过手势打开啦        sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);        //使用左上方icon可点,这样在onOptionsItemSelected里面才可以监听到R.id.home        getActionBar().setDisplayHomeAsUpEnabled(true);    }@Overridepublic boolean onOptionsItemSelected(MenuItem item) {if(item.getItemId()== android.R.id.home){toggle();}return super.onOptionsItemSelected(item);}}

package com.light.android.study;import android.app.Fragment;import android.os.Bundle;import android.util.Log;import android.view.LayoutInflater;import android.view.Menu;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;public class PageFragment extends Fragment {   private String text;    public PageFragment(){} public String getText() {return text;}public void setText(String text) {this.text = text;}public PageFragment(String t){this.text = t;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setRetainInstance(true);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {Log.i("Light", "onCreateView "+text);View view = inflater.inflate(R.layout.fragment_page_layout, null);TextView tv = (TextView) view.findViewById(R.id.tv);tv.setText(text);return view;}}

package com.light.android.study.adapter;import java.util.ArrayList;import java.util.List;import com.light.android.study.PageFragment;import android.app.Fragment;import android.app.FragmentManager;import android.app.FragmentTransaction;import android.support.v4.view.PagerAdapter;import android.view.View;import android.view.ViewGroup;public class ContentPageAdapter extends PagerAdapter{private List<PageFragment> pageList = new ArrayList<PageFragment>();private FragmentManager fragmentManager;private FragmentTransaction transaction;public ContentPageAdapter(List<PageFragment> list,FragmentManager manager){this.pageList = list;this.fragmentManager = manager;transaction = manager.beginTransaction();}    //获取当前窗体界面数@Overridepublic int getCount() {return pageList.size();}//判断是否是由对象生成的View@Overridepublic boolean isViewFromObject(View view, Object object) {return ((Fragment) object).getView() == view;}//这个方法,return一个对象,这个对象表明了PagerAdapter适配器选择哪个对象放在当前的ViewPager中 @Overridepublic Object instantiateItem(ViewGroup container, int position) { if(transaction==null){ transaction = fragmentManager.beginTransaction(); } //先判斷之前是否有attach過這個Fragment,有的話直接重新attach綁定 String tag = pageList.get(position).getText(); PageFragment fragment = (PageFragment) fragmentManager.findFragmentByTag(tag); if(fragment!=null){ transaction.attach(fragment); }else{ //沒有attach過直接add fragment = pageList.get(position); transaction.add(container.getId(),fragment,fragment.getText()); } return fragment;} /**     * 此方法是移当前Object     */    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        if (transaction == null) {        transaction = fragmentManager.beginTransaction();        }        //detach解除綁定        transaction.detach((Fragment) object);    }      /**     *  在UI更新完成后的动作     */   @Override   public void finishUpdate(ViewGroup container) {  if(transaction!=null){  //提交  transaction.commitAllowingStateLoss();  transaction = null;          //立即執行事務          fragmentManager.executePendingTransactions();  }   }}

package com.light.android.study.fragment;import com.light.android.study.R;import android.app.Fragment;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;public class ContentFragment extends Fragment {private String title;public ContentFragment(){}public ContentFragment(String title){this.title = title;}@Override    public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);        //設置Fragment不重建        setRetainInstance(true);    }@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View convertView = inflater.inflate(R.layout.fragment_page_layout, null);TextView tv = (TextView) convertView.findViewById(R.id.tv);tv.setText(title);return convertView;}}

package com.light.android.study.fragment;import java.util.ArrayList;import java.util.List;import android.app.ActionBar;import android.app.ActionBar.Tab;import android.app.FragmentTransaction;import android.os.Bundle;import android.preference.Preference;import android.preference.PreferenceFragment;import android.support.v4.view.ViewPager;import android.view.View;import android.widget.FrameLayout;import com.light.android.study.MainActivity;import com.light.android.study.PageFragment;import com.light.android.study.R;import com.light.android.study.adapter.ContentPageAdapter;import com.slidingmenu.lib.SlidingMenu;public class MenuFragment extends PreferenceFragment {private List<PageFragment> pageList = new ArrayList<PageFragment>();private MainActivity mActivity; private ViewPager pager;FrameLayout mFrameLayout;private ContentPageAdapter adapter;private int index = -1;public MenuFragment() {}    @Override    public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setRetainInstance(true);    addPreferencesFromResource(R.xml.menu);    }        @Override    public void onActivityCreated(Bundle savedInstanceState) {    super.onActivityCreated(savedInstanceState);    mActivity = (MainActivity) getActivity();    pager = (ViewPager) mActivity.findViewById(R.id.viewpager);    mFrameLayout = (FrameLayout)mActivity.findViewById(R.id.content);    findPreference("chunqiu").setOnPreferenceClickListener(onPreferenceClickListener);        findPreference("zhanguo").setOnPreferenceClickListener(onPreferenceClickListener);        findPreference("han").setOnPreferenceClickListener(onPreferenceClickListener);        findPreference("sanguo").setOnPreferenceClickListener(onPreferenceClickListener);        }        Preference.OnPreferenceClickListener onPreferenceClickListener = new Preference.OnPreferenceClickListener() {    //点击一个选项@Overridepublic boolean onPreferenceClick(Preference preference) {String key = preference.getKey();    mFrameLayout.setVisibility(View.GONE);//历史//三国if("sanguo".equals(key)){   //刚好是三国这一个选项   if(index == 0) {    mActivity.getSlidingMenu().toggle();                return true;            }  index = 0;  ActionBar actionBar =  mActivity.getActionBar();  actionBar.removeAllTabs();   //清空  pageList.clear();          actionBar.addTab(actionBar.newTab().setText("魏").setTabListener(tablistener));          PageFragment weiFragment = new PageFragment("魏");           pageList.add(weiFragment);          actionBar.addTab(actionBar.newTab().setText("蜀").setTabListener(tablistener));          PageFragment shuFragment = new PageFragment("蜀");           pageList.add(shuFragment);          actionBar.addTab(actionBar.newTab().setText("吴").setTabListener(tablistener));          PageFragment wuFragment = new PageFragment("吴");           pageList.add(wuFragment);          adapter = new ContentPageAdapter(pageList,mActivity.getFragmentManager());          //設置PagerView預加載View數量        pager.setOffscreenPageLimit(2);        //为ViewPager设置Adapter        pager.setAdapter(adapter);        //設置Page改變監聽器        pager.setOnPageChangeListener(onPageChangeListener);          }else if("han".equals(key)){   //汉代   //刚好是汉这一个选项   if(index == 1) {    mActivity.getSlidingMenu().toggle();                return true;            }   index = 1;  ActionBar actionBar =  mActivity.getActionBar();  //清空一次          actionBar.removeAllTabs();  pageList.clear();          actionBar.addTab(actionBar.newTab().setText("汉").setTabListener(tablistener));          PageFragment hanFragment = new PageFragment("汉");           pageList.add(hanFragment);          actionBar.addTab(actionBar.newTab().setText("楚").setTabListener(tablistener));          PageFragment chuFragment = new PageFragment("楚");           pageList.add(chuFragment);          adapter = new ContentPageAdapter(pageList,mActivity.getFragmentManager());          //設置PagerView預加載View數量        pager.setOffscreenPageLimit(1);        //为ViewPager设置Adapter        pager.setAdapter(adapter);        //設置Page改變監聽器        pager.setOnPageChangeListener(onPageChangeListener);}else if("zhanguo".equals(key)){   //战国   //刚好是战国这一个选项   if(index == 2) {    mActivity.getSlidingMenu().toggle();                return true;            }   index = 2;  ActionBar actionBar =  mActivity.getActionBar();  //清空一次          actionBar.removeAllTabs();      pageList.clear();          actionBar.addTab(actionBar.newTab().setText("戰國").setTabListener(tablistener));          PageFragment zgFragment = new PageFragment("戰國");           pageList.add(zgFragment);          adapter = new ContentPageAdapter(pageList,mActivity.getFragmentManager());        //为ViewPager设置Adapter        pager.setAdapter(adapter);        //設置Page改變監聽器        pager.setOnPageChangeListener(onPageChangeListener);          }else if("chunqiu".equals(key)){   //春秋   //刚好是春秋这一个选项   if(index == 3) {    mActivity.getSlidingMenu().toggle();                return true;            }   index = 3;  ActionBar actionBar =  mActivity.getActionBar();  //清空一次          actionBar.removeAllTabs();      pageList.clear();          actionBar.addTab(actionBar.newTab().setText("春秋").setTabListener(tablistener));          PageFragment cqFragment = new PageFragment("春秋");           pageList.add(cqFragment);          adapter = new ContentPageAdapter(pageList,mActivity.getFragmentManager());        //为ViewPager设置Adapter        pager.setAdapter(adapter);        //設置Page改變監聽器        pager.setOnPageChangeListener(onPageChangeListener);}//无论如何将菜单开关动作交给SlidingMenu管理mActivity.getSlidingMenu().toggle();return false;}};  /**     * SimpleOnPageChangeListener.该监听是当我们的viewpager页面切换的时候会触发      * 在里面我们会去改变 tab的聚焦情况 。     * 因为实现上viewpager与actionbar是独立的,需要我们手动同步 。     */    ViewPager.SimpleOnPageChangeListener onPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {        @Override        public void onPageSelected(int position) {        /**         *  setSelectedNavigationItem 方法用于设置ActionBar的聚焦tab .           *  在接下来我们判断了SLidingMenu的手势力模式,         *  如果ViewPager已经滑到了最左边,则我们把手势设置成全屏的,         *  这样更往左滑动的时候,就会打开Menu .         */            getActivity().getActionBar().setSelectedNavigationItem(position);            switch (position) {                //滑到最左邊頁卡設置SlidingMenu滑動手勢可全屏即右滑出菜單                case 0:                    getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);                    break;                default:                    getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);                    break;            }        }    };ActionBar.TabListener tablistener = new ActionBar.TabListener() {@Overridepublic void onTabUnselected(Tab tab, FragmentTransaction ft) {}@Overridepublic void onTabSelected(Tab tab, FragmentTransaction ft) {  if (pager.getCurrentItem() != tab.getPosition())   pager.setCurrentItem(tab.getPosition());}@Overridepublic void onTabReselected(Tab tab, FragmentTransaction ft) {}};private SlidingMenu getSlidingMenu() {        return ((MainActivity)getActivity()).getSlidingMenu();}}


content_fragment_layout.xml:
<?xml version="1.0" encoding="utf-8"?><Fragment xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    </Fragment>


content_page.xml:
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <FrameLayout        android:id="@+id/content"        android:layout_width="match_parent"        android:layout_height="match_parent" >    </FrameLayout>    <android.support.v4.view.ViewPager        android:id="@+id/viewpager"        android:layout_width="match_parent"        android:layout_height="match_parent"         /></FrameLayout>


fragment_page_layout.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=".PageActivity" >    <TextView        android:id="@+id/tv"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center"        android:text="page"       /></FrameLayout>


menu_page.xml
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/menu"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity" ></FrameLayout>









更新:

源代码已上传:http://download.csdn.net/detail/u011176244/6227395 

需要另外导入SlidingMenu库 网上有很多教程如何使用这个库。





 


 

原创粉丝点击