目录:

1、我的手机助手简介

2、DrawerLayout+NavigationLayout实现侧滑菜单

3、使用ToolBar代替ActionBar,与侧滑菜单进行整合

4、TabLayout+ViewPager+Fragment实现可滑动的顶部菜单

1. 我的手机助手简介  

App的排行,分类,推荐,搜索功能。提供App的下载,支持多个App同时下载以及断点续传。有应用安装管理模块,能够卸载已经安装的应用,提醒需要升级的应用。同时还具有安装包管理、登录等功能。

2. DrawerLayout+NavigationLayout实现侧滑菜单

App的主内容界面下,通过侧滑或者点击相应按钮实现打开侧滑菜单。一般侧滑菜单里面含有一些设置信息,用户信息。下图是一个典型的DrawerLayout侧滑事件触发后的例图:

android commandline toolsg下载 my android tools pro_侧滑菜单

NavigationLayout控件。NavigationLayout包括两个布局,一是上方的HeaderLayout,用于显示一些用户信息;二是下方的Menu,显示一些选项。下面分步骤讨论侧滑菜单的具体实现细节:

1、首先,要以android.support.v4.widget.DrawerLayout为根控件。在DrawerLayout下面包含两个控件:

LinearLayout布局实现);

  二是侧滑控件,采用android.support.design.widget.NavigationView控件来实现。

2、将DrawerLayout定义好后,便要在MainActivity中获取到其控件,并且加上相应监听器,使其能够相应侧滑事件。

android commandline toolsg下载 my android tools pro_控件_02

DrawerLayout绑定上监听事件。

android commandline toolsg下载 my android tools pro_控件_03

3、内容控件的总布局是在一个LinearLayout下进行处理,内部可以采用各种布局。比如说我们后面要是用的ToolBar+TabLayout+ViewPager实现滑动菜单的布局。如下图所示:

android commandline toolsg下载 my android tools pro_移动开发_04

4、侧滑控件NavigationLayout一共包含两个控件,一是头布局HeaderView,二是下方菜单布局menu。下面是设置NavigationLayout的布局代码:

<android.support.design.widget.NavigationView
     android:layout_width="320dp"
     android:layout_height="match_parent"
     android:id="@+id/design_navigation_view"
     app:headerLayout="@layout/layout_header" //引入头布局文件
     app:menu="@menu/menu_left" //引入menu文件夹下的menu文件
     android:layout_gravity="start"> //设置其从左边滑出
 </android.support.design.widget.NavigationView>

NavigationLayout的头部以及菜单中的各项均可以单独设置点击事件,设置方法如下:

//分别获取HeaderView以及菜单中的Item以及为他们注册点击事件

@BindView(R.id.design_navigation_view)
 NavigationView mNavigationView;
 private View HeaderView;HeaderView = mNavigationView.getHeaderView(0); //获取头部对应的View
 HeaderView.setOnClickListener(new View.OnClickListener(){  //为头部注册点击事件
     @Override //添加具体点击头部的事件处理逻辑
     public void onClick(View v) {
     }
 });

//为菜单中各项注册点击事件,注意要先获取到各个item的id,根据id来判断执行哪一段代码

mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener(){
     @Override
     public boolean onNavigationItemSelected(@NonNull MenuItem item) {
         int id = item.getItemId();
         switch (id){
             case R.id.menu_app_update:  //添加相应点击menu_app_update的处理代码
                 break;
             case R.id.menu_message://添加相应点击menu_message的处理代码
                 break;
             case R.id.menu_setting://添加相应点击menu_setting的处理代码
                 break;
         }
         return false;
     }
 });

3.使用ToolBar代替ActionBar,与侧滑菜单进行整合

ToolBar,必须先了解清楚默认使用的ActionBar。ActionBar是开发安卓软件时默认使用的一个布局头部,一般只显示一段固定的文字,也有一些扩展的显示按钮等功能。首先我们看看AndroidManifest文件中的如下代码:

<application
    android:allowBackup="true" //表示允许在adb调试下,不获取root权限就能备份数据
    android:icon="@mipmap/ic_launcher"//设置应用图标
    android:label="@string/app_name"//设置应用名称
    android:supportsRtl="true"//设置支持强制从左到右布局
    android:theme="@style/AppTheme"> //关键在此,设置当前应用style为AppTheme

显然我们要看看AppTheme中的代码:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!—在此处自定义相关属性-->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>
  上面四段代码一共设置了四个属性。首先设置了AppTheme继承自系统自带的一个主题Theme.AppCompat.Light.NoActionBar。表示是不带ActionBar的主题。下面的元素colorPrimary表示ActionBar的背景颜色,colorPrimaryDark表示状态栏颜色,colorAccent表示强调提示颜色,比如说点击了某个按钮,变化提示的颜色。还有一些元素比如textColorPrimary设置ActionBar中文字颜色,windowBackground设置主显示区背景颜色等。

NoActionBar,因此就可以使用自己定义的ToolBar。典型的ToolBar设置代码如下所示:

<android.support.v7.widget.Toolbar
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:id="@+id/tool_bar"
     android:minHeight="?attr/actionBarSize"  //设置最小高度为actionBarSize
     android:background="?attr/colorPrimary" //背景颜色为colorPrimary,可以修改
     app:title="@string/app_name"  //ToolBar文字设置为string资源中的app_name
    app:titleTextColor=”@color/mywhite” //设置标题颜色为白色
    android:theme="@style/AppTheme.ToolBar">//风格设置为style中的AppTheme.ToolBar</android.support.v7.widget.Toolbar>

AppTheme.ToolBar单独设置了ToolBar的Navigation图标以及图标的颜色,代码如下:

<style name="AppTheme.ToolBar" parent="AppTheme">

     <item name="drawerArrowStyle">@style/AppTheme.DrawerArrowToggle</item>
     <item name="android:windowActionBarOverlay">@style/ActionButton.Overflow</item>
     <item name="actionOverflowButtonStyle">@style/ActionButton.Overflow</item>
 </style>

<style  name="ActionButton.Overflow"parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
    <item name="android:src">@mipmap/ic_menu_more_overflow</item>
 </style> <style name="AppTheme.DrawerArrowToggle" parent="Base.Widget.AppCompat.DrawerArrowToggle">
     <item name="color">@android:color/white</item>
 </style>

xml文件中定义好后,要在activity代码文件中获取到该控件,为其加载菜单,初始化状态,设置监听等。ToolBar的菜单布局文件也是在menu中设置,注意menu中的各个item可以设置其showAsAction属性。always表示永远显示在ToolBar中,ifRoom表示有空间时显示,never则表示隐藏在菜单之中。



@BindView(R.id.tool_bar)
Toolbar mToolbar;

mToolbar.inflateMenu(R.menu.toolbar_menu); //为ToolBar设置右边菜单
ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle (this,mDrawerLayout, mToolbar, R.string.open, R.string.close);
drawerToggle.syncState();
mDrawerLayout.addDrawerListener(drawerToggle);//设置监听



注意,之前单独为DrawerLayout设置了监听事件,现在可以直接将drawerToggle作为监听器传给DrawerLayout的实例。

4. TabLayout+ViewPager+Fragment实现可滑动的顶部菜单

ToolBar下是本应用的内容显示界面。一共分为四个部分,利用TabLayout来实现这四个标签,利用ViewPager+Fragment实现下方四个显示区域。其中,TabLayout是与ViewPager绑定的,通过Tablayout的setupWithViewPager(viewpager)方法就能将两者绑定,当viewpager发生改变时,就实时更新到上方的TabLayout。下面是具体的实现步骤:

1、 在ToolBar下方添加好TabLayout以及ViewPager。代码如下:

android.support.design.widget.TabLayout
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:id="@+id/tab_layout"

<!-- fixed表示,如果有更多的内容则可以一直向右滑出屏幕范围-->
    app:tabMode="fixed">

</android.support.design.widget.TabLayout>
<!-- 下面是设置ViewPager-->

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

</android.support.v4.view.ViewPager>

activity文件中,获取到TabLayout以及ViewPager的控件实例。首先要为ViewPager设置内容适配器,使用的是setAdapter(adapter)方法。其次要将ViewPager与TabLayout绑定起来。下面是设置代码:

  



1   PagerAdapter adapter = new ViewPageAdapter(getSupportFragmentManager());
2   mViewPager.setAdapter(adapter);//为mViewPager设置内容适配器
3   mTabLayout.setupWithViewPager(mViewPager);//将ViewPager与mTabLayout绑定



 

接下来详细讲述,ViewPager的内容适配器adapter的创建方法。

ViewPager要继承FragmentStatePagerAdapter(相对于FragmentPagerAdapter,当page不为用户所见时,仅仅保留该碎片的状态,能够以较小的内存代价维持信息显示)。下面根据实际代码进行分析:



public class ViewPageAdapter extends FragmentStatePagerAdapter {
//建立FragmentInfo的List来保存相应的碎片信息(为什么不是Fragment下面再谈)
  private List<FragmentInfo> mFragments = new ArrayList<>(4);  
//有参构造函数,接收一个碎片管理对象FragmentManager
    public ViewPageAdapter(FragmentManager fm){     
        super(fm);
        initFragment();
    }
  private void initFragment(){
        //将具体的碎片添加到mFragments中,添加顺序决定了显示顺序
        mFragments.add(new FragmentInfo("推荐",RecommendFragment.class)); 
        mFragments.add(new FragmentInfo ("排行", RankingFragment.class));
 
        mFragments.add(new FragmentInfo ("游戏", GamestFragment.class));
        mFragments.add(new FragmentInfo ("分类", CategortFragment.class));
  }
  /*getItem()是继承自FragmentStatePagerAdapter必须要重写的方法,根据位置返回Fragment。可以推测,将此内容适配器传入ViewPager时,肯定会调用这个方法,分别获取到四个碎片对象,从而将内容适配好。
    */ 
    @Override 
    public Fragment getItem(int position) {
        try {
             return (Fragment)mFragments.get(position).getFragment(). newInstance(); //返回对应位置的碎片的实例。
        } catch (InstantiationException e) {
            e.printStackTrace();
        }catch (IllegalAccessException e){
            e.printStackTrace();
        }
        return  null;
    }
    //也是必须重写的方法,可以确定到底有几个碎片,方便getItem()方法知道范围
    @Override
    public int getCount() {
        return mFragments.size();
    }
    //必须重写的方法,TabLayout会调用这个方法来获取各个page的名称,即碎片名称。
    @Override
    public CharSequence getPageTitle(int position) {
        return mFragments.get(position).getTitle();
    }
}



 

FragmentInfo的代码来分析,为何不用直接用Fragment的List而是用FramentInfo。



public class FragmentInfo {
    private String title;
    private Class fragment;  
    //构造函数接收title以及Class对象,传入的Class一般都是继承Fragment的类
    public FragmentInfo( String title,Class fragment) {
        this.fragment = fragment;
        this.title = title;
    }

    public Class getFragmet() {
        return fragment;  
    }
    public String getTitle() {
        return title;
    }
}



 

       假如在ViewPagerAdapter的List设置为Fragment,那么的确是可以往list里面传入四个继承自Fragment的具体碎片对象。但是问题随之而来,就是怎么重写getPageTitle()方法?因为mFragment.getPosition(i)方法返回的是一个以Fragment为类型的Fragment类型对象。要通过父类Fragment去访问子类中的属性自然是很麻烦,因此此处就使用FragmentInfo作为中间类,其保存了一个Class以及一个title。同时将ViewPagerAdapter的List设置为FragmentInfo。在往List里面add FragmentInfo时,只需要指定好title,同时传入各个碎片类对应的Class作为FragmentInfo的碎片标识。在getItem()方法中,再将各个碎片利用Class类的无参构造方法newInstance()来调用Fragment的无参构造方法实例化各个碎片。

Fragment的源文件,可以再添加FragmentInfo的时候指定其PageTitle,方便实用。