SwipeRefreshLayout+CoordinatorLayout+AppBarLayout+RecyclerView多层嵌套,实现下拉刷新以及共同滚动
layout.xml布局
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout 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/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:fitsSystemWindows="false"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<androidx.appcompat.widget.Toolbar
...
app:layout_scrollFlags="scroll|enterAlways"/>
<com.google.android.material.tabs.TabLayout
...
app:layout_scrollFlags="scroll|enterAlways"/>
<!-- 或者其他视图,指定app:layout_scrollFlags, xml中不指定时, -->
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
关键代码(kotlin)
private var _binding: LayoutBinding? = null
private val binding get() = _binding!!
override fun onDestroy() {
super.onDestroy()
_binding = null // 视图销毁时
}
需要隐藏系统的ActionBar
- Activity中隐藏
supportActionBar?.hide() - Fragment隐藏的代码
(requireActivity() as AppCompatActivity).supportActionBar?.show()
AppBarLayout需要添加OnOffsetChangedListener控制SwipeRefreshLayout
private var isExpend = true // 当页面重新恢复时,AppBarLayout根据isExpend的值,确定是否展开
binding.appBarLayout.setExpanded(isExpend) // 默认appBarLayout展开
binding.appBarLayout.addOnOffsetChangedListener { appBarLayout:AppBarLayout, verticalOffset ->
// verticalOffset: AppBarLayout的垂直偏移量,垂直偏移量大于等于0时,SwipeRefreshLayout 才可被启用,
// 否则下拉时,AppBarLayout不能下拉展现完全,SwipeRefreshLayout 就会执行刷新
binding.swipeRefresh.isEnabled = verticalOffset >=0
// 当页面重新恢复时,AppBarLayout根据isExpend的值,确定是否展开
isExpend = appBarLayout.totalScrollRange + verticalOffset > appBarLayout.totalScrollRange / 3
}
AppBarLayout是CoordinatorLayout的直接子类,AppBarLayout的大部分功能只能在CoordinatorLayout中产生作用,因此AppBarLayout是CoordinatorLayout的子类时,才能完全的展示它的强大功能。
AppBarLayout.LayoutParams.setScrollFlags(int)布局xml属性:app:layout_scrollFlags提供AppBarLayout子视图的滚动行为。
// AppBarLayout的子View设置AppBarLayout.LayoutParams.setScrollFlags(int)的相关代码
val lp = AppBarLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
lp.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL //相当于app:layout_scrollFlags = "scroll"
// 子View的“layoutParams = lp”即可
layout_scrollFlags值解释说明
LayoutParams值 | layout_scrollFlags | 解释说明 |
---|---|---|
SCROLL_FLAG_NO_SCROLL 整型值:0x0 -> 0 | noScroll 整型值:0x0 -> 0 | Disable scrolling on the view. This flag should not be combined with any of the other scroll flags. |
SCROLL_FLAG_SCROLL 整型值:0x1 -> 1 | scroll 整型值:0x1 -> 1 | The view will be scroll in direct relation to scroll events. This flag needs to be set for any of the other flags to take effect. If any sibling views before this one do not have this flag, then this value has no effect. |
SCROLL_FLAG_EXIT_UNTIL_COLLAPSED 整型值:1<<1 -> 2 | exitUntilCollapsed 整型值:0x2 -> 2 | When exiting (scrolling off screen) the view will be scrolled until it is ‘collapsed’. The collapsed height is defined by the view’s minimum height. |
SCROLL_FLAG_ENTER_ALWAYS 整型值:1<<2 -> 4 | enterAlways 整型值:0x4 -> 4 | When entering (scrolling on screen) the view will scroll on any downwards scroll event, regardless of whether the scrolling view is also scrolling. This is commonly referred to as the ‘quick return’ pattern. |
SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED 整型值:1<<3 -> 8 | enterAlwaysCollapsed 整型值:0x8 -> 8 | An additional flag for ‘enterAlways’ which modifies the returning view to only initially scroll back to it’s collapsed height. Once the scrolling view has reached the end of it’s scroll range, the remainder of this view will be scrolled into view. The collapsed height is defined by the view’s minimum height. |
SCROLL_FLAG_SNAP 整型值:1<<4 -> 16 | snap 整型值:0x10 -> 16 | Upon a scroll ending, if the view is only partially visible then it will be snapped and scrolled to it’s closest edge.For example, if the view only has its bootom 25% displayed, it will be scrolled off screen completely. Conversely, if it bottom 75% is visible then it will be scrolled full into view. |
SCROLL_FLAG_SNAP_MARGINS 整型值:1<<5 -> 32 | snapMargins 整型值:0x20 -> 32 | An additional flag to be used with ‘snap’. If set, the view will be snapped to its top and bottom margins, as opposed to the edges of the view itself. |