Material Design 提供的组件

时间:2021-10-20 05:28:24

反编译看的实在有点头疼,于是就仔细研究了一下前一段时间的一篇文章Material Design规范,发现这个东西2014年就出来了,为什么我今年才发现呢..无奈.于是乎,读书查资料,撸出一个Demo来;

Demo主要知识点<解释纯属个人见解>

  1. Toolbar- ->Material Design中推荐用来替代ActionBar的组件

  2. DrawerLayout- ->侧滑菜单的父组件

  3. NavigationView- ->侧滑菜单推荐和DrawerLayout一起组合的使用的菜单组件

  4. FloatingActionButton- ->悬浮按钮

  5. CoordinatorLayout- ->加强版的FrameLayout,拥有部分新特性

  6. Snackbar- ->可交互的Toast(不是替代品)

  7. CardView- ->卡片式布局

  8. AppBarLayout->Toolbar的父组件,封装部分事件

  9. SwipeRefreshLayout- ->下拉刷新组件

  10. CollapsingToolbarLayout- ->只能作为AppBarLayout的直接子布局,用于实现更多效果

  11. RecyclerView- ->ListView的代替品

// 话不多说

1.ToolBar

Toolbar强大之处在于,他不仅继承了ActionBar的所有功能,而且灵活性很高,可以配合其他控件完成一些Material Design的效果

下面我们就来学习一下(首先你需要有一个项目):

  • 修改styles文件中的style部分内容.目的是让ActionBar隐藏,可由多种实现方式,这里提供一种.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
  • xml文件中
<?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.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary">
</android.support.v7.widget.Toolbar>

</LinearLayout>

高度为?attr/actionBarSize,也可以自己指定,不过MD规范推荐用这个,同样background也是这个道理

运行

Material Design 提供的组件

..好难看

  • 替换ActionBar
    Activity中加入代码
protected void onCreate(Bundle savedInstanceState) {
...
Toolbar toolBar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolBar);
...

}

运行

Material Design 提供的组件

出现我们的Title了,这个是怎么来的,是我们在Manifest中为application设置的label属性的值.和ActionBar是一样的,现在我们的ToolBar才相当于我们的ActionBar,我们也可以修改这个标题,只需要在Manifest中为当前activity添加一个label属性即可

  • ToolBar还有好多用法,自己太单调,结合后面的组件一起来

DrawerLayout

好多应用都有这种效果,比如QQ,XX,XXX好多软件
用MD中推荐了一种做法

  • 需要修改xml根布局为DrawerLayout并加入一个FrameLayout和一个TextView如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/drawer_layout"
android:layout_height="match_parent">

<FrameLayout
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:layout_gravity=""
android:background="@color/colorPrimary"></android.support.v7.widget.Toolbar>
</FrameLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:text="然而我就是侧拉菜单" />


</android.support.v4.widget.DrawerLayout>

运行

Material Design 提供的组件

android:layout_gravity=”start”用来设置滑动菜单在左边还是右边

然而还是有点儿问题,因为用户可能根本不知道有这个菜单,因为只有从屏幕左侧向右滑动才可以,所以我们要如此这般

Activity中

@Override
protected void onCreate(Bundle savedInstanceState) {
...
setSupportActionBar(toolBar);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
// 使ActionBar左侧的按钮默认可见 是一个←
actionBar.setDisplayHomeAsUpEnabled(true);
// 修改图标
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu_home);
}
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
mDrawerLayout.openDrawer(GravityCompat.START);
break;
}
return true;
}

// Material Design 提供的组件

然而功能是实现了,但是还是很丑,不过可以的,前面已经说了,有个和DrawerLayout组合用的组件,组合起来用就不丑啦.

  • 使用方法很简单,将原本TextView的位置用NavigationView替换了就是了->需要加依赖<-
    compile ‘com.android.support:design:25.3.1’
<android.support.design.widget.NavigationView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/colorPrimary" />
运行之后 效果还是一样,只不过没字了,因为不是TextView,好了NavigationView有两个属性
  1. app:menu
  2. app:headerLayout
具体是做什么的,写完你就知道了
  • 首先我们建立一个menu_nav.xml 肯定在menu文件夹中
<?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/menu_nav_1"
android:icon="@drawable/ic_menu_home"
android:title="我是1" />

<item
android:id="@+id/menu_nav_2"
android:icon="@drawable/ic_menu_home"
android:title="我是2" />

</group>

</menu>

group android:checkableBehavior=”single”
这个属性是为了限制单选

  • 我们再建立一个nav_header.xml 在layout文件夹中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp"
android:orientation="vertical">


<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/icon_header" />


</LinearLayout>

也是很简单的一个布局

  • 为NavigationView设置属性了
    <android.support.design.widget.NavigationView
android:layout_width="match_parent"
android:id="@+id/design_navigation_view"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/colorPrimary"
app:headerLayout="@layout/nav_header"
app:menu="@menu/menu_nav" />

这里是app命名空间,所以需要

xmlns:app=”http://schemas.android.com/apk/res-auto”

当然 直接alt+enter也会自动添加

运行

Material Design 提供的组件

  • 为NavigationView菜单项设置点击事件
    @Override
protected void onCreate(Bundle savedInstanceState) {
...
if (actionBar != null) {
// 使ActionBar左侧的按钮默认可见 是一个←
actionBar.setDisplayHomeAsUpEnabled(true);
// 修改图标
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu_home);
}
mNavigationView = (NavigationView) findViewById(R.id.design_navigation_view);
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_nav_1:
case R.id.menu_nav_2:
mDrawerLayout.closeDrawers();
return true;
}
return false;
}
});
}

好了我们继续来,悬浮式按钮

FloatingActionButton

知乎右下角的那个圆型按钮就是了

实现

  • xml中我们写在ToolBar下方
    <FrameLayout
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="@color/colorPrimary"></android.support.v7.widget.Toolbar>

<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/ic_menu_home" />
</FrameLayout>

都是老属性,大家一看效果便能明白:

Material Design 提供的组件

  • 基本事件

它也有基本的OnOlick事件,使用方式和普通View相同,不做过多说明

Snackbar

Snackbar不是Toast的替代品,Snackbar只是能够和用户交互而已,但是会自动消失,介于Dialog和Toast之间的组件,使用方式也是介于两者之间;

我们就在FloatingActionButton的事件中显示Snackbar

        mFloatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Snackbar.make(v, "然而我弹出来了", Snackbar.LENGTH_SHORT).setAction("点我", new View.OnClickListener() {
@Override
public void onClick(View v) {
Snackbar.make(v, "然而你点我也没用", Snackbar.LENGTH_SHORT).show();
}
}).show();
}
});

运行

Material Design 提供的组件Material Design 提供的组件

咳咳,这里Snackbar把下面的FAB挡住了,我们需要解决这个问题,谷歌为我们创造了这个问题,肯定也有相应的解决办法- ->CoordinatorLayout

CoordinatorLayout

CoordinatorLayout是一个加强版的FrameLayout,可以监听所有子控件的各种事件,然后自动帮我们做出最为合理的相应;

我们把FrameLayout替换为CoordinatorLayout

    <android.support.design.widget.CoordinatorLayout
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:layout_gravity=""
android:background="@color/colorPrimary"></android.support.v7.widget.Toolbar>

<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/ic_menu_home" />
</android.support.design.widget.CoordinatorLayout>

运行

Material Design 提供的组件

需要注意的是,只有Snackbar传入的第一个参数View是CoordinatorLayout的子组件时,此效果才会生效,因为我们传入的是v,而v是我们的FAB,所以会生效;

CardView

需要依赖

compile ‘com.android.support:cardview-v7:25.3.1’

卡片式布局 ,他可以让页面中的元素看起来就像在卡片中一样,并且能够拥有圆角和投影.

咱们把这个卡片里面装上美女放到RecyclerView中去,放松一下…

美女图片需要加载咱们用Glide

compile ‘com.github.bumptech.glide:glide:3.7.0’

  • 首先写一个item布局,顺带着看看CardView的用法
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView 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="wrap_content"
android:elevation="5dp"
android:orientation="vertical"
app:cardCornerRadius="4dp">


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">


<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="100dp"
android:scaleType="centerCrop" />


<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center_horizontal"
android:textSize="16sp" />

</LinearLayout>
</android.support.v7.widget.CardView>

app:cardCornerRadius=”4dp” 表示圆角的大小
android:elevation=”5dp”表示高度Z轴
数值越大,高度越高,投影范围越大,投影越浅,反之亦然;

CardView本质是一个FrameLayout没啥好的定位方式,咱们就嵌套一个LinearLayout;

之后我们写RecyclerView部分代码,主界面加入RecyclerView

...
</android.support.v7.widget.Toolbar>

<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>

// 此处有FAB 影响妹子美观,删除
...

写好适配器以及在Activity中设置好Manager以及初始化好数据

高能预警:!!!!!!下面会有一长串代码,不想复制的童鞋可以直接跳过

  • 首先妹子实体
public class MeiZi implements Serializable {
private String meiZiName;
private int meiZiId;

public MeiZi(String meiZiName, int meiZiId) {
this.meiZiName = meiZiName;
this.meiZiId = meiZiId;
}

public String getMeiZiName() {
return meiZiName;
}

public void setMeiZiName(String meiZiName) {
this.meiZiName = meiZiName;
}

public int getMeiZiId() {
return meiZiId;
}

public void setMeiZiId(int meiZiId) {
this.meiZiId = meiZiId;
}
}
  • 适配器
public class MeiZiAdapter extends RecyclerView.Adapter<MeiZiAdapter.MeiZiViewHolder> implements View.OnClickListener {
private List<MeiZi> meiZiList;
private Context mContext;

private OnItemClickListener listener;

public MeiZiAdapter(List<MeiZi> meiZiList, Context mContext) {
this.meiZiList = meiZiList;
this.mContext = mContext;
}

public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}

@Override
public MeiZiViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_meizi_list, parent, false);
view.setOnClickListener(this);
return new MeiZiViewHolder(view);
}

@Override
public void onBindViewHolder(MeiZiViewHolder holder, int position) {
MeiZi meiZi = meiZiList.get(position);
Glide.with(mContext).load(meiZi.getMeiZiId()).into(holder.imageView);
holder.textView.setText(meiZi.getMeiZiName());
}


@Override
public int getItemCount() {
return meiZiList.size();
}

@Override
public void onClick(View v) {
if (listener == null)
return;
listener.OnItemClick(v);
}

static class MeiZiViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textView;

public MeiZiViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.image);
textView = (TextView) itemView.findViewById(R.id.text);
}
}

public interface OnItemClickListener {
void OnItemClick(View v);
}
}
  • Activity中部分代码
...
initMeiZi();
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mManager = new GridLayoutManager(this, 2);
mAdapter = new MeiZiAdapter(meiZiList, this);
mRecyclerView.setLayoutManager(mManager);
mAdapter.setOnItemClickListener(new MeiZiAdapter.OnItemClickListener() {
@Override
public void OnItemClick(View v) {
Snackbar.make(v, "点击了第" + mRecyclerView.getChildAdapterPosition(v) + "个"
, Snackbar.LENGTH_SHORT).show();

}
});
mRecyclerView.setAdapter(mAdapter);
}

private void initMeiZi() {
meiZiList.clear();
for (int i = 0; i < 30; i++) {
Random random = new Random();
int index = random.nextInt(fruits.length);
meiZiList.add(fruits[index]);
}
}

运行
Material Design 提供的组件

妹子们还是挺好看的.不过咱们可爱的妹子们把咱们的ToolBar遮挡了…无奈,因为CoordinatorLayout本身是一个FrameLayout,怎么解决?用偏移量么?…不要,MD给我们提供了更好的解决办法

AppBarLayout

AppBarLayout是一个垂直的LinearLayout,用它来包裹一下ToolBar再设置一下属性即可

    <android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"></android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>

<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"></android.support.v7.widget.RecyclerView>

</android.support.design.widget.CoordinatorLayout>

app:layout_behavior=”@string/appbar_scrolling_view_behavior”
这个,咱们Ctrl点进去看看
android.support.design.widget.AppBarLayout$ScrollingViewBehavior

这么着写,Recycler就会在ToolBar的下方了

Material Design 提供的组件

不过这还不是AppbarLayout真正炫酷的地方.它给他的子控件提供一个属性,可以让它随着列表的操作做出相应的操作

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"></android.support.v7.widget.Toolbar>

app:layout_scrollFlags=”scroll|enterAlways|snap”>

说明一下

  • scroll –>当RecyclerView向上滚动时,Toolbar会跟着向上动
  • enterAlways –>当RecyclerView向下滑动时.ToolBar会跟着向下动并显示
  • snap –>当RecyclerView还没有完全隐藏或者显示的时候,自动判断ToolBar的显示状态

大家可以自行运行一下

RecyclerView得刷新吧,下拉刷新,MD也给我们提供了一个组件,目前知乎掘金动用到了这个SwipeRefreshLayout

SwipeRefreshLayout

没啥解释的,代码才是王道

同样也是用它包裹RecyclerView,当然,RecyclerView的部分属性要移到SwipeRefreshLayout上来;

        <android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">

<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>

此时运行的话,会这样…

Material Design 提供的组件

这个圈圈消失不掉.因为我们没有对这个SwipeRefreshLayout进行事件响应,下面我们开始写它的事件响应;

        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
// 轮询颜色
mSwipeRefreshLayout.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary, R.color.colorPrimaryDark);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
initMeiZi();
mAdapter.notifyDataSetChanged();
mSwipeRefreshLayout.setRefreshing(false);
}
});

这样就能消失了….简单吧,至于下拉加载更多,博主还没有找到适合MD规范的组件,不过这里提供一种实现方法,仅提供代码

        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
// newState RecyclerView的滑动状态
// 0 滑动停止
// 1 屏幕没停且手在屏幕上
// 2 屏幕没停 惯性滑动
// 当滑动停止并且屏幕最后一个可见的Item的pos+3大于等于ItemCount的时候 下载更多
if (newState == RecyclerView.SCROLL_STATE_IDLE && mManager.findLastVisibleItemPosition() + 3 >= mManager.getItemCount()) {
initMeiZi(true);
mAdapter.notifyDataSetChanged();
}
}
});

private void initMeiZi(boolean isLoadMore) {
if (!isLoadMore) {
meiZiList.clear();
}
for (int i = 0; i < 25; i++) {
Random random = new Random();
int index = random.nextInt(meiZis.length);
meiZiList.add(meiZis[index]);
}
}

…还剩一个CollapsingToolbarLayout了吧,那咱们就看看妹子的详情;-)

CollapsingToolbarLayout

配合ToolBar和AppBarLayout实现类似QQ空间的样式

高能预警:!!!!!!下面也会有一长串代码,不想复制的童鞋可以直接跳过

具体是详情Act以及跳转的部分代码还有xml

public class MeiZiDetailAct extends AppCompatActivity {

private Toolbar toolbar;
private ImageView imageView;
private TextView textView;

private MeiZi meiZi;


public static void actionStart(Context context, MeiZi fruit) {
Intent intent = new Intent(context, MeiZiDetailAct.class);
intent.putExtra("MEI_ZI", fruit);
context.startActivity(intent);
}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_meizi_detail);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
imageView = (ImageView) findViewById(R.id.image);
textView = (TextView) findViewById(R.id.text);

meiZi = (MeiZi) getIntent().getSerializableExtra("MEI_ZI");
if (meiZi == null) {
return;
}
Glide.with(this).load(meiZi.getMeiZiId()).into(imageView);

StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 300; i++) {
stringBuilder.append(meiZi.getMeiZiName() + "_ _" + i + "_ _");
}
textView.setText(stringBuilder);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}

跳转部分

        mAdapter.setOnItemClickListener(new MeiZiAdapter.OnItemClickListener() {
@Override
public void OnItemClick(View v) {
MeiZiDetailAct.actionStart(MeiZiListAct.this, meiZiList.get(mRecyclerView.getChildAdapterPosition(v)));
}
});
<?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:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="250dp">

<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:contentScrim="@color/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">

<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
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:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<android.support.v7.widget.CardView
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="35dp"
app:cardCornerRadius="4dp">

<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp" />
</android.support.v7.widget.CardView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>

<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_menu_home"
app:layout_anchor="@id/app_bar_layout"
app:layout_anchorGravity="bottom|end" />

</android.support.design.widget.CoordinatorLayout>

这个xml有点长,我简单说一下.
CollapsingToolbarLayout

  • app:contentScrim=”@color/colorPrimary” 区域折叠以及折叠后 显示的颜色,CollapsingToolbarLayout折叠之后 就是一个ToolBar
  • app:layout_scrollFlags=”scroll|exitUntilCollapsed”之前见过,exitUntilCollapsed说的是当折叠完成 就停下 不再移出屏幕

Image

  • app:layout_collapseMode=”parallax” 指定它的折叠模式,只有CollapsingToolbarLayout子控件才有的属性, parallax意思是折叠过程中产生错位偏移
  • app:layout_collapseMode=”pin” 折叠过程中 形状不变

最下面有一个NestedScrollView,可以响应滚动事件,因为只有滚动才能折叠,类似ScrollView但是ScrollView不支持响应滚动;

FloatingActionButton

  • app:layout_anchor=”@id/app_bar_layout” 为FAB指定锚点,使其以锚点为基准显示
  • app:layout_anchorGravity=”bottom|end” 以锚点为基准显示的位置

然后我们运行
图录制的不咋地
Material Design 提供的组件

资源都在源码中,可能和本文格式上有点出入,但是代码大致相同;

https://github.com/RedWolfChao/MaterialDesignDemo