现在很多APP的布局都是使用了侧滑菜单,实现侧滑菜单有很多的方式,像开源的SlidingMenu和PagerSlidingTabStrip。同时谷歌官方也在support-v4的包中提供了相应的原生控件DrewerLayout。下面来学习使用这个控件,并结合ActionBar实现Tab的侧滑功能。
先来看一下最终的效果图。
看一下项目的基本结构
ActionBarTab是主界面,DepthPageTransformer是Fragment的切换效果的实现类,fragment1,2,3是Fragment的子类,MenuAdapter是左侧侧滑菜单ListView的适配器,SectionPagerAdapter是ViewPager的适配器。
下面我们再来说说布局文件的实现,想要使用DrawerLayout,首先我们要先在布局文件中声明
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#ccffffff"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>
这里使用DrawerLyout有一些需要注意的事情,这里DrawerLyout必须作为根布局。我们在里面放了ViewPager来实现滑动的功能,Listview就是侧滑菜单。如果需要控制侧滑菜单的滑出方向,可以设置 layout_gravity的属性,为Left|Right或者start|end。要控制滑出的距离,可以设置layout_width属性。其中DrawerLayout的第一个子控件的宽和高必须是match_parent。
定义好了布局文件,我们就要把DrawerLyout和我们的Activity结合起来,android为我们提供了 ActionBarDrawerToggle,顾名思义,这是一个ToggleButton
mActionBarDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, R.string.drawer_open,
R.string.drawer_close){
@Override
public void onDrawerClosed(View drawerView) {
invalidateOptionsMenu();
}
@Override
public void onDrawerOpened(View drawerView) {
invalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);
并通过
DrawerLyout.setDrawerListener 与DrawerLyout进行绑定。在ActionBarDrawerToggle中重写了onDrawerClosed和onDrawerOpened方法,但是我们注意到,这两个方法并不直接控制侧滑菜单的打开与关闭,而是通过一个 invalidateOptionsMenu()方法,让系统去调用onPrepareoptionsMenu()进行操作。那么我们应该怎么去操作菜单的开关呢?
我们可以在onOptionsItemSelected(MenuItem item)进行操作,当然之前也需要重写onCreateOptionsMenu(Menu menu)方法。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mActionBarDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
下面我们再来设置Tab页面,整改页面的实现是通过一个ViewPanger和ActionBar.Tab组成。ViewPager,这是一个我们常用的控件,我们可以添加一个适配器,然后在里面进行Fragment的切换操作。重点是怎么讲ViewPager的切换与ActionBar.Tab进行结合。
首先我们应该初始化ActionBar.并将ActionBar设置成导航模式
actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayHomeAsUpEnabled(true);
然后我们来组合
mViewPager.setAdapter(mSectionPagerAdapter);
//ViewPager的切换效果
mViewPager.setPageTransformer(true, new DepthPageTransformer());
//缓存数量
mViewPager.setOffscreenPageLimit(3);
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
actionBar.setSelectedNavigationItem(arg0);
//Log.e(TAG, arg0+"");
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
Log.e(TAG, "arg0--"+arg0+" agr1--"+arg1+" arg2--"+arg2);
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
Log.e(TAG, "onPageScrollStateChanged--"+arg0+"");
}
});
//添加tab
for(int i=0;i<mSectionPagerAdapter.getCount();i++){
actionBar.addTab(actionBar.newTab().
setText(mSectionPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
还需要滑动之后改变Tab的选项,我们要在 onPageSelected中根据pos进行设置即可。如果要点击tab然后切换到相应的选项卡,我们需要实现ActionBar.TabListener 接口。
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
同时我们重写onPostCreate和onConfigurationChanged方法。
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mActionBarDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mActionBarDrawerToggle.onConfigurationChanged(newConfig);
}
这时我们设置的是默认情况下的ActionBar的Tab的模式,
这个模式会占用屏幕的空间,而且也不是很美观,我们可以将Tab嵌入到ActionBar中,实现类似这样的效果
修改的方法有很多,有种比较简单的方法进行修改。我们可以通过反射来修改ActionBar中的方法
private void enableEmbeddedTabs(Object actionBar){
try {
Method setHasEmbeddedTabsMethod = actionBar.getClass().getDeclaredMethod("setHasEmbeddedTabs", boolean.class);
setHasEmbeddedTabsMethod.setAccessible(true);
setHasEmbeddedTabsMethod.invoke(actionBar, true);
} catch (Exception e) {
// TODO: handle exception
}
}
然后在onCreate方法中进行调用,这样我们的Tab就会嵌入到ActionBar中。
参考文章
http://blog.csdn.net/zhaokaiqiang1992/article/details/40585677
关于ActionBar的相关修改参考
http://segmentfault.com/blog/codethink/1190000000672903?bd_source_light=4746641
第一次写博客,参考很多,技术不好,实力不行,继续努力。