天天看點

Android Toolbar+DrawerLayout+PagerSlidingTabStrip實作仿csdn側滑菜單

Toolbar是Android5.0新出的一個工具欄,相對于ActionBar ToolBar的位置可以随意擺放,DrawerLayout則是SlidingDrawer的更新版,我們知道SlidingDeawer并不是是支援所有方向的拉動,它隻支援從右到左,從下到上,是以有一定的局限性,而DrawerLayout則可以随意設定,PagerSlidingTabStrip是github上的一個開源庫,它是配合viewPager使用的一個導航欄。下面來一步步實作我們的目标。

首先先從github上吧這個項目拷下來,其實這就一個類繼承了水準的ScrollView,然後自定義了一些屬性,是以我就直接把這個類複制到項目中,源碼最後會給出,或者可以直接在github上下載下傳,下載下傳的連結為:https://github.com/astuetz/PagerSlidingTabStrip,可以下載下傳然後把這個類拷貝到項目中作為一個工具類使用,它需要一些自定義的屬性,是以直接将屬性拷貝到values/attrs.xml檔案夾下面,屬性為:

<declare-styleable name="PagerSlidingTabStrip">
        <attr name="pstsIndicatorColor" format="color" />
        <attr name="pstsUnderlineColor" format="color" />
        <attr name="pstsDividerColor" format="color" />
        <attr name="pstsIndicatorHeight" format="dimension" />
        <attr name="pstsUnderlineHeight" format="dimension" />
        <attr name="pstsDividerPadding" format="dimension" />
        <attr name="pstsTabPaddingLeftRight" format="dimension" />
        <attr name="pstsScrollOffset" format="dimension" />
        <attr name="pstsTabBackground" format="reference" />
        <attr name="pstsShouldExpand" format="boolean" />
        <attr name="pstsTextAllCaps" format="boolean" />
    </declare-styleable>
           

然後還有一個tab背景選擇器,放在了drawable檔案夾下面;

拷貝完成之後我們的準備工作就做好了,下面是代碼一步步實作,首先是頁面布局:

<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.widget.DrawerLayout
        android:id="@+id/dl"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!-- 内容-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:background="#ffffff"
                android:minHeight="?attr/actionBarSize">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:text="頭條"
                    android:textColor="#000"
                    android:textSize="16sp" />

                <ImageView
                    android:layout_width="16dp"
                    android:layout_height="16dp"
                    android:layout_gravity="center_vertical|right"
                    android:layout_marginRight="20dp"
                    android:src="@drawable/search" />

                <ImageView
                    android:layout_width="16dp"
                    android:layout_height="16dp"
                    android:layout_gravity="center_vertical|right"
                    android:layout_marginRight="20dp"
                    android:src="@drawable/add_attention" />
            </android.support.v7.widget.Toolbar>

            <com.sjr.toolbar.PagerSlidingTabStrip
                android:id="@+id/pss_tab"
                android:layout_width="match_parent"
                android:layout_height="48dp" />

            <android.support.v4.view.ViewPager
                android:id="@+id/vp_fragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>

        <!-- 側滑菜單 -->

        <LinearLayout
            android:id="@+id/ll_drawer"
            android:layout_width="200dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@drawable/drawer"
            android:orientation="vertical"
            android:padding="8dp">
            <!--這裡可以放側滑菜單的界面布局-->
        </LinearLayout>
    </android.support.v4.widget.DrawerLayout>

</LinearLayout>
           

因為Toolbar是跟着内容一起被左邊側滑菜單覆寫的是以我把它包在了内容布局裡面,這也是Toolbar的一個優勢,我們可以直接把它當做一個ViewGroup來使用,它的位置可以随意擺放,内容部分的布局我用了一個線性布局,将Toobar、PagerSlidingTabStrip、ViewPager依次擺放,左邊的側滑菜單布局可以照着業務需求進行布局,這裡為了省事我直接截了一張圖..布局說明完畢,下面是MainActivity的邏輯實作:

public class MainActivity extends AppCompatActivity {

    private Toolbar mToolbar;
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    private PagerSlidingTabStrip mPagerSlidingTabStrip;
    private ViewPager mViewPager;
    private final String[] mDatas = {"最新", "前端", "移動開發", "語言", "遊戲&圖像"
            , "系統&安全", "loT", "資料庫", "業界"
            , "雲計算", "大資料", "研發工具", "軟體工程"};
    private List<Fragment> container;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initFragment();
        initDatas();
    }


    private void initView() {
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.dl);
        mPagerSlidingTabStrip = (PagerSlidingTabStrip) findViewById(R.id.pss_tab);
        mViewPager = (ViewPager) findViewById(R.id.vp_fragment);

        mToolbar.setTitle("");//把Toolbar的标題設定為空
        setSupportActionBar(mToolbar);//設定Toolbar
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar,
                R.string.drawer_open, R.string.drawer_close);//觸發器
        mDrawerToggle.syncState();//同步狀态
        mDrawerLayout.addDrawerListener(mDrawerToggle);//設定監聽
    }

    private void initFragment() {
        container = new ArrayList<>();
        for (int i = 1; i <= mDatas.length; i++) {//這裡應該是根據實際業務添加Fragment,我為了示範是以直接循環添加一個Fragment而已
            TestFragment fragment = new TestFragment();
            container.add(fragment);
        }
    }

    private void initDatas() {
        mViewPager.setAdapter(new MPagerAdapter(getSupportFragmentManager()));//viewpager設定擴充卡
        mPagerSlidingTabStrip.setViewPager(mViewPager);//把viewpager跟pagerSlidingTabStrip進行綁定

        mPagerSlidingTabStrip.setTextSize(40); //标簽字型大小
        mPagerSlidingTabStrip.setIndicatorColor(Color.BLUE); //标簽下的橫線顔色
        mPagerSlidingTabStrip.setIndicatorHeight(4);//标簽下的橫線高度
        mPagerSlidingTabStrip.setIndicatorColor(Color.RED);//标簽下橫線的顔色
        mPagerSlidingTabStrip.setDividerColor(Color.TRANSPARENT);//每個标簽間的分割線
        mPagerSlidingTabStrip.setBackgroundColor(Color.parseColor("#F6F6F6"));//标簽背景
        mPagerSlidingTabStrip.setSelectedTextColor(Color.RED);//選中标簽的文字顔色
        mPagerSlidingTabStrip.setTextColor(Color.BLACK);//标簽顔色
    }


    public class MPagerAdapter extends FragmentStatePagerAdapter {


        public MPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mDatas[position];
        }

        @Override
        public int getCount() {
            return container == null ? 0 : container.size();
        }

        @Override
        public Fragment getItem(int position) {
            return container == null ? null : container.get(position);
        }

    }
}
           

我覺得我注釋已經寫得很詳細了..這裡就不再多累贅,值得說一說的是FragmentStatePagerAdapter,之是以不用FragmentPagerAdapter是因為他們的緩存政策是不同的,FragmentPagerAdapter會對浏覽過的Fragment進行緩存,對每個界面都緩存當界面一多時就會增加程式占用的記憶體,還有一個是當我們滑動幾個Fragment之後再傳回第一個時會出現空白。而FragmentStatePagerAdapter會儲存目前界面,下一個界面和上一個界面(如果有),其他的會銷毀,注意的是使用FragmentStatePagerAdapter可能會有記憶體回收不正常的情況,比如Fragment上有EditText儲存了焦點而造成Fragment沒有被正常回收,這種情況可能會造成記憶體溢出。是以當tabs少的時候就是用FragmentPagerAdapter,而tabs多的時候就是用FragmentStatePagerAdapter。

到這裡就已經完成需求了,下面是demo的效果(請原諒我不會錄制視訊...):

Android Toolbar+DrawerLayout+PagerSlidingTabStrip實作仿csdn側滑菜單
Android Toolbar+DrawerLayout+PagerSlidingTabStrip實作仿csdn側滑菜單
Android Toolbar+DrawerLayout+PagerSlidingTabStrip實作仿csdn側滑菜單

demo源碼:http://download.csdn.net/detail/lxzmmd/9522072

繼續閱讀