无需SherlockActionbar的SlidingMenu使用详解(二)——向Fragment中添加ViewPager和Tab
之前我们对大体框架有了一定的认识,现在我们来做Fragment界面,其实这里面和这个框架的关系就不大了,但因为有些同学对于在SlidingMenu中切换fragment还是有问题,所以我就在本篇进行详细讲解。
1.定义MenuFragment
1.1首先定义这个fragment的布局文件,其实很简单了就是几张图片和一个listview
app_menu.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="200dp" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="120dp" > <ImageView android:id="@+id/backgroundPicture_id" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" android:src="@drawable/background" /> <ImageView android:id="@+id/head_pic_id" android:layout_width="60dp" android:layout_height="60dp" android:layout_alignParentLeft="true" android:layout_marginLeft="22dp" android:layout_marginTop="40dp" android:scaleType="fitXY" android:src="@drawable/kale" /> <TextView android:id="@+id/name_id" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignBottom="@+id/head_pic_id" android:layout_marginBottom="20dp" android:layout_marginLeft="20dp" android:layout_marginTop="55dp" android:layout_toRightOf="@id/head_pic_id" android:text="JackTony" android:textColor="#ffffff" android:textSize="20sp" /> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="90dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:gravity="center" android:orientation="horizontal" > <ImageView android:id="@+id/personalSetting_id" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginRight="10dp" android:src="@drawable/personalsettingbutton" android:scaleType="fitCenter" /> <ImageView android:id="@+id/releaseMessageButton_id" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginLeft="10dp" android:src="@drawable/releasemessagebutton" android:scaleType="fitCenter" /> </LinearLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/menu_list" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="15dp" /> </RelativeLayout> </LinearLayout>
1.2和往常一样,我们在Fragment中加载布局文件,并且给里面的listview添加适配器用于绑定数据
MenuFragment
package com.kale.slidingmenutest.fragment; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ListView; import com.kale.slidingmenutest.MainActivity; import com.kale.slidingmenutest.R; /** * @author:JackTony * @tips :菜单的fragment * @date :2013-11-17 */ public class MenuFragment extends Fragment { private MainActivity activity; @Override public void onAttach(Activity activity) { super.onAttach(activity); this.activity = (MainActivity)activity; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ View v = inflater.inflate(R.layout.app_menu, null); return v; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); String []items = {"第一个栏目","第二个栏目"}; ArrayAdapter<String> adapter = new ArrayAdapter<String>( getActivity(), android.R.layout.simple_list_item_1,items); ListView menuLv = (ListView)getActivity().findViewById(R.id.menu_list); //设置适配器和监听器 menuLv.setAdapter(adapter); menuLv.setOnItemClickListener(new MenuItemClickListener()); } class MenuItemClickListener implements OnItemClickListener{ @Override public void onItemClick(AdapterView<?> parent, View view, int position,long id) { Fragment newFragment = null; MainActivity.NOW_FRAGMENT_NO = position; activity.supportInvalidateOptionsMenu(); switch (position) { case 0: newFragment = new FirstFragment(); break; case 1: newFragment = new SecondFragment(); break; } if (newFragment != null) { //交给Activity来切换正文fragment activity.switchContent(newFragment); } } } }
讲解:
1.listview用一个最简单的ArrayAdapter来放了两个数据,并且添加了监听器来监听点击事件。
2.在实际使用中不同的fragment很可能会需要不同的菜单,所以我通过对MainActivity中静态变量的设置和activity.supportInvalidateOptionsMenu();来使得每次切换Fragment的时候都重新根据静态变量的值来生成菜单项
3.这里面因为要用到MainActivity中切换Fragment的方法,所以要生成MainActivity对象。需要注意的是在多次切换后这个Fragment中的getActivity()方法很可能会出错,返回null值。因此这里在绑定activity时实例化一个activity对象是很有必要的!
2.简单的Fragment
SecondFragment是个很简单的Fragment,就是为了举例子用的。
package com.kale.slidingmenutest.fragment; import android.os.Bundle; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; public class SecondFragment extends MenuFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TextView textView = new TextView(getActivity()); textView.setGravity(Gravity.CENTER); textView.setText("第二个Fragment"); textView.setTextSize(30); return textView; } }
3.拥有TAB和ViewPager的FirstFragment
先贴上布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="visible" /> </LinearLayout>
这里面稍微有个难点就是,在不同的页面滑动时要实时改变slidingMenu的触控范围,是边缘还是全屏触控都需要设置。
3.1初始化viewPager和actionbar,并添加监听器。
因为actionbar监听器中需要传入viewpager做判断,所以要先初始化viewpager。
ViewPager viewPager; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO 自动生成的方法存根 return inflater.inflate(R.layout.first_fragment, null); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { // TODO 自动生成的方法存根 super.onActivityCreated(savedInstanceState); //设置actionbar initViewPager(); initActionBar(); } /** */ private void initActionBar() { ActionBar actionBar = ((MainActivity)getActivity()).getSupportActionBar(); //设定有Tab actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); ActionBar.Tab tab; //开始添加Tab,这里添加4个,并且设置监听器 for (int i = 1; i <= 4; i++) { tab = actionBar.newTab(); tab.setText("Tab " + i); tab.setTabListener(new MyTabListener(viewPager)); actionBar.addTab(tab); } } private void initViewPager() { ArrayList<View> list = new ArrayList<View>(); for (int i = 0; i < 4; i++) { list.add(newTextView("第"+(i+1)+"个界面")); } viewPager = (ViewPager)getActivity().findViewById(R.id.viewPager); viewPager.setAdapter(new MyPagerAdapter(list)); viewPager.setOnPageChangeListener(new PageChangeListener((MainActivity)getActivity())); } private TextView newTextView(String text) { TextView tv = new TextView(getActivity()); tv.setText(text); tv.setTextSize(30); tv.setGravity(Gravity.CENTER); return tv; }
/** * @author:Jack Tony 这里配置适配器 * @tips :这里传入一个list数组,从每个list中可以剥离一个view并显示出来 * @date :2014-9-24 */ public class MyPagerAdapter extends PagerAdapter { private ArrayList<View> mViewList; private int pagerNum = 0; public MyPagerAdapter(ArrayList<View> viewList) { mViewList = viewList; } public int getPagerNum() { return pagerNum; } @Override public int getCount() { return mViewList.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public void destroyItem(View arg0, int arg1, Object arg2) { if (mViewList.get(arg1) != null) { ((ViewPager) arg0).removeView(mViewList.get(arg1)); } } @Override public Object instantiateItem(View arg0, int arg1) { try { if (mViewList.get(arg1).getParent() == null) { ((ViewPager) arg0).addView(mViewList.get(arg1), 0); } else { /* * 很难理解新添加进来的view会自动绑定一个父类,由于一个儿子view不能与两个父类相关, * 所以得解绑不这样做否则会产生 viewpager java.lang.IllegalStateException: * The specified child already has a parent. You must call * removeView() on the child's parent first. */ ((ViewGroup) mViewList.get(arg1).getParent()) .removeView(mViewList.get(arg1)); ((ViewPager) arg0).addView(mViewList.get(arg1), 0); } } catch (Exception e) { e.printStackTrace(); } finally { pagerNum = arg1; } return mViewList.get(arg1); } }
全部代码:
package com.kale.slidingmenutest.fragment; import java.util.ArrayList; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBar; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.kale.slidingmenutest.MainActivity; import com.kale.slidingmenutest.R; import com.kale.slidingmenutest.listener.MyTabListener; import com.kale.slidingmenutest.listener.PageChangeListener; public class FirstFragment extends Fragment { ViewPager viewPager; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO 自动生成的方法存根 return inflater.inflate(R.layout.first_fragment, null); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { // TODO 自动生成的方法存根 super.onActivityCreated(savedInstanceState); //设置actionbar initViewPager(); initActionBar(); } /** */ private void initActionBar() { ActionBar actionBar = ((MainActivity)getActivity()).getSupportActionBar(); //设定有Tab actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); ActionBar.Tab tab; //开始添加Tab,这里添加4个,并且设置监听器 for (int i = 1; i <= 4; i++) { tab = actionBar.newTab(); tab.setText("Tab " + i); tab.setTabListener(new MyTabListener(viewPager)); actionBar.addTab(tab); } } private void initViewPager() { ArrayList<View> list = new ArrayList<View>(); for (int i = 0; i < 4; i++) { list.add(newTextView("第"+(i+1)+"个界面")); } viewPager = (ViewPager)getActivity().findViewById(R.id.viewPager); viewPager.setAdapter(new MyPagerAdapter(list)); viewPager.setOnPageChangeListener(new PageChangeListener((MainActivity)getActivity())); } private TextView newTextView(String text) { TextView tv = new TextView(getActivity()); tv.setText(text); tv.setTextSize(30); tv.setGravity(Gravity.CENTER); return tv; } /** * @author:Jack Tony 这里配置适配器 * @tips :这里传入一个list数组,从每个list中可以剥离一个view并显示出来 * @date :2014-9-24 */ public class MyPagerAdapter extends PagerAdapter { private ArrayList<View> mViewList; private int pagerNum = 0; public MyPagerAdapter(ArrayList<View> viewList) { mViewList = viewList; } public int getPagerNum() { return pagerNum; } @Override public int getCount() { return mViewList.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public void destroyItem(View arg0, int arg1, Object arg2) { if (mViewList.get(arg1) != null) { ((ViewPager) arg0).removeView(mViewList.get(arg1)); } } @Override public Object instantiateItem(View arg0, int arg1) { try { if (mViewList.get(arg1).getParent() == null) { ((ViewPager) arg0).addView(mViewList.get(arg1), 0); } else { /* * 很难理解新添加进来的view会自动绑定一个父类,由于一个儿子view不能与两个父类相关, * 所以得解绑不这样做否则会产生 viewpager java.lang.IllegalStateException: * The specified child already has a parent. You must call * removeView() on the child's parent first. */ ((ViewGroup) mViewList.get(arg1).getParent()) .removeView(mViewList.get(arg1)); ((ViewPager) arg0).addView(mViewList.get(arg1), 0); } } catch (Exception e) { e.printStackTrace(); } finally { pagerNum = arg1; } return mViewList.get(arg1); } } }
3.2设置ViewPager的滑动监听,滑动时要求tab也需要跟着变换,并且滑动到最左边的界面时将触控范围变为全屏有效。
PageChangeListener
package com.kale.slidingmenutest.listener; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu; import com.kale.slidingmenutest.MainActivity; public class PageChangeListener implements ViewPager.OnPageChangeListener { private ActionBarActivity activity; public PageChangeListener(ActionBarActivity activity) { this.activity = activity; } @Override public void onPageScrollStateChanged(int arg0) { // TODO 自动生成的方法存根 } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO 自动生成的方法存根 } @Override public void onPageSelected(int position) { //System.out.println("position:" + position); activity.getSupportActionBar().setSelectedNavigationItem(position); //设置在其他页面滑动时slingmenu是边缘模式,最边上页面是全屏模式(防误触) switch (position) { case 0: ((MainActivity)activity).getMySlidingMenu(). setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); break; default: ((MainActivity)activity).getMySlidingMenu(). setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN); break; } } }
3.3MyTabListener
注意:要判断viewpager是否为空
package com.kale.slidingmenutest.listener; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar.Tab; /** * @author:Jack Tony * @tips :设置tab的监听器,控制viewpager的显示 * @date :2014-7-30 */ public class MyTabListener implements ActionBar.TabListener { ViewPager viewPager; public MyTabListener(ViewPager viewPager) { this.viewPager = viewPager; } @Override public void onTabReselected(Tab arg0, FragmentTransaction arg1) { } /* 核心方法 * @see android.support.v7.app.ActionBar.TabListener#onTabSelected(android.support.v7.app.ActionBar.Tab, android.support.v4.app.FragmentTransaction) * 选中某个tab时,同时切换viewpager */ @Override public void onTabSelected(Tab tab, FragmentTransaction arg1) { if (viewPager != null && viewPager.getCurrentItem() != tab.getPosition()) { viewPager.setCurrentItem(tab.getPosition()); } } @Override public void onTabUnselected(Tab arg0, FragmentTransaction arg1) { } }
源码下载:http://download.csdn.net/detail/shark0017/7976759