zoukankan      html  css  js  c++  java
  • SlidingMenu+ViewPager实现侧滑菜单效果

    先简单介绍下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;
    	@Override
    	public 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);
    		//初始化SlidingMenu
    		initSlidingMenu();
    	}
    
    	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);
        }
    	
    	@Override
    	public 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;
    	}
    
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setRetainInstance(true);
    	}
    
    
    	@Override
    	public 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();
    	}
    	
        //获取当前窗体界面数
    	@Override
    	public int getCount() {
    		return pageList.size();
    	}
    
    	//判断是否是由对象生成的View
    	@Override
    	public boolean isViewFromObject(View view, Object object) {
    		return ((Fragment) object).getView() == view;
    	}
    
    	//这个方法,return一个对象,这个对象表明了PagerAdapter适配器选择哪个对象放在当前的ViewPager中 
    	@Override
    	public 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);
        }
    	
    	@Override
    	public 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() {
    		
        	//点击一个选项
    		@Override
    		public 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() {
    		
    		@Override
    		public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    			
    		}
    		
    		@Override
    		public void onTabSelected(Tab tab, FragmentTransaction ft) {
    			  if (pager.getCurrentItem() != tab.getPosition())
    				   pager.setCurrentItem(tab.getPosition());
    		}
    		
    		@Override
    		public 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库 网上有很多教程如何使用这个库。





     


     

  • 相关阅读:
    用VS Code写C++程序如何运行
    DRF
    DRF
    DRF
    DRF
    DRF
    DRF
    DRF
    DRF
    DRF
  • 原文地址:https://www.cnblogs.com/krislight1105/p/3748361.html
Copyright © 2011-2022 走看看