MaterialDesign学习笔记3:CoordinatorLayout基本用法

Material Design:CoordinatorLayout基本用法

CoordinatorLayout 扩展了许多能实现 Google Material Design scrolling effects(滚动技巧)的效果。目前,这个框架内提供了几种方法使它并不需要自定义动画就可以运行,有以下几种效果:

  • 上下移动 FloatingActionButton 以便给 Snackbar 腾出空间
  • 扩张或收缩 Toolbar 或者顶部空间以便给 main content 腾出空间
  • 控制某个 view 可以扩张或收缩,以及扩张或收缩的速率大小,包括 parallax scrolling effects 动画

接下来会以CoordinatorLayout的三个基本用法展开。

涉及到的控件:
1. CoordinatorLayout
2. FloatingActionButton
3. Snackbar
4. AppBarLayout
5. Toolbar
6. CollapsingToolbarLayout
7. RecyclerView
8. NestedScrollView


首先在 build.gradle 导入相对应的包:

compile 'com.android.support:design:23.4.0'


FloatingActionButton and Snackbar

FloatingActionButton and Snackbar

布局

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.tangvim.floatingsnackbar.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <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/AppTheme.PopupOverlay" />

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

    <!--<include layout="@layout/content_scrolling" />-->

    <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="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />

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

CoordinatorLayout 里嵌套 FloatingActionButton

CoordinatorLayout作为 “ super-powered FrameLayout ” ,设置子视图的Android:layout_gravity属性控制位置。

FloatingActionButton是最简单的使用CoordinatorLayout的例子,FloatingActionButton默认使用FloatingActionButton.Behavior

代码

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                //这里的单击事件代表点击消除Action后的响应事件
                            }
                        }).show();
            }
        });
    }
}

FloatingActionButton 用法跟 Button 类似。

Snackbar 用法跟 Toast 用法类似。Snackbar在出现一定时间后,也会跟Toast一样消失。

需要注意的是:

  • Snackbar.make()第一个参数作为Snackbar显示的基准元素。
  • setAction()设置的Action也可以设置多个。如果第二个参数为null则没有按键。

滑动扩展或收缩 Toolbar

Toolbar

为了使得 Toolbar 有滑动效果,必须做到如下三点:

  1. CoordinatorLayout 作为布局的父布局容器。
  2. 给需要滑动的组件设置 app:layout_scrollFlags=”scroll|enterAlways” 属性。
  3. 给滑动的组件设置 app:layout_behavior 属性

布局

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.tangvim.scrolltoolbar.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/appbar_padding_top"
        android:theme="@style/AppTheme.AppBarOverlay">

        <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"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

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

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

    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

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

布局文件跟之前的TabLayout+ViewPaper实现滑动切换相似。只是在ViewPaper 里面放RecyclerView

AppBarLayout继承自LinearLayout,布局方向为垂直方向。所以你可以把它当成垂直布局的LinearLayout来使用。AppBarLayout是在LinearLayou上加了一些材料设计的概念,它可以让你定制当 某个可滚动View 的滚动手势发生变化时,其内部的子View实现何种动作。

注意: 根据 Goolge 官方文档,官方希望 AppBarLayout 作为第一个子 view 嵌套在 CoordinatorLayout 中。 然后,我们在 AppBarLayout 和 你所想要滑动的 View 之间建立一个联系。 给 RecyclerView 或者其它例如 NestedScrollView 一样能够使用滑动的 View 添加一个属性 app:layout_behavior

support library 中包含了一个特别的字符串资源 @string/appbar_scrolling_view_behavior,它映射自 AppBarLayout.ScrollingViewBehavior,当指定视图的滑动事件发生了,它就用来通知 AppBarLayout。这个 behavior 属性必须添加在触发滑动事件的那个 view 上。

通过使用 app:layout_scrollFlags 属性,RecyclerView 的滑动事件会改变 AppBarLayout 的子 views。

scroll 这个Flag必须和enterAlwaysenterAlwaysCollapsedexitUntiCollapsed或者 snap 一起使用:

  • enterAlways:界面向上滑动的时候,这个 view 就变得可见。当 当前 list 滑动到底部然后想让 Toolbar 在界面上划的时候就能出来的时候,这个 flag 是非常有用的。通常情况下,我们希望 Toolbar 只会在 list 滑动到顶部的时候出现。
  • enterAlwaysCollapsed:通常情况下,如果仅仅使用 enterAlways,只要你向上滑动界面,Toolbar 就会不停扩展。假设当前我们已经声明了 enterAlways 属性,并且我们定义了一个 minHeight,那么你也可以指定 enterAlwaysCollapsed,当这个设置被使用的时候,那么在向上滑动界面的过程中,你的 view 会一直以 minHeight 的高度显示在屏幕上,并且在到达顶端的时候继续滑动的话,它将扩展到它的最大高度。
  • exitUntilCollapsed:当 scroll 属性被设置了,我们向下滑动界面的时候,界面中全部的内容都会跟着滑动。通过定义 minHeightexitUntilCollapsed,在 Toolbar 到达最小的高度的时候,它会一直停留在屏幕上端。
  • snap:使用这个操作可以定义当一个 view 局部减少时候的响应。假如滑动结束的时候,当前 view 有小于一半的内容被滑动到屏幕外面去了,那么就恢复成最开始的样子,如果有大于一半的内容被滑动到屏幕外,那么滑动结束的时候,这个 view 就会全部消失。

补充: Toobar主要是用来替换ActionBar的,使用Toobar先要把ActionBar隐藏掉,隐藏方式有很多,最常用的是在styles.xml加上下面两行:

<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>

滑动扩展或收缩 Toolbar 并不需要代码实现。下面讲下RecyclerView的基本使用。


RecyclerView 的基本使用方法

代码部分跟TabLayout+ViewPaper实现滑动切换相似的就不再复述。

public static class PlaceholderFragment extends Fragment {

    private RecyclerView recyclerView;
    private RecyclerAdapter recyclerAdapter;
    private List<String> datas;

    private static final String ARG_SECTION_NUMBER = "section_number";

    public PlaceholderFragment() {
    }

    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);

        initList();

        recyclerView = (RecyclerView) rootView.findViewById(R.id.rv_content);
        recyclerAdapter = new RecyclerAdapter(getActivity(), datas);

        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.setAdapter(recyclerAdapter);

        return rootView;
    }

    private void initList() {
        datas = new ArrayList<String>();
        for (int i = 0; i < 100; i++) {
            datas.add("item:" + i);
        }
    }
}

上面PlaceholderFragmentViewPaper加载的Fragment

RecyclerView 用法和 ListView 有些相似。RecyclerView主要是使用setLayoutManager()setAdapter()方法。

接下来是RecyclerView.Adapter的定义:

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
    private LayoutInflater inflater;
    private Context context;
    private List<String> datas;

    public RecyclerAdapter(Context context, List<String> datas) {
        this.inflater = LayoutInflater.from(context);
        this.context = context;
        this.datas = datas;
    }

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

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.fragment_item, parent, false);
        MyViewHolder holder = new MyViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.textView.setText(datas.get(position));
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView textView;

        public MyViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv_item);
        }
    }
}

RecyclerView.Adapter 需要实现3个方法:

  • onCreateViewHolder():这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。
  • onBindViewHolder():这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder
  • getItemCount():这个方法就类似于BaseAdaptergetCount()方法了,即总共有多少个条目。

更多 RecyclerView 用法参考Android开发之RecyclerView的使用全解


构建折叠效果 CollapsingToolbarLayout

CollapsingToolbarLayout

使用 CollapsingToolbarLayout 实现折叠效果,需要注意3点:

  1. AppBarLayout 的高度固定
  2. CollapsingToolbarLayout 的子视图设置 layout_collapseMode 属性
  3. 关联悬浮视图设置 app:layout_anchorapp:layout_anchorGravity 属性
<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.tangvim.scrolltoolbar2.ScrollingActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:collapsedTitleTextAppearance="@style/TextAppearance.AppCompat.Body1"
            app:expandedTitleTextAppearance="@style/TextAppearance.AppCompat.Title"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/iv_title"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                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"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_scrolling" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|end"
        app:srcCompat="@android:drawable/ic_dialog_email" />

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

CollapsingToolbarLayout 是用来对 Toolbar 进行再次包装的ViewGroup,主要是用于实现折叠的AppBar效果。它需要放在 AppBarLayout 布局里面,并且作为 AppBarLayout 的直接子View。

CollapsingToolbarLayout 的几个主要功能:

  1. 折叠Title(Collapsing title):当布局内容全部显示出来时,title是最大的,但是随着View逐步移出屏幕顶部,title变得越来越小。你可以通过调用 setTitle() 函数来设置title。
  2. 内容纱布(Content scrim):根据滚动的位置是否到达一个阀值,来决定是否对View“盖上纱布”。可以通过 setContentScrim(Drawable) 来设置纱布的图片.
  3. 状态栏纱布(Status bar scrim):根据滚动位置是否到达一个阀值,来决定是否对状态栏“盖上纱布”,你可以通过 setStatusBarScrim(Drawable) 来设置纱布图片,但是只能在 LOLLIPOP 设备上面有作用。
  4. 视差滚动子View(Parallax scrolling children):子View可以选择在当前的布局当时是否以“视差”的方式来跟随滚动。(PS:其实就是让这个View的滚动的速度比其他正常滚动的View速度稍微慢一点)。将布局参数 app:layout_collapseMode 设为 parallax
  5. 将子View位置固定(Pinned position children):子View可以选择是否在全局空间上固定位置,这对于 Toolbar 来说非常有用,因为当布局在移动时,可以将 Toolbar 固定位置而不受移动的影响。 将 app:layout_collapseMode 设为 pin

app:collapsedTitleTextAppearanceapp:expandedTitleTextAppearance 分别设置折叠和展开文本显示的样式。

一般情况下,我们需要给 Toolbar 设置标题,现在我们给 CollapsingToolBarLayout 设置标题而不是 Toolbar。如下:

CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle("Title");

注意当使用 CollapsingToolbarLayout 时,系统状态栏应该设置成半透明(API 19)的或透明的(API 21),就像这个文件 。特别地,下面的样式应该写在 res/values-xx/styles.xml 中以示说明:

<!-- res/values-v19/styles.xml -->
<style name="AppTheme" parent="Base.AppTheme">
    <item name="android:windowTranslucentStatus">true</item>
</style>

<!-- res/values-v21/styles.xml -->
<style name="AppTheme" parent="Base.AppTheme">
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

···

PS: FloatingActionButton 通过指定 app:layout_anchor , app:layout_anchorGravity ,指定显示位置的锚点。这里 FloatingActionButton 依附到 AppBarLayout

@layout/content_scrolling 定义如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.tangvim.scrolltoolbar2.ScrollingActivity"
    tools:showIn="@layout/activity_scrolling">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:text="@string/large_text" />

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

这里用到 NestedScrollView 来做滚动的View,layout_behavior 也定义在这里面。


参考:

android CoordinatorLayout使用

Android Design Support Library使用详解

玩转AppBarLayout,更酷炫的顶部栏

CoordinatorLayout

Demo:cheesesquare

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值