之前我们对大体框架有了一定的认识,现在我们来做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) { } }