Android Material Design简单使用

做为一个 Android developer,没有什么比拿着 UI 设计的一堆 iOS 风格的设计 来作需求更恶心的了,基本全部空间都要照着 iOS 来画一遍,Material Design 辣么酷炫 为何 UI在设计的阶段不设计成 Material Design风格呢?html

今天试了几个比较Support包中比较典型的Material Design控件,后期会在学习下Material Design的设计思想和理念,但愿能拉着 UI 作一次Material Design 分享,改变咱们 APP 的 iOS 风格啊。java

最终效果以下
android

Android Design Support 库依赖

在 build.gradle 中加入support 包git

1
compile 'com.android.support:appcompat-v7:23.1.1' 

Design Support Library 中包含了 Support v4 和 AppCompat v7github

Floating Action Button

咱们但愿FloatingActionButton悬浮在页面的右下方,因此咱们父节点应使用Flowlayoutapi

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"  android:paddingBottom="@dimen/activity_vertical_margin"  android:paddingLeft="@dimen/activity_horizontal_margin"  android:paddingRight="@dimen/activity_horizontal_margin"  android:paddingTop="@dimen/activity_vertical_margin"  tools:context="io.github.xuyushi.materialdesigndemo.MainActivity">   <TextView  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="Hello World!" />   <android.support.design.widget.FloatingActionButton  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_gravity="bottom|end"  android:src="@android:drawable/ic_dialog_email" />  </FrameLayout> 

和普通 button 同样能够设置其点击事件app

1
2 3 4 5 6 7 8 9 
private void initFb() {  mFb = (FloatingActionButton) findViewById(R.id.fb);  mFb.setOnClickListener(new View.OnClickListener() {  @Override  public void onClick(View v) {  Toast.makeText(MainActivity.this, "fb predsed ", Toast.LENGTH_SHORT).show();  }  });  } 

Android:elevation属性为 view 在空闲状态下的阴影深度, 须要在 api 21以上才能使用,使用 support 包可使用app:elevation来表示空闲状态高度,app:pressedTanslationZ为按下状态的高度ide

按钮的颜色通常为主题的强调色,也可使用 ”app:backgroundTint“修改布局

Snackbar

和 Toast 很像,snackbar 能够展现一段简单的信息,不一样点是它的展现更像是总体 UI 的一部分,不是想 toast 同样是浮在 UI 上的,而且能够有简单的交互post

在点击 floatingActionButton时显示Snackbar

可是能够看到,Snackbar 遮挡住了咱们的 view,这时候须要一个CoordinatorLayout来协调 view 布局

CoordinatorLayout

将父布局中的framelaout换成CoordinatorLayout,其余不变,再来看看效果

==todo CoordinatorLayout学习==

Toolbar

Toolbar 比传统的 ActionBar 更灵活,功能也更多,咱们能够看到如今市面上不少的 APP 已经用 Toolbar 替代了 actionbar,在 Desgin Support 的组件中,不少设计均可以和 Toolbar 协同工做,而不是和 actionbar,因此仍是建议使用新的 toolbar 替换之前的 actionbar

替换步骤

一、在 minifest 中,将 activity 的 apptheme 的 style 中的 actionbar属性去掉

1
2 3 4 5 6 7 8 9 10 11 12 
<style name="AppTheme.NoActionBar">  <item name="windowActionBar">false</item>  <item name="windowNoTitle">true</item> </style>  <activity android:name=".MainActivity">  <intent-filter>  <action android:name="android.intent.action.MAIN" />   <category android:name="android.intent.category.LAUNCHER" />  </intent-filter>  </activity> 
  1. 在 fb 以前放入 Toolbar 组件
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 
<android.support.design.widget.CoordinatorLayout 
 .........   <android.support.v7.widget.Toolbar  android:id="@+id/toolbar"  android:layout_width="match_parent"  android:layout_height="?attr/actionBarSize"  android:background="?attr/colorPrimary"  app:popupTheme="@style/ThemeOverlay.AppCompat.Light"  app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />   <TextView  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="Hello World!" />   <android.support.design.widget.FloatingActionButton  android:id="@+id/fb"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_gravity="end|bottom"  android:src="@android:drawable/ic_dialog_email"  app:elevation="12dp"  app:pressedTranslationZ="30dp"  />   </android.support.design.widget.CoordinatorLayout> 
  1. 通知系统使用 toolbar
1
2 3 4 
private void initToolbar() {  mToolbar = (Toolbar) findViewById(R.id.toolbar);  setSupportActionBar(mToolbar); } 

CoordinatorLayout中的 view 必须是能一同协做的 view,就像 Snackbar 同样,可是 toolbar 并非这样能协同做战的 view,因此咱们须要用一个能够协同做战的 view 来包裹上Toolbar,这就是 AppBarLayout

如今咱们的布局文件结构是这样的

1
2 3 4 5 6 7 8 9 10 11 12 13 14 
<android.support.design.widget.CoordinatorLayout  ...>   <android.support.design.widget.AppBarLayout  android:layout_width="match_parent"  android:layout_height="wrap_content">  <android.support.v7.widget.Toolbar  .../>  </android.support.design.widget.AppBarLayout>   <android.support.design.widget.FloatingActionButton  ...>  </android.support.design.widget.FloatingActionButton> </android.support.design.widget.CoordinatorLayout> 

注意

根据官方的谷歌文档,AppBarLayout目前必须是第一个嵌套在CoordinatorLayout里面的子view

在 toolbar 中加入属性,app:layout_collapseMode=”pin”,使得 Toolbar 中的按钮能固定在顶部

在布局中加入内容

在布局中尝试加入一些按钮

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 
....
 </android.support.design.widget.AppBarLayout>    <LinearLayout  android:layout_width="match_parent"  android:layout_height="match_parent"  app:layout_behavior="@string/appbar_scrolling_view_behavior"  android:orientation="vertical">   <Button  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="test" />   <Button  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="test" />   <Button  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="test" />   </LinearLayout>  ... 

咱们定义三个按键,却被 toolbar 遮住了一个,缘由是LinearLayout并无被设计成在CoordinatorLayout协同工做的模式,为了使他们能在CoordinatorLayout协同工做,咱们须要在LinearLayout加上一条属性,来告诉它的滚动属性()

1
2 3 4 5 
<LinearLayout  ...  app:layout_behavior="@string/appbar_scrolling_view_behavior"  ...  > 

搞定

TabLayout

根据官网的知道,TabLayout一般应该是放在顶部,(iOS 的 tab 好像基本在底部),
他应该在阴影部分上面,因此应该放在AppBarlayout

1
2 3 4 5 6 7 
<android.support.design.widget.AppBarLayout ...>  <android.support.v7.widget.Toolbar ... />  <android.support.design.widget.TabLayout  android:id="@+id/tabLayout"  android:layout_width="match_parent"  android:layout_height="wrap_content"/> </android.support.design.widget.AppBarLayout> 

java 中设置这些 tab 属性

1
2 3 4 5 6 
private void initTableLayout() {  mTabLayout = (TabLayout) findViewById(R.id.tabLayout);  mTabLayout.addTab(mTabLayout.newTab().setText("Tab 1"));  mTabLayout.addTab(mTabLayout.newTab().setText("Tab 2"));  mTabLayout.addTab(mTabLayout.newTab().setText("Tab 3")); } 

背景会设置为主题色,导航线是强调色。可是字仍是黑色的,由于咱们没有为 tablayout 定义主题,

1
2 3 
<android.support.design.widget.TabLayout  ...  app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> 

一般 tablayout 会和ViewPager一块儿使用 ,这时候使用
public void setupWithViewPager (ViewPager viewPager)

一张图看的比较清晰

内容滚动时,AppBarLayout隐藏

当滑档内容时,为了腾出跟多的空间展现内容能够将AppBarLayout隐藏

1.用 scrollView 包裹 LinearLayout,记得加上 app:layout_behavior属性

1
2 3 4 5 6 7 8 9 10 11 12 13 14 
<ScrollView  android:layout_width="match_parent"  android:layout_height="match_parent"  android:fillViewport="true"  app:layout_behavior="@string/appbar_scrolling_view_behavior"  >  <LinearLayout  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical"  >  ...  </LinearLayout> </ScrollView> 
  1. Toolbar 加上属性
1
2 3 
<android.support.v7.widget.Toolbar  ...  app:layout_scrollFlags="scroll|enterAlways" /> 
  1. scrollView 也不能喝 CoordinatorLayout 协同工做,同上面同样,要用别的 view 包裹或者直接使用 NestedSrollView替换scrollView

若是但愿 tablayout 也消失,只须要和 tablayout 加上相同的属性就好了

1
2 3 
<android.support.design.widget.TabLayout  ...  app:layout_scrollFlags="scroll|enterAlways" /> 

滑动内容 和 AppBarLayout是如何进行联系的?

咱们须要定义AppBarLayout与滚动视图之间的联系。在RecyclerView或者任意支持嵌套滚动的view好比NestedScrollView上添加app:layout_behavior。support library包含了一个特殊的字符串资源@string/appbar_scrolling_view_behavior,它和AppBarLayout.ScrollingViewBehavior相匹配,用来通知AppBarLayout 这个特殊的view什么时候发生了滚动事件,这个behavior须要设置在触发事件(滚动)的view之上

当CoordinatorLayout发现scrollView中定义了这个属性,它会搜索本身所包含的其余view,看看是否有view与这个behavior相关联。AppBarLayout.ScrollingViewBehavior描述了RecyclerView与AppBarLayout之间的依赖关系。RecyclerView的任意滚动事件都将触发AppBarLayout或者AppBarLayout里面view的改变。

AppBarLayout里面定义的view只要设置了app:layout_scrollFlags属性,就能够在RecyclerView滚动事件发生的时候被触发:

app:layout_scrollFlags属性里面必须至少启用scroll这个flag,这样这个view才会滚动出屏幕,不然它将一直固定在顶部。可使用的其余flag有:

  • enterAlways: 一旦向上滚动这个view就可见。
  • enterAlwaysCollapsed: 顾名思义,这个flag定义的是什么时候进入(已经消失以后什么时候再次显示)。假设你定义了一个最小高度(minHeight)同时enterAlways也定义了,那么view将在到达这个最小高度的时候开始显示,而且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。
  • exitUntilCollapsed: 一样顾名思义,这个flag时定义什么时候退出,当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候消失。

记住,要把带有scroll flag的view放在前面,这样收回的view才能让正常退出,而固定的view继续留在顶部。

可折叠的 Toolbar

  • 用 CollapsingToolbarLayout 包裹 Toolbar,但仍然在 AppBarLayout 中
  • 删除 Toolbar 中的 layout_scrollFlags
  • 为 CollapsingToolbarLayout 声明 layout_scrollFlags,而且将 layout_scrollFlags 设置成 scroll|exitUntilCollapsed
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 
<android.support.design.widget.AppBarLayout  android:layout_width="match_parent"  android:layout_height="256dp">   <android.support.design.widget.CollapsingToolbarLayout  android:id="@+id/collapsingToolbarLayout"  android:layout_width="match_parent"  android:layout_height="match_parent"  app:layout_scrollFlags="scroll|exitUntilCollapsed">   <android.support.v7.widget.Toolbar  android:id="@+id/toolbar"  android:layout_width="match_parent"  android:layout_height="?attr/actionBarSize"  android:background="?attr/colorPrimary"  android:minHeight="?attr/actionBarSize"  app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"  app:popupTheme="@style/ThemeOverlay.AppCompat.Light"  app:layout_collapseMode="pin"/>   </android.support.design.widget.CollapsingToolbarLayout>  </android.support.design.widget.AppBarLayout> 

注意 CollapsingToolbarLayout 的高度是android:layout_height="match_parent"

CollapsingToolbarLayout在展开和收缩时,标题的文字会自动过分的,能够经过 app:expandedTitleMargin 等来改变文字位置

为 appBar 添加背景图片

因为 CollapsingToolbarLayout 是继承 Framelayout 的,因此咱们能够直接添加一个 ImageView 做为背景图片

1
2 3 4 5 6 7 8 
<ImageView  android:layout_width="match_parent"  android:layout_height="match_parent"  android:scaleType="centerCrop"  android:src="@drawable/header" />  <android.support.v7.widget.Toolbar  ... 

此时虽然背景已经出来了,可是蓝色的导航条依旧存在,须要在 toolbar 去掉这条属性

1
android:background="?attr/colorPrimary"

给 Imageview 加上视差模式会更帅

1
2 
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.5" 

也能够在最后恢复成主题色

1
2 3 
<android.support.design.widget.CollapsingToolbarLayout  ...  app:contentScrim="?attr/colorPrimary"> 

AppBarLayout布局下,增DrawerLayout

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 
<android.support.design.widget.AppBarLayout> ...  <android.support.v4.widget.DrawerLayout xmlns:app="http://schemas.android.com/apk/res-auto"  xmlns:tools="http://schemas.android.com/tools"  android:id="@+id/drawer_layout"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:fitsSystemWindows="true"  app:layout_behavior="@string/appbar_scrolling_view_behavior"  tools:openDrawer="start">   <include layout="@layout/content_main" />   <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_main2"  app:menu="@menu/activity_main2_drawer" />   </android.support.v4.widget.DrawerLayout> 

DrawerLayout中分两部分组成,一部分是content 就是咱们须要的主布局内容,另外一部分是咱们的抽屉的布局,NavigationView中有顶部头,和标签

1
2 
app:headerLayout="@layout/nav_header_main2"
 app:menu="@menu/activity_main2_drawer" 

建立菜单。

菜单元素是放在group标签之下,同时声明每次只能有一个item被选中:

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 
<?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/nav_camera"  android:icon="@drawable/ic_menu_camera"  android:title="Import" />  <item  android:id="@+id/nav_gallery"  android:icon="@drawable/ic_menu_gallery"  android:title="Gallery" />  <item  android:id="@+id/nav_slideshow"  android:icon="@drawable/ic_menu_slideshow"  android:title="Slideshow" />  <item  android:id="@+id/nav_manage"  android:icon="@drawable/ic_menu_manage"  android:title="Tools" />  </group>   <item android:title="Communicate">  <menu>  <item  android:id="@+id/nav_share"  android:icon="@drawable/ic_menu_share"  android:title="Share" />  <item  android:id="@+id/nav_send"  android:icon="@drawable/ic_menu_send"  android:title="Send" />  </menu>  </item>  </menu> 

为了防止页面被遮盖,一样要使得 DrawerLayout协调。加入app:layout_behavior="@string/appbar_scrolling_view_behavior"属性

java初始化

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 
private void initDraw() {  DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);  ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(  this, drawer, mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);  drawer.setDrawerListener(toggle);  toggle.syncState();   NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);  navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {  @Override  public boolean onNavigationItemSelected(MenuItem item) {  // Handle navigation view item clicks here.  int id = item.getItemId();   if (id == R.id.nav_camera) {  // Handle the camera action  } else if (id == R.id.nav_gallery) {   } else if (id == R.id.nav_slideshow) {   } else if (id == R.id.nav_manage) {   } else if (id == R.id.nav_share) {   } else if (id == R.id.nav_send) {   }   DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);  drawer.closeDrawer(GravityCompat.START);  return true;  }  }); 

SwipeRefreshLayout

NestedScrollView外在包裹一层SwipeRefreshLayout

1
2 3 4 5 6 7 8 9 10 11 12 13 14 
<android.support.v4.widget.SwipeRefreshLayout  android:id="@+id/refresh"  android:layout_width="match_parent"  android:layout_height="match_parent"  app:layout_behavior="@string/appbar_scrolling_view_behavior">  <android.support.v4.widget.NestedScrollView  android:layout_width="match_parent"  android:layout_height="match_parent"  android:fillViewport="true"  >  .....  </android.support.v4.widget.NestedScrollView>   </android.support.v4.widget.SwipeRefreshLayout> 

初始化监听器

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 
private void initRefresh() {  mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh);  mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {  @Override  public void onRefresh() {  refreshContent();  }  });  }   private void refreshContent() {  new Handler().postDelayed(new Runnable() {  @Override  public void run() {  mSwipeRefreshLayout.setRefreshing(false);  }  }, 2000);  } 

失败是什么?没有什么,只是更走近成功一步;成功是什么?就是走过了全部通向失败的路,只剩下一条路,那就是成功的路

转载自:http://www.cnblogs.com/android-blogs/p/5632103.html