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顯示一個」錯誤信息」。