Material Design with the Android Design Support Libraryhtml
原文http://www.sitepoint.com/material-design-android-design-support-library/java
Material Design,Android 5.0发布时为android app 和其余平台app引入的一门新的设计语言。android
它带来了一些新的UI组件,如“Floating Action Button”。实施这些新组件,同时确保向后兼容性是一般一个繁琐的过程。第三方库一般会须要简化过程。git
在今年的谷歌IO大会上,谷歌推出了Android设计支持库带来了一些重要的Material Design组件的开发。该组件是向后兼容,向后兼容到Android 2.1,并实现他们的是比之前更容易。该库包括一个抽屉式导航视图,浮动编辑文本,浮动操做按钮,Snackbar,标签和motion和滚动框架绑在一块儿的标签。在本教程中,咱们将建立一个应用程序,展现了这些组件。github
工程源码:Github https://github.com/sitepoint-editors/Design-Demoapp
在开始使用这些组件以前,咱们将创建项目,并设置一些样式。采用Android Studio中建立一个新的Android项目。将它命名为“Material Design”并保留其余设置为默认值,保证了最低的SDK版本是在API级别15。框架
在 build.gradle(module:app)文件添加库依赖:ide
compile 'com.android.support:design:22.2.1' compile 'com.android.support:cardview-v7:22.2.1'
第一个声明添加 design support library,第二个声音添加 CardView 库,稍候咱们将用到。接下来同步更新一下project。它可能会下载一些其余的支持库。函数
建立文件夹 res/values下资源文件 colors.xml,内容更改以下:工具
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="primary">#3F51B5</color> <color name="primary_dark">#303F9F</color> <color name="accent">#FF4081</color> </resources>
在res/values/strings.xml修改以下,咱们在工程须要用到的字符串:
<resources> <string name="app_name">Design Demo</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> <string name="nav_item_attachment">Attachment</string> <string name="nav_item_images">Images</string> <string name="nav_item_location">My Location</string> <string name="nav_sub_menu">Sub Menu</string> <string name="nav_sub_menu_item01">Sub Menu Item 1</string> <string name="nav_sub_menu_item02">Sub Menu Item 2</string> <string name="drawer_header_text">Drawer Header</string> <string name="second_activity_text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin consectetur diam id aliquam scelerisque. Donec ultrices lacus vel dignissim pharetra. Vivamus pharetra augue quis rhoncus placerat. Sed ultricies at risus non cursus. Nam rutrum leo nec placerat consectetur. Vestibulum feugiat eleifend diam, nec interdum augue tincidunt sit amet. Praesent feugiat est auctor lacus consectetur, vitae pellentesque dolor laoreet.</string> <string name="title_activity_second">SecondActivity</string> </resources>
修改 res/values/styles.xml 文件:
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/primary</item> <item name="colorPrimaryDark">@color/primary_dark</item> <item name="colorAccent">@color/accent</item> </style> </resources>
在上面代码中,咱们根据Material Design指南自定义了app的primary, primary-dark and accent color颜色
可定制其它主题设置以下图所示。
注意 item 名称不包含android: 前缀(如android:colorPrimaryDark),这是为了向后兼容。android: 注解须要将最低的API级别设置为 21。咱们须要NoActionBar主题。
由于咱们将使用一个 Toolbar做为 Action Bar(或者称为 AppBar).
(SOURCE: https://developer.android.com/training/material/theme.html)
添加 Toolbar, res/layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark" /> </RelativeLayout>
上面代码中,咱们删除了RelativeLayout 默认的 padding,而后添加支持库的 Toolbar。若是你只支持API级别21以上的设备,那么你可使用默认的 Toolbar组件,而不须要支持库。
修改 MainActivity.java 的 onCreate(Bundle)方法:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); ActionBar actionBar = getSupportActionBar(); actionBar.setHomeAsUpIndicator(R.drawable.ic_menu); actionBar.setDisplayHomeAsUpEnabled(true); }
Download the project resources from gitHub 包含drawable文件夹。你须要复制res目录到你的工程,上面的代码才不会显示错误信息。
上面代码,咱们引用了 Toolbar 做为 Action Bar,而后为 Action Bar设置 Home 图标。
运行代码,你会看一个设置了 Toolbar的AppBar.
Navigation Drawer是一个Android应用公用组件。它是创建Android导航层次结构的方式之一, Tabs和 Spinners。实现一个历来就不是一个很快的过程,但如今随着设计支持库,它的实现要简单得多。
接着,改修 activity_main.xml:
<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/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark" /> </RelativeLayout> <android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/drawer_header" app:menu="@menu/drawer"/> </android.support.v4.widget.DrawerLayout>
上面代码,咱们在DrawerLayout布局添加了一个NavigationView,这里你会注意到两个属性:app:heanderLaytout
用来控制 header 部分的布局;app:menu
指定了菜单资源,这两个资源咱们将在下面建立。
建立 res/layout/drawer_header.xml文件,内容为:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="150dp" android:background="?attr/colorPrimaryDark" android:padding="16dp" android:theme="@style/ThemeOverlay.AppCompat.Dark" android:gravity="bottom"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/drawer_header_text" android:textAppearance="@style/TextAppearance.AppCompat.Body1"/> </LinearLayout>
这里咱们建立了NavigationView的头部视图,而后设置视图背景颜色,高度和显示的文本。
接下来在 res/menu目录下建立 drawer.xml文件:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/navigation_item_attachment" android:checked="true" android:icon="@drawable/ic_attachment" android:title="@string/nav_item_attachment" /> <item android:id="@+id/navigation_item_images" android:icon="@drawable/ic_image" android:title="@string/nav_item_images" /> <item android:id="@+id/navigation_item_location" android:icon="@drawable/ic_place" android:title="@string/nav_item_location" /> </group> <item android:title="@string/nav_sub_menu"> <menu> <item android:icon="@drawable/ic_emoticon" android:title="@string/nav_sub_menu_item01" /> <item android:icon="@drawable/ic_emoticon" android:title="@string/nav_sub_menu_item02" /> </menu> </item> </menu>
在上文中,咱们建立了drawer里的菜单项。第一部分显示了菜单项的集合。选中的项目将在导航抽屉突出显示,确保用户知道哪些导航项目当前选择。在第二部分中,咱们使用一个subheader以区别第一部分。
在MainActivity.java 添加如下成员变量:
private DrawerLayout mDrawerLayout;
而后再 onCreate(Bundle)
函数添加如下代码:
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
修改onOptionsItemSelected(MenuItem) 函数:
@Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); switch (id) { case android.R.id.home: mDrawerLayout.openDrawer(GravityCompat.START); return true; case R.id.action_settings: return true; } return super.onOptionsItemSelected(item); }
当按钮屏幕的 home 按钮,drawer将从左边滑出。运行代码看看效果。
咱们还须要为NavigationView设置 OnNavigationItemSelectedListener监听捕获菜单选择点击事件,在onCreate(Bundle)添加代码:
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view); navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(MenuItem menuItem) { menuItem.setChecked(true); mDrawerLayout.closeDrawers(); Toast.makeText(MainActivity.this, menuItem.getTitle(), Toast.LENGTH_LONG).show(); return true; } });
上面的代码设置在导航视图中的监听器,这样当一个抽屉菜单项被选中,菜单项设置为选中状态(这只会影响到标记为可检查的菜单项),抽屉被关闭,并Toast显示选定菜单项的标题。
一个浮动的操做按钮是一个圆形按钮,表示您界面上的主要操做。设计库的FloatingActionButton提供一个一致的实现,在默认状况下使用colorAccent的主题色。
添加一个正常大小(56dp)浮动动做按钮,它支持最低大小(40dp),当与其余元件视觉连续性是相当重要的。
修改 activity_main.xml添加 FAB:
<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/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginRight="@dimen/activity_horizontal_margin" android:layout_marginBottom="@dimen/activity_vertical_margin" android:src="@drawable/ic_done" /> </RelativeLayout> <android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/drawer_header" app:menu="@menu/drawer"/> </android.support.v4.widget.DrawerLayout>
在上面,咱们添加FloatingActionButton在布局的右下角。android:src设置按钮中显示的图标。在代码中,你可使用setImageDrawable()。
运行代码,显示结果
下一节咱们会为 FAB设置onClickListener
之前若是你想快速反馈信息给用户,你能够用 Toast,如今你有另外一个选择了,那就是 Snackbar
Snackbar显示在屏幕的底部,并包含文字与可选的单个动做。超时会自动滑出屏幕。用户也能够在超时前手动将其滑出。
它的API与Toast相似,可是功能却被Toast强大
在 MainActivity.java的onCreate(Bundle)
:添加如下代码
FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Snackbar.make(findViewById(R.id.drawer_layout), "I'm a Snackbar", Snackbar.LENGTH_LONG).setAction("Action", new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "Snackbar Action", Toast.LENGTH_LONG).show(); } }).show(); } });
在上面代码中,咱们为FAB设置一个onClickListener 监听对象,而后显示Snackbar,当用户触发 Action 按钮时,显示一个 Toast信息。
注意函数make()的第一个参数,它将做为Snackbar父视图,以确实Snackbar显示在父视图底部的锚点。
运行程序:
注意到Snackbar与FAB重叠,咱们将在下一节经过CoordinatorLayout修复这个问题。
在Android里经过标签来切换两个不一样的视图已经不是新概念了。可是经过支持库 TabLayout能够简化添加标签的操做。实现了固定 tab(全部 tab 势均力敌,宽度固定)和滚动 tab(宽度根据标题长度自适应,能够水平滑动)两种形式
添加 TabLayout 到应用中,修改 res/layout/activity_main.xml:
<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" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <RelativeLayout 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="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark" /> <android.support.design.widget.TabLayout android:id="@+id/tablayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" app:tabGravity="fill" android:theme="@style/ThemeOverlay.AppCompat.Dark" /> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> </LinearLayout> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="@dimen/activity_vertical_margin" android:layout_marginRight="@dimen/activity_horizontal_margin" android:src="@drawable/ic_done"/> </RelativeLayout> <android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/drawer_header" app:menu="@menu/drawer"/> </android.support.v4.widget.DrawerLayout>
在上文中,咱们添加一个TabLayout以及一个ViewPager。该ViewPager将用于使标签水平切换。
在 MainActivity.java文件下添加如下类:
public static class DesignDemoFragment extends Fragment { private static final String TAB_POSITION = "tab_position"; public DesignDemoFragment() { } public static DesignDemoFragment newInstance(int tabPosition) { DesignDemoFragment fragment = new DesignDemoFragment(); Bundle args = new Bundle(); args.putInt(TAB_POSITION, tabPosition); fragment.setArguments(args); return fragment; } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Bundle args = getArguments(); int tabPosition = args.getInt(TAB_POSITION); TextView tv = new TextView(getActivity()); tv.setGravity(Gravity.CENTER); tv.setText("Text in Tab #" + tabPosition); return tv; } } static class DesignDemoPagerAdapter extends FragmentStatePagerAdapter { public DesignDemoPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return DesignDemoFragment.newInstance(position); } @Override public int getCount() { return 3; } @Override public CharSequence getPageTitle(int position) { return "Tab " + position; } }
而后在onCreate(Bundle)方法添加如下代码:
DesignDemoPagerAdapter adapter = new DesignDemoPagerAdapter(getSupportFragmentManager()); ViewPager viewPager = (ViewPager)findViewById(R.id.viewpager); viewPager.setAdapter(adapter); TabLayout tabLayout = (TabLayout)findViewById(R.id.tablayout); tabLayout.setupWithViewPager(viewPager);
上面代码中,咱们建立一个简单的Fragment,并包含一个TextView视图,而后建立一个FragmentStatePagerAdapter 做为ViewPager的适配器,适配器的getCount()函数返回了 标签总数,getItem(int) 返回了当前标签页的fragment, getPageTitle(int) 则设置了标签title,要让它工做,咱们使用了 TabLayout的setupWithViewPager()函数,更保标签更新时,viewpager跟着一块儿更新。
运行程序:
CoordinatorLayout使用新的思路经过协调调度子布局的形式实现触摸影响布局的形式产生动画效果。
将FloatingActionButton 做为CoordinatorLayout
的子视图,而后将Snackbar.make() 函数的第一个参数指定为CoordinatorLayout
大概意思也就是说:当Snackbar向上移出时,FAB会跟着往上移动,就是同步。就解决了重叠的问题了。(自已的英语水平真差出新高度了)
修改 activity_main.xml文件:
<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" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <android.support.design.widget.CoordinatorLayout android:id="@+id/coordinator" 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="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark" /> <android.support.design.widget.TabLayout android:id="@+id/tablayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" app:tabGravity="fill" android:theme="@style/ThemeOverlay.AppCompat.Dark" /> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> </LinearLayout> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_gravity="bottom|right" android:layout_marginBottom="@dimen/activity_vertical_margin" android:layout_marginRight="@dimen/activity_horizontal_margin" android:src="@drawable/ic_done"/> </android.support.design.widget.CoordinatorLayout> <android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/drawer_header" app:menu="@menu/drawer"/> </android.support.v4.widget.DrawerLayout>
以上代码中,FAB做为CoordinatorLayout的子视图,就是将RelativeLayout布局更改为CoordinatorLayout,注意设置FAB的位置
android:layout_gravity="bottom|right"
.
接下来就是在 MainActivity.java建立Snackbar时,CoordinatorLayout为做Snackbar的视图参数(第一个参数):
Snackbar.make(findViewById(R.id.coordinator), "I'm a Snackbar", Snackbar.LENGTH_LONG).setAction("Action", new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "Snackbar Action", Toast.LENGTH_LONG).show(); } }).show();
运行程序,如今当你点击FAB按钮时,Snackbar会往向滑进界面,可是不会与FAB按钮重叠,FAB按钮会跟着往上移动,但Snackbar移出屏幕时,FAB按钮会跟着回到原来的位置。
另外一个主要用例CoordinatorLayout涉及应用栏和滚动技术。设计库提供了AppBarLayout容许工具栏和其余视图(如由TabLayout提供选项卡)反应以在标有ScrollingViewBehavior同级视图滚动事件。
实现这个功能以前,让咱们先建立一些东西,咱们能够滚动。咱们将使用一个RecyclerView建立,咱们能够滚动项目列表。
(做者使用 ListView, GridView和 ScrollViews不能让CoordinatorLayout正常工做)
build.gradle (Module: app) 文件添加以下内容:
compile 'com.android.support:recyclerview-v7:22.2.1'
建立 res/layout/ fragment_list_view.xml文件
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent"/>
接着建立另外一个布局文件 res/layout/list_row.xml文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="16dp" android:layout_width="match_parent" android:layout_height="56dp"> <TextView android:id="@+id/list_item" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
建立一个java文件DesignDemoRecyclerAdapter.java
package com.echessa.designdemo; // Rename as Appropriate import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.List; /** * Created by echessa on 7/24/15. */ public class DesignDemoRecyclerAdapter extends RecyclerView.Adapter<DesignDemoRecyclerAdapter.ViewHolder> { private List<String> mItems; DesignDemoRecyclerAdapter(List<String> items) { mItems = items; } @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, viewGroup, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder viewHolder, int i) { String item = mItems.get(i); viewHolder.mTextView.setText(item); } @Override public int getItemCount() { return mItems.size(); } public class ViewHolder extends RecyclerView.ViewHolder { private final TextView mTextView; ViewHolder(View v) { super(v); mTextView = (TextView)v.findViewById(R.id.list_item); } } }
修改DesignDemoFragment.onCreateView()
函数的代码:
@Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Bundle args = getArguments(); int tabPosition = args.getInt(TAB_POSITION); ArrayList<String> items = new ArrayList<String>(); for (int i = 0; i < 50; i++) { items.add("Tab #" + tabPosition + " item #" + i); } View v = inflater.inflate(R.layout.fragment_list_view, container, false); RecyclerView recyclerView = (RecyclerView)v.findViewById(R.id.recyclerview); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); recyclerView.setAdapter(new DesignDemoRecyclerAdapter(items)); return v; }
使用建立的 fragment_list_view.xml布局来填充视图,如今fragment视图将会包含一个列表项。运行程序:
修改 activity_main.xml文件:
<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" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <android.support.design.widget.CoordinatorLayout android:id="@+id/coordinator" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways"/> <android.support.design.widget.TabLayout android:id="@+id/tablayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" app:tabGravity="fill"/> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_gravity="bottom|right" android:layout_marginBottom="@dimen/activity_vertical_margin" android:layout_marginRight="@dimen/activity_horizontal_margin" android:src="@drawable/ic_done"/> </android.support.design.widget.CoordinatorLayout> <android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/drawer_header" app:menu="@menu/drawer"/> </android.support.v4.widget.DrawerLayout>
在上面代码中,咱们将 Toolbar和TabLayout嵌入到 AppbarLayout中, AppBarLayout容许Toolbar及标志为ScrollingViewBehavior的其余视图响应滚动事件。当经过RecyclerView用户滚动时,AppBarLayout响应经过其子的滚动标志来控制他们是如何进入(滚动在屏幕上)和出口(滚动关闭屏幕)。也就是全部标志为ScrollingViewBehavior 的子视图都会被推入和拉出。
Flags 包括:
注意一点:全部设置了 scroll 标志的视图必须在未设该标志的视图以前进行声明,这样能够确保全部的滚动视图都从顶部退出,而固定元素都不受影响。
CollapsingToolbarLayout为AppBar提供了另外一种滚动行为。咱们将建立另外一个Activity,只包含一个Toolbar.
建立一个空的 Activity,命名:SecondActivity
修改 res/layout/activity_second.xml:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="250dp" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:contentScrim="?attr/colorPrimary" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:src="@drawable/image" app:layout_collapseMode="parallax"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin"></android.support.v7.widget.Toolbar> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:orientation="vertical" android:paddingTop="24dp" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.CardView android:layout_margin="16dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="vertical" android:padding="16dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Lorem ipsum"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/second_activity_text"/> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:layout_margin="16dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="vertical" android:padding="16dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Lorem ipsum"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/second_activity_text"/> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:layout_margin="16dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="vertical" android:padding="16dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Lorem ipsum"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/second_activity_text"/> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:layout_margin="16dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="vertical" android:padding="16dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Lorem ipsum"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/second_activity_text"/> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:layout_margin="16dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="vertical" android:padding="16dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Lorem ipsum"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/second_activity_text"/> </LinearLayout> </android.support.v7.widget.CardView> </LinearLayout> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout>
在上文中,咱们使用了CollapsingToolbarLayout,标志为 scroll和 exitUnitCollapsed,使它的子视图所有滚出屏幕,对于Toolbar,咱们设置为:app:layout_collapseMode="pin" 能够确保当视图折叠时 Toolbar固定在顶部,在CollapsingToolbarLayout的标题将出现较大的时候,布局是彻底可见,而后过渡到其默认大小,由于它是折叠的。咱们在代码中设置此title。布局的其他部分是一个NestedScrollView包含几个CardView。
在SecondActivity.java中的onCreate(Bundle)函数添加代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar); collapsingToolbar.setTitle("Second Activity"); }
这里咱们为Toolbar添加向上符号和为 CollapsingToolbarLayout设置title
要使用向上符号工做,还须要在manifest文件中为SecondActivity添加标签
<meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.echessa.designdemo.MainActivity" />
修改DesignDemoRecyclerAdapter.java 的onBindViewHolder()方法:
@Override public void onBindViewHolder(ViewHolder viewHolder, int i) { String item = mItems.get(i); viewHolder.mTextView.setText(item); viewHolder.mTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Context context = view.getContext(); context.startActivity(new Intent(context, SecondActivity.class)); } }); }
在上文中,咱们的RecyclerView的每一行上的TextView设置一个onClick监听。这不是设置RecyclerView项监听的好方式,由于若是你运行应用程序,听者的触摸目标将只包括与该行的文本的区域,而不是整个行。我这样作是在这里,由于我要的是一个方法来启动新的活动,因此我选择一个的方式来写最少的代码。
最后要介绍的一个组件是支持库里改良型的EditText,譬如它在咱们输入第一个字符的时候,就会自动隐藏掉提示标签。如今你该使用 TextInputLayout 了,它会在用户开始输入以后,自动将提示标签悬浮到 EditText 上方,这样用户就永远都能知道输入内容的上下文。
为了演示这个功能,咱们修改 activity_second.xml布局文件的第二个CardView的第一个TextView为 EditText.
<android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:hint="Email" /> </android.support.design.widget.TextInputLayout>
运行程序,提示文件将浮如今EditView的上面
你还能够经过设置EditView的setError()函数来为EditView显示一个”错误信息”。