Material Design 提供的组件

本文通过实战方式介绍了MaterialDesign的重要组件如Toolbar、DrawerLayout、NavigationView等,并展示了如何利用这些组件实现复杂的功能,例如侧滑菜单、悬浮按钮及卡片式布局。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反编译看的实在有点头疼,于是就仔细研究了一下前一段时间的一篇文章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也是这个道理

运行

这里写图片描述

..好难看

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

    }

运行

这里写图片描述

出现我们的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>

运行

这里写图片描述

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;
    }

//

然而功能是实现了,但是还是很丑,不过可以的,前面已经说了,有个和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也会自动添加

运行

这里写图片描述

  • 为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>

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

这里写图片描述

  • 基本事件

它也有基本的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();
            }
        });

运行

这里写图片描述这里写图片描述

咳咳,这里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>

运行

这里写图片描述

需要注意的是,只有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]);
        }
    }

运行
这里写图片描述

妹子们还是挺好看的.不过咱们可爱的妹子们把咱们的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的下方了

这里写图片描述

不过这还不是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>

此时运行的话,会这样…

这里写图片描述

这个圈圈消失不掉.因为我们没有对这个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” 以锚点为基准显示的位置

然后我们运行
图录制的不咋地
这里写图片描述

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

https://github.com/RedWolfChao/MaterialDesignDemo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值