使用DrawerLayout,FragmentTabHost实现测滑式底部菜单栏界面

来源:互联网 发布:英雄联盟无法连接网络 编辑:程序博客网 时间:2024/05/22 05:16

使用DrawerLayout,FragmentTabHost实现测滑式底部菜单栏界面:

首先是DrawerLayout布局

mainlayout.xml

<?xml version="1.0" encoding="utf-8"?><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">    <FrameLayout        android:layout_width="match_parent"        android:layout_height="match_parent">        <com.github.ksoichiro.android.observablescrollview.TouchInterceptionFrameLayout            xmlns:android="http://schemas.android.com/apk/res/android"            android:id="@+id/container"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:paddingBottom="60dp">    <FrameLayout        android:id="@+id/content_frame"        android:layout_width="match_parent"        android:layout_height="match_parent">        <android.support.v7.widget.Toolbar            android:id="@+id/tool_bar"            android:layout_width="match_parent"            android:layout_height="?attr/actionBarSize"            android:minHeight="?attr/actionBarSize"            android:background="@color/colorPrimary"            />        <com.drawerlayout.guohua.ui.tab.SlidingTabLayout            android:layout_width="match_parent"            android:layout_height="38dp"            android:background="@color/colorPrimary"           /></FrameLayout></com.github.ksoichiro.android.observablescrollview.TouchInterceptionFrameLayout><RelativeLayout    android:layout_width="match_parent"    android:layout_height="60dp"    android:layout_gravity="bottom"    ><android.support.v4.app.FragmentTabHost    android:id="@+id/tabhost_fragment"    android:layout_width="match_parent"    android:layout_height="match_parent"    >    <FrameLayout        android:id="@+id/tab_layout"        android:layout_width="match_parent"        android:layout_height="match_parent">    </FrameLayout></android.support.v4.app.FragmentTabHost></RelativeLayout>    </FrameLayout><fragment    android:id="@+id/nevigation_draw"    android:name="com.drawerlayout.guohua.ui.NevigationDrawerFragment"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:layout_gravity="left"    /></android.support.v4.widget.DrawerLayout>

ActionBarDrawerToggle  是 DrawerLayout.DrawerListener实现,和NevigationDrawer他他陪使用,推荐用这个方法,符合Adnroid desgin规范。

作用:
1.改变android.R.id.home返回图标。
2.Drawer拉出、隐藏,带有android.R.id.home动画效果。
3.监听Drawer拉出、隐藏;可以在activity创建完成之后:复写onPostCreate()方法 ,加入   mDrawerToggle.syncState();//该方法会自动和actionBar关联, 将开关的图片显示在了action上,如果不设置,也可以有抽屉的效果,不过是默认的图标 

 actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, null, R.string.settings, R.string.search) {            @Override            public void onDrawerClosed(View drawerView) {                super.onDrawerClosed(drawerView);            }            @Override            public void onDrawerOpened(View drawerView) {                super.onDrawerOpened(drawerView);            }        };        drawerLayout.setDrawerListener(actionBarDrawerToggle);        setSupportActionBar(toolbar);        ActionBar actionBar = getSupportActionBar();        actionBar.setDisplayHomeAsUpEnabled(true);        actionBar.setHomeButtonEnabled(true);//Activity加载完成时调用  @Override    protected void onPostCreate(Bundle savedInstanceState) {        super.onPostCreate(savedInstanceState);        //需要将ActionDrawerToggle与DrawerLayout的状态同步        //将ActionBarDrawerToggle中的drawer图标,设置为ActionBar中的Home-Button的Icon        actionBarDrawerToggle.syncState();    }



FragmentTabHost:来自于android.support.v4.app这个包下,继承自TabHost,并且实现了TabHost.OnTabChangeListener接口(FragmentTabHost)findViewById(android.R.id.tabhost);先把tabhost找到,也可以把context传进去直接new出来然后对FragmentTabHost进行初始化操作
在activity中:mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
在fragment中:mTabHost.setup(this, getChildFragmentManager(), R.id.realtabcontent);说明是他子fragment的manager。创建Tab
tabhostFragment.setup(this, getSupportFragmentManager(), R.id.content_frame);


 setIndicator(CharSequence label);
setIndicator(CharSequence label, Drawable icon);
setIndicator(View view)
从参数名字就可以看出来,就不多做解释,其中一和二是系统提供的布局,第三种可以自定义自己想要的view。
其实到这个地方已经大功告成。我们不需要add,replace等等一切对fragment的操作,FragmentTabHost非常强大,他会对所添加的fragment进行管理,保存栈信息和恢复栈信息等一切操作,比如我的fragment内部有三个子fragment,我退出该fragment的时候开启的是第二个子fragment,下次我再进入该fragment的时候依然会开启第二个子fragment,且看FragmentTabHost源码中对保存,和恢复的操作:
protected Parcelable onSaveInstanceState() {    Parcelable superState = super.onSaveInstanceState();    SavedState ss = new SavedState(superState);    ss.curTab = getCurrentTabTag();    return ss;  }  @Override  protected void onRestoreInstanceState(Parcelable state) {    SavedState ss = (SavedState)state;    super.onRestoreInstanceState(ss.getSuperState());    setCurrentTabByTag(ss.curTab);  }


在该fragment退出的时候会自动执行onSaveInstanceState()方法,把当前打开的fragment的TabTag通过Parcelable的方式记录下来,然后当再次进入到该fragment的时候会自动执行OnRestoreInstanceState(Parcelable state)方法,把之前保存的状态恢复,打开记录的TabTag对应的fragment通过代码实际检验,即使退出的时候是打开的第二个fragment,但是再次进来的时候也会执行一遍第一个fragment的生命周期方法,主要是因为tabhost要有一个默认的打开界面。
且看他的addTab方法
public void addTab(TabHost.TabSpec tabSpec, Class&lt;?&gt; clss, Bundle args) {    tabSpec.setContent(new DummyTabFactory(mContext));    String tag = tabSpec.getTag();    TabInfo info = new TabInfo(tag, clss, args);    if (mAttached) {      // If we are already attached to the window, then check to make      // sure this tab's fragment is inactive if it exists.  This shouldn't      // normally happen.      info.fragment = mFragmentManager.findFragmentByTag(tag);      if (info.fragment != null &amp;&amp; !info.fragment.isDetached()) {        FragmentTransaction ft = mFragmentManager.beginTransaction();        ft.detach(info.fragment);        ft.commit();      }    }    mTabs.add(info);    addTab(tabSpec);  }


最后一句是addTab(tabSpec),这是他的父类TabHost的方法,跟踪一下addTab方法,发现他有这样一句代码:
if (mCurrentTab == -1) {            setCurrentTab(0);        }
也就是当前没有Tab的时候,会指定第0个元素为当前的Tab。所以会执行他的生命周期方法。
另外FragmentTabHost还有一个重要的方法就是setOnTabChangedListener(TabHost.OnTabChangeListener l)
就是当页面发生变化的时候,设置回调监听接口,这个接口只有一个方法 public void onTabChanged(String tabId),其实参数就是Tab的Tag。







0 0