一、前言
二、简单滚动效果实例
2.1 Toolbar 滚动效果
Toolbar 帮我们实现了标题栏,但是很多时候并不能满足需求,所以不如自定义标题栏好。简单了解下 Toolbar的使用。
- 滚动效果,效果图:

布局文件:
<?xml version="1.0" encoding="utf-8"?><androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:app="http://schemas.android.com/apk/res-auto"><com.google.android.material.appbar.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><androidx.appcompat.widget.Toolbarandroid:id="@+id/tb_tb_scroll_tb"android:layout_width="match_parent"android:layout_height="wrap_content"app:navigationIcon="@mipmap/ic_navigation_back_white"app:title="toolbar滚动"app:titleTextColor="@color/white"android:background="@color/blue_74D3FF"app:layout_scrollFlags="scroll|enterAlways|snap"/></com.google.android.material.appbar.AppBarLayout><include layout="@layout/content_scrolling"/><!-- <androidx.core.widget.NestedScrollView--><!-- android:layout_width="match_parent"--><!-- android:layout_height="match_parent"--><!-- app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">--><!-- <TextView--><!-- android:layout_width="wrap_content"--><!-- android:layout_height="wrap_content"--><!-- android:layout_margin="@dimen/m12"--><!-- android:text="@string/large_text" />--><!-- </androidx.core.widget.NestedScrollView>--><!-- 悬浮按钮--><com.google.android.material.floatingactionbutton.FloatingActionButtonandroid:id="@+id/fab_tb_scroll_menu"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="end|bottom"android:layout_margin="@dimen/m12"android:src="@mipmap/ic_navigation_menu"/></androidx.coordinatorlayout.widget.CoordinatorLayout>
<?xml version="1.0" encoding="utf-8"?><androidx.core.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"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="@dimen/m12"android:text="@string/large_text" /></androidx.core.widget.NestedScrollView>
2.2 简单折叠布局
效果图:
布局:
<?xml version="1.0" encoding="utf-8"?><androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:app="http://schemas.android.com/apk/res-auto"><com.google.android.material.appbar.AppBarLayoutandroid:id="@+id/abl_collaspone_appbar"android:layout_width="match_parent"android:layout_height="250dp"android:background="@color/red_FF8EB7"><com.google.android.material.appbar.CollapsingToolbarLayoutandroid:id="@+id/ctl_collaspone_collapsing"android:layout_width="match_parent"android:layout_height="match_parent"app:contentScrim="@color/blue_74D3FF"app:layout_scrollFlags="scroll|exitUntilCollapsed"><ImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:src="@mipmap/image13"android:scaleType="centerCrop"app:layout_collapseMode="parallax"/><androidx.appcompat.widget.Toolbarandroid:id="@+id/tb_collaspingone_tb"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_collapseMode="pin"app:titleTextColor="@color/white"app:navigationIcon="@mipmap/ic_navigation_back_white"/></com.google.android.material.appbar.CollapsingToolbarLayout></com.google.android.material.appbar.AppBarLayout><include layout="@layout/content_scrolling"/><com.google.android.material.floatingactionbutton.FloatingActionButtonandroid:id="@+id/fab_collaspingone_fab"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/ic_cloud"app:layout_anchor="@id/abl_collaspone_appbar"app:layout_anchorGravity="end|bottom"android:layout_margin="@dimen/m10"/></androidx.coordinatorlayout.widget.CoordinatorLayout>
Activity:
class CollapsingOneActivity: AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_collasping_one)/*layout_collapseMode: 用来指当前控件在 CollapsingToolbarLayout 在折叠过程中的折叠模式,其中 Toolbar 指定成 pin, 表示在折叠过程中位置始终保持不变,ImageView 指定成 parallax,表示在折叠过程中会有一定的错位偏移*/fab_collaspingone_fab.setOnClickListener {Snackbar.make(fab_collaspingone_fab,"hello",Snackbar.LENGTH_SHORT).show()}tb_collaspingone_tb.setNavigationOnClickListener {finish()}}}
2.3 透明状态栏简单折叠布局
效果图:
布局:
<?xml version="1.0" encoding="utf-8"?><androidx.coordinatorlayout.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:fitsSystemWindows="true"><com.google.android.material.appbar.AppBarLayoutandroid:id="@+id/abl_collaspone_appbar"android:layout_width="match_parent"android:layout_height="250dp"android:background="@color/red_FF8EB7"android:fitsSystemWindows="true"><com.google.android.material.appbar.CollapsingToolbarLayoutandroid:id="@+id/ctl_collaspone_collapsing"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"app:contentScrim="@color/blue_74D3FF"app:layout_scrollFlags="scroll|exitUntilCollapsed"><ImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"android:scaleType="centerCrop"android:src="@mipmap/image13"app:layout_collapseMode="parallax" /><androidx.appcompat.widget.Toolbarandroid:id="@+id/tb_collaspingone_tb"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_collapseMode="pin"app:navigationIcon="@mipmap/ic_navigation_back_white"app:titleTextColor="@color/white" /></com.google.android.material.appbar.CollapsingToolbarLayout></com.google.android.material.appbar.AppBarLayout><include layout="@layout/content_scrolling" /><com.google.android.material.floatingactionbutton.FloatingActionButtonandroid:id="@+id/fab_collaspingone_fab"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="@dimen/m10"android:src="@drawable/ic_cloud"app:layout_anchor="@id/abl_collaspone_appbar"app:layout_anchorGravity="end|bottom" /></androidx.coordinatorlayout.widget.CoordinatorLayout>
Activity:
class CollapsingOneActivity: AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_collasping_one)//设置沉浸式状态栏,可以设置状态栏颜色StatusBarUtils.initStatusBarStyle(this,true)/*layout_collapseMode: 用来指当前控件在 CollapsingToolbarLayout 在折叠过程中的折叠模式,其中 Toolbar 指定成 pin, 表示在折叠过程中位置始终保持不变,ImageView 指定成 parallax,表示在折叠过程中会有一定的错位偏移*/fab_collaspingone_fab.setOnClickListener {Snackbar.make(fab_collaspingone_fab,"hello",Snackbar.LENGTH_SHORT).show()}tb_collaspingone_tb.setNavigationOnClickListener {finish()}}}
2.3 透明状态栏简单折叠布局带标题
设置折叠时标题居中无效,会因为设置了返回按钮而偏向右边,效果图:
布局和上面完全一样,可以在 xml 中设置图标相关,也可以在代码中设置,在代码中设置如下:
//折叠标题设置ctl_collaspone_collapsing.title = "测试标题"ctl_collaspone_collapsing.collapsedTitleGravity = Gravity.STARTctl_collaspone_collapsing.expandedTitleGravity = Gravity.BOTTOMctl_collaspone_collapsing.setCollapsedTitleTextColor(ContextCompat.getColor(this,R.color.red))ctl_collaspone_collapsing.setExpandedTitleColor(ContextCompat.getColor(this,R.color.blue_74D3FF))
三、加上刷新
- 第一种,刷新和折叠布局平级,适用于折叠布局不是很高的情况
效果图:
xml 布局:
<?xml version="1.0" encoding="utf-8"?><androidx.coordinatorlayout.widget.CoordinatorLayout 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"xmlns:app="http://schemas.android.com/apk/res-auto"><com.google.android.material.appbar.AppBarLayoutandroid:id="@+id/appbar_refresh_appbar"android:layout_width="match_parent"android:layout_height="250dp"android:background="@color/red_FF8EB7"><com.google.android.material.appbar.CollapsingToolbarLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"app:contentScrim="@color/blue_74D3FF"app:layout_scrollFlags="scroll|exitUntilCollapsed"><ImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"android:src="@mipmap/image13"app:layout_collapseMode="parallax" /><androidx.appcompat.widget.Toolbarandroid:id="@+id/tb_collaspingone_tb"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_collapseMode="pin"app:navigationIcon="@mipmap/ic_navigation_back_white"app:titleTextColor="@color/white"/></com.google.android.material.appbar.CollapsingToolbarLayout></com.google.android.material.appbar.AppBarLayout><androidx.swiperefreshlayout.widget.SwipeRefreshLayoutandroid:id="@+id/srl_refresh_refresh"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_refresh_refresh"android:layout_width="match_parent"android:layout_height="wrap_content"/></androidx.swiperefreshlayout.widget.SwipeRefreshLayout><com.google.android.material.floatingactionbutton.FloatingActionButtonandroid:id="@+id/fab_refresh_fab"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="@dimen/m10"android:src="@drawable/ic_cloud"app:layout_anchor="@id/appbar_refresh_appbar"app:layout_anchorGravity="end|bottom" /></androidx.coordinatorlayout.widget.CoordinatorLayout>
activity:
class RefreshActivity:AppCompatActivity() {val list = arrayListOf("测试数据一","测试数据二","测试数据三","测试数据四","测试数据五","测试数据六","测试数据七","测试数据八","测试数据九","测试数据一","测试数据二","测试数据三","测试数据四","测试数据五","测试数据六","测试数据七","测试数据八","测试数据九")val mAdapter by lazy { RefreshAdapter() }override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_refresh)rv_refresh_refresh?.run {layoutManager = LinearLayoutManager(this@RefreshActivity)adapter = mAdaptersetHasFixedSize(true)}mAdapter.setList(list)//mAdapter.setNewInstance()srl_refresh_refresh.setOnRefreshListener {srl_refresh_refresh.postDelayed({srl_refresh_refresh.isRefreshing = false},1000)}fab_refresh_fab.setOnClickListener {Snackbar.make(fab_refresh_fab,"hello", Snackbar.LENGTH_SHORT).show()}}}
adapter:
class RefreshAdapter(layoutId: Int = R.layout.item_refresh): BaseQuickAdapter<String,BaseViewHolder>(layoutId){override fun convert(holder: BaseViewHolder, item: String) {holder.itemView.tv_item_refresh_text.text = item}}
- 刷新放在最外层,需要处理滑动冲突
效果图:
布局:
<?xml version="1.0" encoding="utf-8"?><androidx.swiperefreshlayout.widget.SwipeRefreshLayoutandroid:id="@+id/srl_refresh_refresh"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"xmlns:app="http://schemas.android.com/apk/res-auto"><androidx.coordinatorlayout.widget.CoordinatorLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><com.google.android.material.appbar.AppBarLayoutandroid:id="@+id/appbar_refresh_appbar"android:layout_width="match_parent"android:layout_height="250dp"android:background="@color/red_FF8EB7"><com.google.android.material.appbar.CollapsingToolbarLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"app:contentScrim="@color/blue_74D3FF"app:layout_scrollFlags="scroll|exitUntilCollapsed"><ImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"android:src="@mipmap/image13"app:layout_collapseMode="parallax" /><androidx.appcompat.widget.Toolbarandroid:id="@+id/tb_collaspingone_tb"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_collapseMode="pin"app:navigationIcon="@mipmap/ic_navigation_back_white"app:titleTextColor="@color/white"/></com.google.android.material.appbar.CollapsingToolbarLayout></com.google.android.material.appbar.AppBarLayout><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_refresh_refresh"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"/><com.google.android.material.floatingactionbutton.FloatingActionButtonandroid:id="@+id/fab_refresh_fab"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="@dimen/m10"android:src="@drawable/ic_cloud"app:layout_anchor="@id/appbar_refresh_appbar"app:layout_anchorGravity="end|bottom" /></androidx.coordinatorlayout.widget.CoordinatorLayout></androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
activity:
class Refresh2Activity:AppCompatActivity() {val list = arrayListOf("测试数据一","测试数据二","测试数据三","测试数据四","测试数据五","测试数据六","测试数据七","测试数据八","测试数据九","测试数据一","测试数据二","测试数据三","测试数据四","测试数据五","测试数据六","测试数据七","测试数据八","测试数据九")val mAdapter by lazy { RefreshAdapter() }override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_refresh2)rv_refresh_refresh?.run {layoutManager = LinearLayoutManager(this@Refresh2Activity)adapter = mAdaptersetHasFixedSize(true)}mAdapter.setList(list)//mAdapter.setNewInstance()srl_refresh_refresh.setOnRefreshListener {srl_refresh_refresh.postDelayed({srl_refresh_refresh.isRefreshing = false},1000)}//下拉刷新和下拉会有冲突appbar_refresh_appbar.addOnOffsetChangedListener(object : AppBarStateChangeListener(){override fun onStateChanged(appBarLayout: AppBarLayout?, state: State?) {if( state == State.EXPANDED ) {//展开状态srl_refresh_refresh.isEnabled = true}else if(state == State.COLLAPSED){//折叠状态srl_refresh_refresh.isEnabled = false}else {//中间状态srl_refresh_refresh.isEnabled = false}}})//悬浮按钮fab_refresh_fab.setOnClickListener {Snackbar.make(fab_refresh_fab,"hello", Snackbar.LENGTH_SHORT).show()}}}
AppBarStateChangeListener:
public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {public enum State {EXPANDED,COLLAPSED,IDLE}private State mCurrentState = State.IDLE;@Overridepublic final void onOffsetChanged(AppBarLayout appBarLayout, int i) {if (i == 0) {if (mCurrentState != State.EXPANDED) {onStateChanged(appBarLayout, State.EXPANDED);}mCurrentState = State.EXPANDED;} else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {if (mCurrentState != State.COLLAPSED) {onStateChanged(appBarLayout, State.COLLAPSED);}mCurrentState = State.COLLAPSED;} else {if (mCurrentState != State.IDLE) {onStateChanged(appBarLayout, State.IDLE);}mCurrentState = State.IDLE;}}public abstract void onStateChanged(AppBarLayout appBarLayout, State state);}
