Android 原生导航 IV-实现Drawer+ToolBar+Tab
2016-02-02 16:30
651 查看
概述:
要实现这个组合, 先要了解结构层次. 合理的组合应该是Drawer封装ToolBar, 然后ToolBar再封装Tab.Drawer:
首先是Drawer, Drawer的层次结构比较简单, 可以在layout中直接实现.为Drawer创建一个layout:
Layout的结构是<android.support.v4.widget.DrawerLayout …>
<!--Your contents ToolBar-->
<android.support.design.widget.NavigationView …/>
</android.support.v4.widget.DrawerLayout>
其中NavigationView是Material Design中推荐的用法, 它可以在Drawer中显示一个这样的页面:
其中蓝色的头部区域是可选的, 下面的菜单区域是必选的. 它的完整用法是这样:
<android.support.design.widget.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/drawer"/>
其中, 有两个属性, 一个是app:headerLayout, 它是可选的, 指定了一个header. App:menu则指定了一个菜单资源, 代表header下面的菜单(可以在运行时更新). 最简单的drawer菜单是一些checkable菜单项:
<group android:checkableBehavior="single">
<item
android:id="@+id/navigation_item_1"
android:checked="true"
android:icon="@drawable/ic_android"
android:title="@string/navigation_item_1"/>
<item
android:id="@+id/navigation_item_2"
android:icon="@drawable/ic_android"
android:title="@string/navigation_item_2"/>
</group>
选中的菜单项将会在drawer中高亮显示, 以确保让用户知道当前选中的是哪个. 还可以在菜单中使用subheader来指定一个独立组的item:
<item
android:id="@+id/navigation_subheader"
android:title="@string/navigation_subheader">
<menu>
<item
android:id="@+id/navigation_sub_item_1"
android:icon="@drawable/ic_android"
android:title="@string/navigation_sub_item_1"/>
<item
android:id="@+id/navigation_sub_item_2"
android:icon="@drawable/ic_android"
android:title="@string/navigation_sub_item_2"/>
</menu>
</item>
现在假设我们已经拥有了一个这样的Drawer的layout, 它来自Android的Sample:
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/my_drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> </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>
这里的NavigationVIew也可以使用一个LIstView来代替, 以显示一个简单的菜单, 它的headerLayout和menu的实现稍后再研究, 我们先拿它作为一个整体来看待. 在主layout中有了这些之后我们就拥有了一个Drawer的基本框架, 它在隐藏和显示的时候分别长这样:
而在MainActivity中不需要添加额外的代码, 设置Activity的Content即可.
ToolBar:
现在要为APP添加layout, 只需要修改Drawer layout中的主界面内容为一个appbar就可以了.为ToolBar添加Layout:
添加一个新建的layout, 很简单, 一个Toolbar + 主界面内容:<?xml version="1.0" encoding="utf-8"?> <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.v7.widget.Toolbar android:id="@+id/my_own_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:elevation="4dp" android:theme="@style/ThemeOverlay.AppCompat.ActionBar" /> <include layout="@layout/content_main" /> </LinearLayout>
并将Drawer中的FrameLayout改为引入Toolbar的代码:
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout …> <include layout="@layout/app_bar_my_own" android:layout_height="match_parent" android:layout_width="match_parent"/>
… </android.support.v4.widget.DrawerLayout>
这时候就可以看到已经拥有一个ToolBar了, 但是上面是空的, 什么也没有:
关联ToolBar与Drawer:
现在我们需要在Activity中添加一些代码:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_own);
//设置Toolbar Toolbar myToolbar = (Toolbar) findViewById(R.id.my_own_toolbar); setSupportActionBar(myToolbar); //关联Drawer DrawerLayout drawer = (DrawerLayout) findViewById(R.id.my_drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, myToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.setDrawerListener(toggle); toggle.syncState(); }
上面的代码包括两部分, 一个是设置Toolbar, 还有就是关联Drawer与Toolbar. setSupportActionBar()之后, Activity的名字就会出现在ToolBar上面. 下面关联Drawer这段可以参考Android
原生导航 III-Drawer导航. 它添加了对Drawer显示/隐藏事件的监听. syncState()则是用来在ToolBar上为Drawer添加一个指示器. 这个指示器可以通过drawerArrowStyle属性修改. 完成这些代码之后, 主界面变成了这样, 并且图标会因为Drawer显示而发生变化:
Tab:
Tab的实现比较复杂, 基础逻辑是TabLayout+ ViewPager.实现Tab的Layout:
因为Tab是AppBar的子view, 所以要修改AppBar的layout文件, 添加TabLayout和ViewPager元素, 修改之后的AppBar的layout文件如下:<?xml version="1.0"encoding="utf-8"?>
<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.v7.widget.Toolbar
android:id="@+id/my_own_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"/>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</LinearLayout>
这时界面没有变化, 因为想让它们起作用还得设置一下.
关联TabLayout和VIewPager:
首先是TabLayout, 它比较简单, 添加如下代码到onCreate()中即可:TabLayout tabLayout= (TabLayout)findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
这时候就可以看到Tab了.
然后添加ViewPager, ViewPager需要用到FragmentPagerAdapter或者FragmentStatePagerAdapter. 这里使用FragmentPagerAdapter:
public class SectionsPagerAdapter extends FragmentPagerAdapter { public SectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { Fragment fragment = new DummySectionFragment(); Bundle args = new Bundle(); args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1); fragment.setArguments(args); return fragment; } @Override public int getCount() { return 3; } } public static class DummySectionFragment extends Fragment { public static final String ARG_SECTION_NUMBER = "section_number"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.content_main, container, false); TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label); dummyTextView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER))); return rootView; } }
这里添加一个Fragment作为页面内容, 显示Tab的号码. 有了FragmentPagerAdapter就可以将它设置给ViewPager了, 在onCreate()中添加如下代码:
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mSectionsPagerAdapter); mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); tabLayout.setOnTabSelectedListener(this);
现在完整的onCreate()代码是这样的:
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_own);
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_own_toolbar);
setSupportActionBar(myToolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.my_drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, myToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
TabLayout tabLayout = (TabLayout)findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(this);
}
由于要监听Tab的点击事件, 还要添加implements TabLayout.OnTabSelectedListener到Activity. 并且实现它的回调方法:
@Override public void onTabSelected(TabLayout.Tab tab) { mViewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { }
至此这个Android最常用的导航的基本样子就已经有了, 它是这样的, 并且可以响应点击和滑动改变Tab的事件:
在栗子中, NavigationView和TabLayout这两种很重要的类都来自于android.support.design, 它提供了Material Design的支持, 很好用.
参考: https://github.com/googlesamples/android-HorizontalPaging/
https://github.com/googlesamples/android-NavigationDrawer/
http://stackoverflow.com/questions/26540078/use-tab-with-new-toolbar-appcompat-v7-21
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories