Fragment实战案例

对于Fragment,《Android编程权威指南》的作者极力推崇,坚持AUF(Always Use Fragment)原则,即总是使用Fragment。Fragment本身占用内存比Activity少很多,在流畅性,性能上具有很大的优势,尤其是在中低端手机上。此外,如果你的应用需要移植到平板上的话,那使用Fragment更是你的不二之选。
本文就是通过一个实战案例来解剖一下Fragment。
效果图:
Fragment实战案例_第1张图片
Fragment实战案例_第2张图片
Fragment实战案例_第3张图片
Fragment实战案例_第4张图片
主界面是一个空的FrameLayout,这里我们将添加一个HomeFragment来显示首页内容,此外还有一个抽屉菜单,这里我们用NavigationView来实现,既然官方提供了这个控件,感觉我们也就没必要来自己写一个侧滑栏了。


<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <FrameLayout
        android:id="@+id/fl_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    FrameLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer"/>

android.support.v4.widget.DrawerLayout>

其中属性app:headerLayout=”@layout/nav_header_main”中的nav_header_main就是布局左上角的图标以及一些用户名信息等,app:menu=”@menu/activity_main_drawer”中的activity_main_drawer就是菜单栏。
接下来就需要把我们的HomeFragment加载进来了

if (savedInstanceState == null) {
            loadRootFragment(R.id.fl_container, HomeFragment.newInstance());
        }

其中的loadRootFragment如果在Activity使用,则本质是FragmentActivity.getSupportFragmentManager().getTopFragment().start(f);

如果在Fragment中使用,则是Fragment.getFragmentManager().start(f);
然后是初始化抽屉菜单:

private void initView() {
        mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawer, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
//        mDrawer.setDrawerListener(toggle);
        toggle.syncState();

        mNavigationView = (NavigationView) findViewById(R.id.nav_view);
        mNavigationView.setNavigationItemSelectedListener(this);
        mNavigationView.setCheckedItem(R.id.nav_home);//默认点击栏

        LinearLayout llNavHeader = (LinearLayout) mNavigationView.getHeaderView(0);
        mTvName = (TextView) llNavHeader.findViewById(R.id.tv_name);
        mImgNav = (ImageView) llNavHeader.findViewById(R.id.img_nav);
        llNavHeader.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDrawer.closeDrawer(GravityCompat.START);

                mDrawer.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        goLogin();
                    }
                }, 250);
            }
        });
    }

为了实现侧滑栏的点击事件,我们需要实现OnNavigationItemSelectedListener中的onNavigationItemSelected方法:

@Override
    public boolean onNavigationItemSelected(final MenuItem item) {
        mDrawer.closeDrawer(GravityCompat.START);

        mDrawer.postDelayed(new Runnable() {
            @Override
            public void run() {
                int id = item.getItemId();

                final SupportFragment topFragment = getTopFragment();

                if (id == R.id.nav_home) {
                    HomeFragment fragment = findFragment(HomeFragment.class);
                    Bundle newBundle = new Bundle();
                    newBundle.putString("from", "主页来自-->" + topFragment.getClass().getSimpleName());
                    fragment.putNewBundle(newBundle);

                    start(fragment, SupportFragment.SINGLETASK);
                } else if (id == R.id.nav_discover) {
                    DiscoverFragment fragment = findFragment(DiscoverFragment.class);
                    if (fragment == null) {
                        popTo(HomeFragment.class, false, new Runnable() {
                            @Override
                            public void run() {
                                start(DiscoverFragment.newInstance());
                            }
                        });
                    } else {
                        // 如果已经在栈内,则以SingleTask模式start
                        start(fragment, SupportFragment.SINGLETASK);
                    }
                } else if (id == R.id.nav_msg) {
                    ShopFragment fragment = findFragment(ShopFragment.class);
                    if (fragment == null) {
                        popTo(HomeFragment.class, false, new Runnable() {
                            @Override
                            public void run() {
                                start(ShopFragment.newInstance());
                            }
                        });
                    } else {
                        // 如果已经在栈内,则以SingleTask模式start,也可以用popTo
//                        start(fragment, SupportFragment.SINGLETASK);
                        popTo(ShopFragment.class, false);
                    }
                } else if (id == R.id.nav_login) {
                    goLogin();
                } else if (id == R.id.nav_swipe_back) {
                    startActivity(new Intent(MainActivity.this, SwipeBackSampleActivity.class));
                } else if (id == R.id.nav_swipe_back_f) {
                    start(SwipeBackSampleFragment.newInstance());
                }
            }
        }, 250);

        return true;
    }

接着就是根据各自的点击栏实现相应的Fragment,还有一些细节需要看相应的代码,文末提供源码。

你可能感兴趣的:(android历程)