我的手机助手开发日志---1

目录:

  1、我的手机助手简介

  2、DrawerLayout+NavigationLayout实现侧滑菜单

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

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

1. 我的手机助手简介  

  我的手机助手是一款简单易用的应用市场,包括各种App的排行,分类,推荐,搜索功能。提供App的下载,支持多个App同时下载以及断点续传。有应用安装管理模块,能够卸载已经安装的应用,提醒需要升级的应用。同时还具有安装包管理、登录等功能。

2. DrawerLayout+NavigationLayout实现侧滑菜单

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

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

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

  一是内容控件(可采用LinearLayout布局实现);

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

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

  将DrawerLayout绑定上监听事件。

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

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>

       ToolBar在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>

       2、在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下面的内容是四个碎片,每个碎片中分别显示相应内容。首先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,方便实用。

猜你喜欢

转载自www.cnblogs.com/Chris-Zhan/p/9776337.html