当与 viewpager 和 recyclerview 一起使用时,CollapsingToolbarLayout 的部分内容会粘在顶部
Part of the content of a CollapsingToolbarLayout is getting sticky on top, when used with viewpager and recyclerview
-
android
-
android-recyclerview
-
android-coordinatorlayout
-
android-collapsingtoolbarlayout
-
android-nestedscrollview
我正在尝试实现这样的布局:
问题是当卡片向上滚动时触摸到工具栏,它不再像这样向上滚动:
我希望它向上滚动直到 viewpager 填满屏幕,即至少矩形卡应该向上滚动到工具栏之外(甚至 tabLayout 也可以向上滚动)。但我不希望它停留在顶部。
主要布局在这里:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:showIn="@layout/activity_main">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/background_dark"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbarCollapse"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="190dp"
android:minHeight="190dp"
android:src="@drawable/ic_launcher_foreground"
app:layout_collapseMode="parallax" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:behavior_overlapTop="90dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/lin"
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/debit_card_item" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_marginTop="40dp"
android:background="?attr/colorPrimary" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
分页器的片段在 NestedScrollView 中,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rcView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.core.widget.NestedScrollView>
我尝试过的事情:
- 我尝试删除线性布局上方的 NestedScrollView,并将
app:behavior_overlapTop="90dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
添加到线性布局。但它仍然给我相同的输出。
- 静态设置视图分页器的高度(给出相同的结果)。
-->>>编辑<<<
3. 我想到了一个解决方法,我正在尝试将自定义行为添加到我的 mainActivity 中的 LinearLayout。从而减小矩形卡的margin-bottom和height。当我猛击并关闭折叠的工具栏时,它会产生很好的效果。但是当我按住并滚动时,屏幕闪烁如下图:
我的自定义行为是
class CustomHeaderBehavior : AppBarLayout.ScrollingViewBehavior {
private var mContext: Context
var height = 0
var width = 0
var marginBottom = 0
var firstTime = true
constructor(
context: Context,
attrs: AttributeSet?
) : super(context, attrs) {
mContext = context
}
constructor(
context: Context?,
attrs: AttributeSet?,
mContext: Context
) : super(context, attrs) {
this.mContext = mContext
}
override fun layoutDependsOn(
parent: CoordinatorLayout,
child: View,
dependency: View
): Boolean {
return super.layoutDependsOn(parent, child, dependency)
}
override fun onDependentViewChanged(
parent: CoordinatorLayout,
childP: View,
dependency: View
): Boolean {
val child = childP.findViewById<RelativeLayout>(R.id.cardParent)
val maxScroll: Int = (dependency as AppBarLayout).totalScrollRange
val percentage =
abs(dependency.y) / maxScroll.toFloat()
Log.d("Behavx","D.y "+abs(dependency.y)+ " m s "+maxScroll+ " p "+percentage)
val lp: LinearLayout.LayoutParams =
child.layoutParams as LinearLayout.LayoutParams
if(firstTime){
height = child.height
width = child.width
marginBottom = lp.bottomMargin
firstTime = false
}
Log.d("Behaviour", "P "+ ((1-(percentage))*100).toString() +" H " +height+ " U H " +(height*(((1-(percentage))*100))/100) )
// lp.bottomMargin = ((marginBottom*(((1-(percentage))*100))/100) - ((height*((((percentage))*100))/100))).toInt()
lp.bottomMargin = ((marginBottom*(((1-(percentage))*100))/100)).toInt() //updating margin bottom
lp.height = ((height*(((1-(percentage))*100))/100)).toInt() //updating height
child.layoutParams = lp
child.alpha = 1 - (percentage * 4)
return super.onDependentViewChanged(parent, childP, dependency)
}
companion object {
fun getToolbarHeight(context: Context): Int {
var result = 0
val tv = TypedValue()
if (context.theme.resolveAttribute(R.attr.actionBarSize, tv, true)) {
result = TypedValue.complexToDimensionPixelSize(
tv.data,
context.resources.displayMetrics
)
}
return result
}
}
}
闪烁似乎正在发生,因为 dependency.y
随机变得错误,同时我按住并滚动并更新卡片的高度(如果我只更新边距,则不会发生闪烁)。由于某种原因,控制宽度正在顺利进行。但不幸的是,这对我没有帮助。
我也尝试通过向应用栏添加 offsetChangedListener
来做类似的事情,如下所示:
appBar.addOnOffsetChangedListener(OnOffsetChangedListener { appBarLayout, verticalOffset ->
如果 (abs(verticalOffset) == appBarLayout.totalScrollRange) {
// 折叠
cardParent.visibility = View.GONE
} 别的 {
//展开
cardParent.visibility = View.VISIBLE
}
})
但我仍然遇到闪烁
我在这里添加了示例项目:
github link
自定义行为被推送到新分支 custom_behaviour
为了实现该效果,卡片布局应位于折叠工具栏内。
尝试替换这个:
<ImageView
android:layout_width="match_parent"
android:layout_height="190dp"
android:minHeight="190dp"
android:src="@drawable/ic_launcher_foreground"
app:layout_collapseMode="parallax" />
与:
<include layout="@layout/debit_card_item"
android:layout_width="match_parent"
android:layout_height="190dp"
android:minHeight="190dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="72dp"
app:layout_collapseMode="parallax"/>
并删除 NestedScrollView 中的 <include layout="@layout/debit_card_item" />
。
希望对您有所帮助。
终于解决了我的问题。我将卡片添加到折叠布局中,如 Kalyans ,并向卡片添加了一个虚拟视图和一个 -ve 边距,以产生重叠行为效果,如
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbarCollapse"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin" />
<View
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#000" />
<include
layout="@layout/debit_card_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-90dp"
app:layout_collapseMode="parallax" />
</LinearLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
我也已将我的代码推送到 github。
android
android-recyclerview
android-coordinatorlayout
android-collapsingtoolbarlayout
android-nestedscrollview
我正在尝试实现这样的布局:
问题是当卡片向上滚动时触摸到工具栏,它不再像这样向上滚动:
我希望它向上滚动直到 viewpager 填满屏幕,即至少矩形卡应该向上滚动到工具栏之外(甚至 tabLayout 也可以向上滚动)。但我不希望它停留在顶部。
主要布局在这里:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:showIn="@layout/activity_main">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/background_dark"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbarCollapse"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="190dp"
android:minHeight="190dp"
android:src="@drawable/ic_launcher_foreground"
app:layout_collapseMode="parallax" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:behavior_overlapTop="90dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/lin"
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/debit_card_item" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_marginTop="40dp"
android:background="?attr/colorPrimary" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
分页器的片段在 NestedScrollView 中,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rcView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.core.widget.NestedScrollView>
我尝试过的事情:
- 我尝试删除线性布局上方的 NestedScrollView,并将
app:behavior_overlapTop="90dp" app:layout_behavior="@string/appbar_scrolling_view_behavior"
添加到线性布局。但它仍然给我相同的输出。 - 静态设置视图分页器的高度(给出相同的结果)。
-->>>编辑<<< 3. 我想到了一个解决方法,我正在尝试将自定义行为添加到我的 mainActivity 中的 LinearLayout。从而减小矩形卡的margin-bottom和height。当我猛击并关闭折叠的工具栏时,它会产生很好的效果。但是当我按住并滚动时,屏幕闪烁如下图:
我的自定义行为是
class CustomHeaderBehavior : AppBarLayout.ScrollingViewBehavior {
private var mContext: Context
var height = 0
var width = 0
var marginBottom = 0
var firstTime = true
constructor(
context: Context,
attrs: AttributeSet?
) : super(context, attrs) {
mContext = context
}
constructor(
context: Context?,
attrs: AttributeSet?,
mContext: Context
) : super(context, attrs) {
this.mContext = mContext
}
override fun layoutDependsOn(
parent: CoordinatorLayout,
child: View,
dependency: View
): Boolean {
return super.layoutDependsOn(parent, child, dependency)
}
override fun onDependentViewChanged(
parent: CoordinatorLayout,
childP: View,
dependency: View
): Boolean {
val child = childP.findViewById<RelativeLayout>(R.id.cardParent)
val maxScroll: Int = (dependency as AppBarLayout).totalScrollRange
val percentage =
abs(dependency.y) / maxScroll.toFloat()
Log.d("Behavx","D.y "+abs(dependency.y)+ " m s "+maxScroll+ " p "+percentage)
val lp: LinearLayout.LayoutParams =
child.layoutParams as LinearLayout.LayoutParams
if(firstTime){
height = child.height
width = child.width
marginBottom = lp.bottomMargin
firstTime = false
}
Log.d("Behaviour", "P "+ ((1-(percentage))*100).toString() +" H " +height+ " U H " +(height*(((1-(percentage))*100))/100) )
// lp.bottomMargin = ((marginBottom*(((1-(percentage))*100))/100) - ((height*((((percentage))*100))/100))).toInt()
lp.bottomMargin = ((marginBottom*(((1-(percentage))*100))/100)).toInt() //updating margin bottom
lp.height = ((height*(((1-(percentage))*100))/100)).toInt() //updating height
child.layoutParams = lp
child.alpha = 1 - (percentage * 4)
return super.onDependentViewChanged(parent, childP, dependency)
}
companion object {
fun getToolbarHeight(context: Context): Int {
var result = 0
val tv = TypedValue()
if (context.theme.resolveAttribute(R.attr.actionBarSize, tv, true)) {
result = TypedValue.complexToDimensionPixelSize(
tv.data,
context.resources.displayMetrics
)
}
return result
}
}
}
闪烁似乎正在发生,因为 dependency.y
随机变得错误,同时我按住并滚动并更新卡片的高度(如果我只更新边距,则不会发生闪烁)。由于某种原因,控制宽度正在顺利进行。但不幸的是,这对我没有帮助。
我也尝试通过向应用栏添加
offsetChangedListener
来做类似的事情,如下所示:appBar.addOnOffsetChangedListener(OnOffsetChangedListener { appBarLayout, verticalOffset -> 如果 (abs(verticalOffset) == appBarLayout.totalScrollRange) { // 折叠 cardParent.visibility = View.GONE } 别的 { //展开 cardParent.visibility = View.VISIBLE } })
但我仍然遇到闪烁
我在这里添加了示例项目:
github link
自定义行为被推送到新分支 custom_behaviour
为了实现该效果,卡片布局应位于折叠工具栏内。
尝试替换这个:
<ImageView
android:layout_width="match_parent"
android:layout_height="190dp"
android:minHeight="190dp"
android:src="@drawable/ic_launcher_foreground"
app:layout_collapseMode="parallax" />
与:
<include layout="@layout/debit_card_item"
android:layout_width="match_parent"
android:layout_height="190dp"
android:minHeight="190dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="72dp"
app:layout_collapseMode="parallax"/>
并删除 NestedScrollView 中的 <include layout="@layout/debit_card_item" />
。
希望对您有所帮助。
终于解决了我的问题。我将卡片添加到折叠布局中,如 Kalyans
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbarCollapse"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin" />
<View
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#000" />
<include
layout="@layout/debit_card_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-90dp"
app:layout_collapseMode="parallax" />
</LinearLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
我也已将我的代码推送到 github。