利用ViewPager+Fragment+slidingmenu侧滑组件实现的小demo
扫描二维码
随时随地手机看文章
最近折腾了很久,经过三番五次的推倒重来,总算是弄出了一个效果比较满意的侧滑demo。把主要的实现流程mark下来,方便日后翻阅,实现的效果图(手动录制的,不流畅):
从图上可以看到,demo上面有三个按钮和一个包含3个Fragment页面的ViewPager,另外左侧滑能拉出一个左页面。刚开始做的demo是直接用FragmentTabHost来实现的,并在这个基础上继承RelativeLayout写了个布局,来实现页面的侧滑效果。那个demo的效果跟这个的主要差距就是三个tab之间只能通过点击切换,没有viewpager这样的滑动切换效果。这个demo下面的三个按钮其实是三个RadioButton,只是把它前面的圆点隐藏了(demo里面没好好弄按钮上的背景效果了)。之前尝试过利用PagerTitleStrip来实现三个Tab的标签,但结果是它们会随着ViewPager不停滚动,没法固定下来。
demo主要的布局文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
android:id="@+id/pager"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/titlelayout" >
android:id="@+id/titlelayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
android:id="@+id/tab_menu"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/tab_bg_normal"
android:orientation="horizontal" >
android:id="@+id/title1"
style="@style/tab_style"
android:checked="true"
android:drawableTop="@drawable/tab_activity_selector"
android:text="活动" />
android:id="@+id/title2"
style="@style/tab_style"
android:drawableTop="@drawable/tab_friend"
android:text="工作" />
android:id="@+id/title3"
style="@style/tab_style"
android:drawableTop="@drawable/tab_friend"
android:text="圈子" />
要实现ViewPager+Fragment的滑动效果,必须继承FragmentActivity,同时要给ViewPager设置Adapter。由于ViewPager上面要加载Fragment(需要继承Fragment类),所以不是重载PagerAdapter,而是重写FragmentPagerAdapter类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MyViewPagerAdapter extends FragmentPagerAdapter {
private ArrayList
public MyViewPagerAdapter(FragmentManager fm) {
super(fm);
}
/**
* 自定义的构造函数
* @param fm
* @param fragments ArrayList
*/
public MyViewPagerAdapter(FragmentManager fm,ArrayList
super(fm);
this.fragments = fragments;
}
@Override
public Fragment getItem(int arg0) {
return fragments.get(arg0);//返回Fragment对象
}
@Override
public int getCount() {
return fragments.size();//返回Fragment的个数
}
}
写好了adapter,在主函数的onCreate()函数里面初始化ViewPager,同时给它配置adapter和设置滑动事件监听(这需要实现OnPageChangeListener接口):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 初始化视图
*/
private void initView() {
// TODO Auto-generated method stub[!--empirenews.page--]
pager=(ViewPager) findViewById(R.id.pager);//初始化控件
fragments=new ArrayList
fragments.add(new ActivityFragment());
fragments.add(new JobFragment());
fragments.add(new FriendFragment());
}
/**
* 初始化ViewPager
*/
private void initViewPager() {
// TODO Auto-generated method stub
mAdapter=new MyViewPagerAdapter(getSupportFragmentManager(), fragments);
pager.setAdapter(mAdapter);
pager.setOnPageChangeListener(this);
pager.setCurrentItem(0);//设置成当前第一个
}
/**
* OnPageChangeListener的接口函数
*/
@Override
public void onPageSelected(int arg0) {
title.get(arg0).setChecked(true);//保持页面跟按钮的联动
//下面这个条件语句里面的是针对侧滑效果的
if(arg0==0){
// 如果当前是第一页,那么设置触摸屏幕的模式为全屏模式
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);//设置成全屏响应
}else {
// 如果不是第一页,设置触摸屏幕的模式为边缘60px的地方
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
}
}
以上基本配置好了ViewPager组件,运行起来3个Fragment页面可以自由滑动了,但是下面的三个button还没有设置监听,所以viewpager切换的时候不会跟着切换,点击也不会有响应。接下来要做的就是在onCreate()里面初始化RadioButton,并给它设置OnClickListener监听点击事件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 初始化几个用来显示title的RadioButton
*/
private void initTitle() {
title.add((RadioButton) findViewById(R.id.title1));//三个title标签
title.add((RadioButton) findViewById(R.id.title2));
title.add((RadioButton) findViewById(R.id.title3));
title.get(0).setOnClickListener(new MyOnClickListener(0));//设置响应
title.get(1).setOnClickListener(new MyOnClickListener(1));
title.get(2).setOnClickListener(new MyOnClickListener(2));
}
/**
* 重写OnClickListener的响应函数,主要目的就是实现点击title时,pager会跟着响应切换
* @author llb
*/
private class MyOnClickListener implements OnClickListener{
private int index;
public MyOnClickListener(int index){
this.index=index;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
pager.setCurrentItem(index);//把viewpager的视图切过去,实现title跟pager的联动
title.get(index).setChecked(true);//设置被选中,否则布局里面的背景不会切换
}
}
最后就是实现侧滑出左边页面的效果,这里使用了开源组件SlidingMenu,具体的使用方法可百度or查看源代码。SlidingMenu组件重写了Activity、FragmentActivity、RelativeLayout等,要实现侧滑效果,可以把主函数继承的FragmentActivity改成SlidingFragmentActivity,也可以去在xml布局文件里面直接设置。这个demo里面采用的是继承SlidingFragmentActivity类,主要的初始化代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 初始化开源组件SlidingMenu
*/
private void initSlidingMenu() {
// 实例化滑动菜单对象
SlidingMenu sm = getSlidingMenu();
setContentView(R.layout.activity_main);//设置当前的视图
setBehindContentView(R.layout.left);//设置左页视图
sm.setMode(SlidingMenu.LEFT);
// 设置滑动阴影的宽度
// sm.setShadowWidthRes(R.dimen.shadow_width);
// 设置滑动阴影的图像资源
// sm.setShadowDrawable(R.drawable.shadow);
// 设置滑动菜单视图的宽度
// sm.setBehindOffsetRes(R.dimen.slidingmenu_offset);
// 设置渐入渐出效果的值
sm.setFadeDegree(0.35f);
// 设置触摸屏幕的模式
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
// sm.setTouchModeBehind(SlidingMenu.TOUCHMODE_FULLSCREEN);//设置左页的响应范围
sm.setTouchmodeMarginThreshold(60);//这个设置的是隔屏幕边缘多远开始响应
// sm.setBehindOffset(50);//设置左页距离屏幕右边缘的距离,右页会补上
WindowManager wManager=(WindowManager) getSystemService(Context.WINDOW_SERVICE);
screenWidth=wManager.getDefaultDisplay().getWidth();//获取屏幕的宽度
sm.setBehindWidth((int) (screenWidth*0.8));//设置左页的宽度
}
最后附上其中一个Fragment的示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18[!--empirenews.page--]
19
20
public class ActivityFragment extends Fragment{
private View view;//缓存页面
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(view==null){
view=inflater.inflate(R.layout.activity_fragment,container, false);
}
ViewGroup parent = (ViewGroup) view.getParent();
if(parent!=null){
parent.removeView(view);//先移除
}
return view;
}
}