利用ViewPager+Fragment+slidingmenu側(cè)滑組件實(shí)現(xiàn)的小demo
掃描二維碼
隨時(shí)隨地手機(jī)看文章
最近折騰了很久,經(jīng)過(guò)三番五次的推倒重來(lái),總算是弄出了一個(gè)效果比較滿意的側(cè)滑demo。把主要的實(shí)現(xiàn)流程mark下來(lái),方便日后翻閱,實(shí)現(xiàn)的效果圖(手動(dòng)錄制的,不流暢):
從圖上可以看到,demo上面有三個(gè)按鈕和一個(gè)包含3個(gè)Fragment頁(yè)面的ViewPager,另外左側(cè)滑能拉出一個(gè)左頁(yè)面。剛開(kāi)始做的demo是直接用FragmentTabHost來(lái)實(shí)現(xiàn)的,并在這個(gè)基礎(chǔ)上繼承RelativeLayout寫了個(gè)布局,來(lái)實(shí)現(xiàn)頁(yè)面的側(cè)滑效果。那個(gè)demo的效果跟這個(gè)的主要差距就是三個(gè)tab之間只能通過(guò)點(diǎn)擊切換,沒(méi)有viewpager這樣的滑動(dòng)切換效果。這個(gè)demo下面的三個(gè)按鈕其實(shí)是三個(gè)RadioButton,只是把它前面的圓點(diǎn)隱藏了(demo里面沒(méi)好好弄按鈕上的背景效果了)。之前嘗試過(guò)利用PagerTitleStrip來(lái)實(shí)現(xiàn)三個(gè)Tab的標(biāo)簽,但結(jié)果是它們會(huì)隨著ViewPager不停滾動(dòng),沒(méi)法固定下來(lái)。
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="活動(dòng)" />
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="圈子" />
要實(shí)現(xiàn)ViewPager+Fragment的滑動(dòng)效果,必須繼承FragmentActivity,同時(shí)要給ViewPager設(shè)置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);
}
/**
* 自定義的構(gòu)造函數(shù)
* @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對(duì)象
}
@Override
public int getCount() {
return fragments.size();//返回Fragment的個(gè)數(shù)
}
}
寫好了adapter,在主函數(shù)的onCreate()函數(shù)里面初始化ViewPager,同時(shí)給它配置adapter和設(shè)置滑動(dòng)事件監(jiān)聽(tīng)(這需要實(shí)現(xiàn)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);//設(shè)置成當(dāng)前第一個(gè)
}
/**
* OnPageChangeListener的接口函數(shù)
*/
@Override
public void onPageSelected(int arg0) {
title.get(arg0).setChecked(true);//保持頁(yè)面跟按鈕的聯(lián)動(dòng)
//下面這個(gè)條件語(yǔ)句里面的是針對(duì)側(cè)滑效果的
if(arg0==0){
// 如果當(dāng)前是第一頁(yè),那么設(shè)置觸摸屏幕的模式為全屏模式
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);//設(shè)置成全屏響應(yīng)
}else {
// 如果不是第一頁(yè),設(shè)置觸摸屏幕的模式為邊緣60px的地方
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
}
}
以上基本配置好了ViewPager組件,運(yùn)行起來(lái)3個(gè)Fragment頁(yè)面可以自由滑動(dòng)了,但是下面的三個(gè)button還沒(méi)有設(shè)置監(jiān)聽(tīng),所以viewpager切換的時(shí)候不會(huì)跟著切換,點(diǎn)擊也不會(huì)有響應(yīng)。接下來(lái)要做的就是在onCreate()里面初始化RadioButton,并給它設(shè)置OnClickListener監(jiān)聽(tīng)點(diǎn)擊事件:
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
/**
* 初始化幾個(gè)用來(lái)顯示title的RadioButton
*/
private void initTitle() {
title.add((RadioButton) findViewById(R.id.title1));//三個(gè)title標(biāo)簽
title.add((RadioButton) findViewById(R.id.title2));
title.add((RadioButton) findViewById(R.id.title3));
title.get(0).setOnClickListener(new MyOnClickListener(0));//設(shè)置響應(yīng)
title.get(1).setOnClickListener(new MyOnClickListener(1));
title.get(2).setOnClickListener(new MyOnClickListener(2));
}
/**
* 重寫OnClickListener的響應(yīng)函數(shù),主要目的就是實(shí)現(xiàn)點(diǎn)擊title時(shí),pager會(huì)跟著響應(yīng)切換
* @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的視圖切過(guò)去,實(shí)現(xiàn)title跟pager的聯(lián)動(dòng)
title.get(index).setChecked(true);//設(shè)置被選中,否則布局里面的背景不會(huì)切換
}
}
最后就是實(shí)現(xiàn)側(cè)滑出左邊頁(yè)面的效果,這里使用了開(kāi)源組件SlidingMenu,具體的使用方法可百度or查看源代碼。SlidingMenu組件重寫了Activity、FragmentActivity、RelativeLayout等,要實(shí)現(xiàn)側(cè)滑效果,可以把主函數(shù)繼承的FragmentActivity改成SlidingFragmentActivity,也可以去在xml布局文件里面直接設(shè)置。這個(gè)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
/**
* 初始化開(kāi)源組件SlidingMenu
*/
private void initSlidingMenu() {
// 實(shí)例化滑動(dòng)菜單對(duì)象
SlidingMenu sm = getSlidingMenu();
setContentView(R.layout.activity_main);//設(shè)置當(dāng)前的視圖
setBehindContentView(R.layout.left);//設(shè)置左頁(yè)視圖
sm.setMode(SlidingMenu.LEFT);
// 設(shè)置滑動(dòng)陰影的寬度
// sm.setShadowWidthRes(R.dimen.shadow_width);
// 設(shè)置滑動(dòng)陰影的圖像資源
// sm.setShadowDrawable(R.drawable.shadow);
// 設(shè)置滑動(dòng)菜單視圖的寬度
// sm.setBehindOffsetRes(R.dimen.slidingmenu_offset);
// 設(shè)置漸入漸出效果的值
sm.setFadeDegree(0.35f);
// 設(shè)置觸摸屏幕的模式
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
// sm.setTouchModeBehind(SlidingMenu.TOUCHMODE_FULLSCREEN);//設(shè)置左頁(yè)的響應(yīng)范圍
sm.setTouchmodeMarginThreshold(60);//這個(gè)設(shè)置的是隔屏幕邊緣多遠(yuǎn)開(kāi)始響應(yīng)
// sm.setBehindOffset(50);//設(shè)置左頁(yè)距離屏幕右邊緣的距離,右頁(yè)會(huì)補(bǔ)上
WindowManager wManager=(WindowManager) getSystemService(Context.WINDOW_SERVICE);
screenWidth=wManager.getDefaultDisplay().getWidth();//獲取屏幕的寬度
sm.setBehindWidth((int) (screenWidth*0.8));//設(shè)置左頁(yè)的寬度
}
最后附上其中一個(gè)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;//緩存頁(yè)面
@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;
}
}