CoordinatorLayout,AppBarLayout,CollapsingToolbarLayout,Toolbar,NestedScrollView,RecyclerView结合使用

来源:互联网 发布:数学建模最优化论文 编辑:程序博客网 时间:2024/05/22 09:52

先上几个图吧

初始状态是图一,向上滑动时  图片折叠回去变成标题栏

在这个Demo中用到了CoordinatorLayout, AppBarLayout, CollapsingToolbarLayout, Toolbar, NestedScrollView, RecyclerView这些东西, 那么下面就一一了解一下

一, CoordinatorLayout 协调布局

coordinatorLayout是谷歌推出的M包里的组件,要使用这个组件就要先添加依赖,如下:

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

再看个官方API~

CoordinatorLayoutpublic class CoordinatorLayoutextends ViewGroup implements NestedScrollingParentjava.lang.Object   ↳ android.view.View     ↳ android.view.ViewGroup       ↳ android.support.design.widget.CoordinatorLayoutCoordinatorLayout is a super-powered FrameLayout.CoordinatorLayout is intended for two primary use cases: 1 .  As a top-level application decor or chrome layout 2 .  As a container for a specific interaction with one or more child viewsBy specifying Behaviors for child views of a CoordinatorLayout you can provide many different interactions within a single parent and those views can also interact with one another. View classes can specify a default behavior when used as   a child of a CoordinatorLayout using the DefaultBehavior annotation.Behaviors may be used to implement a variety of interactions and additional layout modifications ranging from sliding drawers and panels to swipe-dismissable elements and buttons that stick to other elements as they move and animate.Children of a CoordinatorLayout may have an anchor. This view id must correspond to an arbitrary descendant of the CoordinatorLayout, but it may not be the anchored child itself or a descendant of the anchored child. This can be used to place floating views relative to other arbitrary content panes.Children can specify insetEdge to describe how the view insets the CoordinatorLayout. Any child views which are set to dodge the same inset edges by dodgeInsetEdges will be moved appropriately so that the views do not overlap.

简单的说就是CoordinatorLayout是一个超级FramLayout, 可以用作一个顶部的特殊装饰,也可以作为一个特殊的容器装载一个或多个至view.

然后最重要的就是behaviors,为子视图添加behaviors行为,例如demo中的滑动


接下来看一下我的布局

<?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:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <android.support.design.widget.AppBarLayout        android:id="@+id/appbar_Layout"        android:layout_width="match_parent"        android:layout_height="wrap_content">        <android.support.design.widget.CollapsingToolbarLayout            android:id="@+id/collapsing_layout"            android:layout_width="match_parent"            android:layout_height="wrap_content"            app:contentScrim="#88e7c7"            app:layout_scrollFlags="scroll|exitUntilCollapsed"           >            <!--title但toolbar拉升到上方时,显示的内容-->            <!--contentScrim 显示在上方作为toolbar的颜色,十六进制-->            <RelativeLayout                android:layout_width="match_parent"                android:layout_height="150dp">                <ImageView                    android:layout_width="match_parent"                    android:layout_height="150dp"                    android:scaleType="fitXY"                    android:src="@mipmap/cat"/>                <TextView                    android:id="@+id/tv1"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:padding="10dp"                    android:layout_alignParentBottom="true"                    android:text="汪汪汪汪汪汪汪汪汪汪"/>                <TextView                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:padding="10dp"                    android:text="喵呜喵呜喵呜喵呜"                    android:layout_toRightOf="@id/tv1"                    android:layout_above="@id/tv1"/>                <ImageView                    android:layout_width="60dp"                    android:layout_height="60dp"                    android:src="@mipmap/all"                    android:layout_above="@id/tv1"                    android:layout_marginLeft="20dp"/>            </RelativeLayout>            <android.support.v7.widget.Toolbar                android:id="@+id/coordinator_toolbar"                android:layout_width="match_parent"                android:layout_height="?actionBarSize"                app:layout_collapseMode="pin"                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"></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.RecyclerView                android:id="@+id/rv"                android:layout_width="match_parent"                android:layout_height="wrap_content">            </android.support.v7.widget.RecyclerView>        </LinearLayout>    </android.support.v4.widget.NestedScrollView></android.support.design.widget.CoordinatorLayout>
可以看到最外层是CordinatorLayout , 包含了一个 AppBarLayout 和 一个NestedScrollView

现在就分别介绍一下

二 . AppBarLAyout

看一下AppBarLayout的API

java.lang.Object   ↳ android.view.View     ↳ android.view.ViewGroup       ↳ android.widget.LinearLayout         ↳ android.support.design.widget.AppBarLayoutAppBarLayout is a vertical LinearLayout which implements many of the features of material designs app bar concept, namely scrolling gestures.Children should provide their desired scrolling behavior through setScrollFlags(int) and the associated layout xml attribute: app:layout_scrollFlags.This view depends heavily on being used as a direct child within a CoordinatorLayout. If you use AppBarLayout within a different ViewGroup, most of it's functionality will not work.AppBarLayout also requires a separate scrolling sibling in order to know when to scroll. The binding is done through the AppBarLayout.ScrollingViewBehavior behavior class, meaning that you should set your scrolling view's behavior to be an instance of AppBarLayout.ScrollingViewBehavior. A string resource containing the full class name is available. 
(颜色不一样不要在意哈, 没啥特殊意义,就都是重点关键词)

可以看到AppBarLayout继承LinearLayout ,是一个纵向的线性布局,想要AppBar可以折叠,就要使用AppBarLayout.,

AppBarlayout的使用严重依赖CoordinatorLayout,如果结合其他ViewGroup使用是不行的.

其中app:layout_scrollFlags属性非常重要,AppBarLayout的子View都应该添加app:layout_scrollFlags这个属性才行

1.app:layout_scrollFlags参数:

 (1)  scroll : 伴随滚动事件滚进滚出屏幕; 如果不设置这个值就不滚动哦~所以在组阁使用的时候一定要加上scroll属性,否则没效果

                      eg: app:layout_scrollFlags:scroll |  其他属性;

 (2)  enterAlways: 急速返回,只要向下滑动,View就显示

 (3)  enterAlwaysCollapsed: enterAlways的附加值。这里涉及到Child View的高度和最小高度,向下滚动时,Child View先向下滚动最小高度值,

                                                   然后其他的才(recyclerView)开始滚动,到达边界时,Child View再向下滚动,直至显示完全。

 (4)  exitUntilCollapsed: 退出屏幕,在屏幕顶端显示

 (5) span : 带有吸附效果,也就是不划出一定高度他还会弹回去,就像ViewPager

三.CollapsingToolbarLayout

 demo中AppBarlayout中包括了一个CollapsingToolbarLayout,来看一下API:

CollapsingToolbarLayout is a wrapper for Toolbar which implements a collapsing app bar. It is designed to be used as a direct child of a AppBarLayout.
父类是FrameLayout, 作为AppBarLayout的子布局使用,用来包裹Toolbar,可以让ToolBar拉伸开始显示多样化,例如我的Demo中添加了ImageView和TextView

CollapsingToolbarLayout可以添加的属性:

 (1) title: toolBar拉伸到上方时显示的标题

 (2)contentScrim : 显示为toolBar时的背景颜色

 以上两个为常用,还有的上API看去吧~(另附上API地址:CollapsingToolbarLayout API

demo中CollapsingToolBarLayout中包括了一个RelativeLayout和一个ToolBar

注意了!!!!  toolBar 的布局一定要在 RelativeLayout的下面!!!

否则作为toolBar背景并不会改变,就只是relativelayout的最下端,如图:

四.ToolBar

toolBar我就不多说了,重点就是要设置一个属性:app:layout_collapseMode折叠模式

参数:

(1)pin : 设置为这个模式时,当CollapsingToolbarLayout完全收缩后,Toolbar还可以保留在屏幕上。

(2)parallax - 在内容滚动时,CollapsingToolbarLayout中的View(比如ImageView)也可以同时滚动,

    实现视差滚动效果,通常和layout_collapseParallaxMultiplier(设置视差因子,值为0~1)搭配使用。(效果就是ImagView有个以缩小的感觉)

Demo中还设置了一个属性app:popupTheme="@style/ThemeOverlay.AppCompat.Light"

这个就是toolBar上最右边menu的主题,

五.NestedScrollView

看API:

NestedScrollView is just like ScrollView, but it supports acting as both a nested scrolling parent and child on both new and old versions of Android. Nested scrolling is enabled by default. 
继承FrameLayout,M包里的组件,跟M包里的其他组件兼容,可以跟toolbar交互,也就是升级版的ScrollView呗.

注意不要忘了Behaviors啊~~ app:layout_behavior="@string/appbar_scrolling_view_behavior"

这句上面CollapsingToolBarLayout的layout_scrollFlags属性对应,

如果NestedScrollView有这个属性,那他就会检测其他组件有没有对应属性,对应后就可实现滑动效果.

六.RecyclerView

这个我也不介绍了,直接上代码,我为什么可以用一个RecyclerView解决的事却用了NestedScrollVew加RecyclerView呢? 因为我任性!!!

下面是全部的代码

MainActivity:

public class CoordinatorLayoutActivity extends AppCompatActivity  {    private Toolbar toolbar;    private AppBarLayout appBarLayout;    private CollapsingToolbarLayout collapsingToolbarLayout;    private RecyclerViewAdapter recyclerViewAdapter ;    private RecyclerView recyclerView;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_coordinatorlayout);        recyclerView = (RecyclerView) findViewById(R.id.rv);        appBarLayout = (AppBarLayout) findViewById(R.id.appbar_Layout);        collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_layout);        toolbar = (Toolbar) findViewById(R.id.coordinator_toolbar);        //标题需要设置在setSupportActionBar之前,否则无效//        toolbar.setTitle("title");        setSupportActionBar(toolbar);        //设置返回键可用        getSupportActionBar().setHomeButtonEnabled(true);        getSupportActionBar().setDisplayHomeAsUpEnabled(true);        getSupportActionBar().setDisplayShowTitleEnabled(false);//设置toolbar不显示title        collapsingToolbarLayout.setTitleEnabled(false);//设置collapsingToolBarLayout不显示title        //右上角填充菜单        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {            @Override            public boolean onMenuItemClick(MenuItem item) {                int menuItemId = item.getItemId();                if (menuItemId == R.id.action_setting){                    Toast.makeText(CoordinatorLayoutActivity.this, "aaa", Toast.LENGTH_SHORT).show();                }else if (menuItemId == R.id.hello) {                    Toast.makeText(CoordinatorLayoutActivity.this, "bbb", Toast.LENGTH_SHORT).show();                } else if (menuItemId == R.id.date) {                    Toast.makeText(CoordinatorLayoutActivity.this, "ccc", Toast.LENGTH_SHORT).show();                }                return true;            }        });        appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {            @Override            //verticalOffset是当前appbarLayout的高度与最开始appbarlayout高度的差,向上滑动的话是负数            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {                //如果折叠后固定,那么以下判断则是折叠完成时为true                if (getSupportActionBar().getHeight() - appBarLayout.getHeight()  == verticalOffset) {                    //do something                    collapsingToolbarLayout.setTitle("title");                    collapsingToolbarLayout.setTitleEnabled(true);                }                if (getSupportActionBar().getHeight()-verticalOffset < appBarLayout.getHeight() ){                    collapsingToolbarLayout.setTitleEnabled(false);                }            }        });        recyclerView.setLayoutManager(new LinearLayoutManager(this));        recyclerViewAdapter = new RecyclerViewAdapter(this);        List<String> strings = new ArrayList<>();        for (int i = 0; i < 50; i++) {            strings.add(i+"");        }        recyclerViewAdapter.setData(strings);        recyclerView.setAdapter(recyclerViewAdapter);    }    /**     * 返回键的监听     * @param item     * @return     */    @Override    public boolean onOptionsItemSelected(MenuItem item) {        if (item.getItemId() == android.R.id.home){            Toast.makeText(this, "back", Toast.LENGTH_SHORT).show();        }        return super.onOptionsItemSelected(item);    }    /**     * 创建menu     * @param menu     * @return     */    @Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.my_menu,menu);        return true;    }}

styles:

   <!-- Base application theme. -->    <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>

my_menu:

<menu    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    >    <item android:id="@+id/action_setting"        android:orderInCategory="100"        android:title="test"        app:showAsAction="never"        />    <item android:id="@+id/hello"        android:title="hello"        app:showAsAction="never"/>    <item        android:id="@+id/date"        android:title="date"        android:icon="@mipmap/all"        app:showAsAction="ifRoom"        />    <item        android:id="@+id/share"        android:icon="@mipmap/beauty"        android:title="share"        app:showAsAction="ifRoom"        />    <item        android:id="@+id/share1"        android:icon="@mipmap/beauty"        android:title="share"        app:showAsAction="ifRoom"        /></menu>

recylerView的item布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="wrap_content"    >    <TextView        android:id="@+id/item_rv_tv"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="what"        android:padding="10dp"/></LinearLayout>

recyclerView的Adapter:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {    private Context context;    private List<String> data;    public RecyclerViewAdapter(Context context) {        this.context = context;    }    public void setData(List<String> data) {        this.data = data;        notifyDataSetChanged();    }    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View itemView = LayoutInflater.from(context).inflate(R.layout.item_rv,parent,false);        MyViewHolder myViewHolder = new MyViewHolder(itemView);        return myViewHolder;    }    @Override    public void onBindViewHolder(MyViewHolder holder, int position) {        holder.textView.setText(data.get(position));    }    @Override    public int getItemCount() {        return data == null? 0 : data.size();    }    class MyViewHolder extends RecyclerView.ViewHolder{        TextView textView;         public MyViewHolder(View itemView) {             super(itemView);             textView = (TextView) itemView.findViewById(R.id.item_rv_tv);         }     }}

MainActivity中我简单说一下:

正常情况下title的显示方式为: 没折叠时左下显示放大的title,折叠为Toolbar时,为缩小的title,过程有一个动画,然而我并不想在他没折叠的时候显示title,

因为我里面加了小图标啊,title显示的话就把我的小图标遮挡了,所以我设置它拉下来时不显示title,拉上去缩微toolBar时显示title,

重点就是:1.collapsingToolbarLayout.setTitleEnabled(false);//开始时设置collapsingToolBarLayout不显示title

                 2.appBarLayout.addOnOffsetChangedListener()中进行监听判断他的状态



献上压缩包 http://download.csdn.net/download/liang_duo_yu/9765252

好了,以上

菜鸟加油!






0 0
原创粉丝点击