Open Er3c opened 1 year ago
使用Motionlayout嵌套SmartRefreshLayout,实现头部收缩效果,布局如下
<androidx.constraintlayout.motion.widget.MotionLayout> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/ctlHeader" android:layout_width="0dp" android:layout_height="150dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"> </androidx.constraintlayout.widget.ConstraintLayout> <Indicator android:id="@+id/indicator" android:layout_width="0dp" android:layout_height="42dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/ctlHeader" /> <SmartRefreshLayout android:id="@+id/refreshLayout" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/indicator" app:srlEnableAutoLoadMore="true" app:srlEnableFooterFollowWhenNoMoreData="true" app:srlEnableLoadMoreWhenContentNotFull="false"> <Header /> <RecyclerView /> <Footer /> </com.yuebuy.common.view.YbRefreshLayout> </androidx.constraintlayout.motion.widget.MotionLayout>
motionScene配置的是向上滑动时收缩header,结果触发loadmore时footer会覆盖卡片,而不是在卡片下方显示。noMoreData状态显示没有问题。 是我使用问题还是bug,期待有人解答
请问这个问题你解决了吗?我还遇到了另一个问题,就是将嵌套了SmartRefreshLayout的RecyclerView往上滑动时,头部的head就会显示出来,而不是等RecyclerView滑动到了顶部在滑动才显示头部head
使用Motionlayout嵌套SmartRefreshLayout,实现头部收缩效果,布局如下
<androidx.constraintlayout.motion.widget.MotionLayout> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/ctlHeader" android:layout_width="0dp" android:layout_height="150dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"> </androidx.constraintlayout.widget.ConstraintLayout> <Indicator android:id="@+id/indicator" android:layout_width="0dp" android:layout_height="42dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/ctlHeader" /> <SmartRefreshLayout android:id="@+id/refreshLayout" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/indicator" app:srlEnableAutoLoadMore="true" app:srlEnableFooterFollowWhenNoMoreData="true" app:srlEnableLoadMoreWhenContentNotFull="false"> <Header /> <RecyclerView /> <Footer /> </com.yuebuy.common.view.YbRefreshLayout> </androidx.constraintlayout.motion.widget.MotionLayout>
motionScene配置的是向上滑动时收缩header,结果触发loadmore时footer会覆盖卡片,而不是在卡片下方显示。noMoreData状态显示没有问题。 是我使用问题还是bug,期待有人解答
请问这个问题你解决了吗?我还遇到了另一个问题,就是将嵌套了SmartRefreshLayout的RecyclerView往上滑动时,头部的head就会显示出来,而不是等RecyclerView滑动到了顶部在滑动才显示头部head
这个问题我昨天遇到了,没找到资料,自己看源码解决了,需要代码吗?
在MotionLayout中的onNestedPreScroll方法里,通过target去判断有没有到达顶部,而这里的target是SmartRefreshLayout。 我们可以通过重写SmartRefreshLayout的onNestedPreScroll方法,判断如果父滚动view是MotionLayout的话,把传过去的this改成子view(在这里是RecyclerView)就可以了。 MotionLayout拿到的target是RecyclerView就可以正确判断是否在顶部
使用Motionlayout嵌套SmartRefreshLayout,实现头部收缩效果,布局如下
<androidx.constraintlayout.motion.widget.MotionLayout> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/ctlHeader" android:layout_width="0dp" android:layout_height="150dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"> </androidx.constraintlayout.widget.ConstraintLayout> <Indicator android:id="@+id/indicator" android:layout_width="0dp" android:layout_height="42dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/ctlHeader" /> <SmartRefreshLayout android:id="@+id/refreshLayout" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/indicator" app:srlEnableAutoLoadMore="true" app:srlEnableFooterFollowWhenNoMoreData="true" app:srlEnableLoadMoreWhenContentNotFull="false"> <Header /> <RecyclerView /> <Footer /> </com.yuebuy.common.view.YbRefreshLayout> </androidx.constraintlayout.motion.widget.MotionLayout>
motionScene配置的是向上滑动时收缩header,结果触发loadmore时footer会覆盖卡片,而不是在卡片下方显示。noMoreData状态显示没有问题。 是我使用问题还是bug,期待有人解答
请问这个问题你解决了吗?我还遇到了另一个问题,就是将嵌套了SmartRefreshLayout的RecyclerView往上滑动时,头部的head就会显示出来,而不是等RecyclerView滑动到了顶部在滑动才显示头部head
这个问题我昨天遇到了,没找到资料,自己看源码解决了,需要代码吗?
在MotionLayout中的onNestedPreScroll方法里,通过target去判断有没有到达顶部,而这里的target是SmartRefreshLayout。 我们可以通过重写SmartRefreshLayout的onNestedPreScroll方法,判断如果父滚动view是MotionLayout的话,把传过去的this改成子view(在这里是RecyclerView)就可以了。 MotionLayout拿到的target是RecyclerView就可以正确判断是否在顶部
优秀优秀,我下午按照你的方式试一下,谢谢啦
使用Motionlayout嵌套SmartRefreshLayout,实现头部收缩效果,布局如下
<androidx.constraintlayout.motion.widget.MotionLayout> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/ctlHeader" android:layout_width="0dp" android:layout_height="150dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"> </androidx.constraintlayout.widget.ConstraintLayout> <Indicator android:id="@+id/indicator" android:layout_width="0dp" android:layout_height="42dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/ctlHeader" /> <SmartRefreshLayout android:id="@+id/refreshLayout" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/indicator" app:srlEnableAutoLoadMore="true" app:srlEnableFooterFollowWhenNoMoreData="true" app:srlEnableLoadMoreWhenContentNotFull="false"> <Header /> <RecyclerView /> <Footer /> </com.yuebuy.common.view.YbRefreshLayout> </androidx.constraintlayout.motion.widget.MotionLayout>
motionScene配置的是向上滑动时收缩header,结果触发loadmore时footer会覆盖卡片,而不是在卡片下方显示。noMoreData状态显示没有问题。 是我使用问题还是bug,期待有人解答
请问这个问题你解决了吗?我还遇到了另一个问题,就是将嵌套了SmartRefreshLayout的RecyclerView往上滑动时,头部的head就会显示出来,而不是等RecyclerView滑动到了顶部在滑动才显示头部head
这个问题我昨天遇到了,没找到资料,自己看源码解决了,需要代码吗?
在MotionLayout中的onNestedPreScroll方法里,通过target去判断有没有到达顶部,而这里的target是SmartRefreshLayout。 我们可以通过重写SmartRefreshLayout的onNestedPreScroll方法,判断如果父滚动view是MotionLayout的话,把传过去的this改成子view(在这里是RecyclerView)就可以了。 MotionLayout拿到的target是RecyclerView就可以正确判断是否在顶部
太帅了,你可以把代码贴出来吗?我刚才看了下你提到的onNestedPreScroll 并不能return view啊
使用Motionlayout嵌套SmartRefreshLayout,实现头部收缩效果,布局如下
<androidx.constraintlayout.motion.widget.MotionLayout> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/ctlHeader" android:layout_width="0dp" android:layout_height="150dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"> </androidx.constraintlayout.widget.ConstraintLayout> <Indicator android:id="@+id/indicator" android:layout_width="0dp" android:layout_height="42dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/ctlHeader" /> <SmartRefreshLayout android:id="@+id/refreshLayout" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/indicator" app:srlEnableAutoLoadMore="true" app:srlEnableFooterFollowWhenNoMoreData="true" app:srlEnableLoadMoreWhenContentNotFull="false"> <Header /> <RecyclerView /> <Footer /> </com.yuebuy.common.view.YbRefreshLayout> </androidx.constraintlayout.motion.widget.MotionLayout>
motionScene配置的是向上滑动时收缩header,结果触发loadmore时footer会覆盖卡片,而不是在卡片下方显示。noMoreData状态显示没有问题。 是我使用问题还是bug,期待有人解答
请问这个问题你解决了吗?我还遇到了另一个问题,就是将嵌套了SmartRefreshLayout的RecyclerView往上滑动时,头部的head就会显示出来,而不是等RecyclerView滑动到了顶部在滑动才显示头部head
这个问题我昨天遇到了,没找到资料,自己看源码解决了,需要代码吗? 在MotionLayout中的onNestedPreScroll方法里,通过target去判断有没有到达顶部,而这里的target是SmartRefreshLayout。 我们可以通过重写SmartRefreshLayout的onNestedPreScroll方法,判断如果父滚动view是MotionLayout的话,把传过去的this改成子view(在这里是RecyclerView)就可以了。 MotionLayout拿到的target是RecyclerView就可以正确判断是否在顶部
太帅了,你可以把代码贴出来吗?我刚才看了下你提到的onNestedPreScroll 并不能return view啊
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewParent
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.core.view.ViewCompat
import androidx.core.view.ViewParentCompat
import com.scwang.smart.refresh.layout.SmartRefreshLayout
class NestedSmartRefreshLayout(context: Context, attrs: AttributeSet?) :
SmartRefreshLayout(context, attrs) {
// 本类保存父滚动view
private var mNestedScrollingParentTouch: ViewParent? = null
// /**
// * 获取嵌套滚动父布局方法
// */
// private val mNestedChildInGetNestedScrollingParentForTypeMethod by lazy {
// mNestedChild.javaClass // 获取指定的私有方法对象
// .getDeclaredMethod("getNestedScrollingParentForType", Int::class.java)
// .apply {
// isAccessible = true // 开启私有调用
// }
// }
/**
* 调用父类初始化方法,随后获取嵌套滚动父布局
*/
override fun onNestedScrollAccepted(child: View, target: View, axes: Int) {
// 调用方法,本类保存 mNestedChild 里的滚动父布局
mNestedScrollingParentTouch =
getNestedScrollingParent(axes and ViewCompat.SCROLL_AXIS_VERTICAL)
// 调用父类初始化方法
super.onNestedScrollAccepted(child, target, axes)
// 暂时注释掉反射获取,采用循环向上遍历
// 反射可能会卡,因为在上面一行已经调用父类的开始嵌套滚动方法了,这里才开始初始化
// // 调用方法,本类保存 mNestedChild 里的滚动父布局
// val result: Any? = mNestedChildInGetNestedScrollingParentForTypeMethod
// .invoke(mNestedChild, ViewCompat.TYPE_TOUCH)
// if (result == null) mNestedScrollingParentTouch = null
// if (result is ViewParent) mNestedScrollingParentTouch = result
}
/**
* 获取父滚动布局
*/
private fun getNestedScrollingParent(
axes: Int, type: Int = ViewCompat.TYPE_TOUCH
): ViewParent? {
if (mNestedChild.isNestedScrollingEnabled) {
var p: ViewParent? = parent
var child: View? = this
while (p != null) {
if (ViewParentCompat.onStartNestedScroll(p, child!!, this, axes, type)) {
return p
}
if (p is View) {
child = p
}
p = p.parent
}
}
return null
}
/**
* 滚动的时候,如果父view是 MotionLayout 则自己处理
* 把传递给 MotionLayout 的 target 改成真实 target ,用于判断滚动是否到顶部
*/
override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray) {
if (mNestedScrollingParentTouch !is MotionLayout) {
super.onNestedPreScroll(target, dx, dy, consumed)
return
}
val parent: MotionLayout = (mNestedScrollingParentTouch ?: return) as MotionLayout
// If we are in the middle of consuming, a scroll, then we want to move the spinner back up
// before allowing the list to scroll
var consumedY = 0
// dy * mTotalUnconsumed > 0 表示 mSpinner 已经拉出来,现在正要往回推
// mTotalUnconsumed 将要减去 dy 的距离 再计算新的 mSpinner
if (dy * mTotalUnconsumed > 0) {
if (Math.abs(dy) > Math.abs(mTotalUnconsumed)) {
consumedY = mTotalUnconsumed
mTotalUnconsumed = 0
} else {
consumedY = dy
mTotalUnconsumed -= dy
}
moveSpinnerInfinitely(mTotalUnconsumed.toFloat())
} else if (dy > 0 && mFooterLocked) {
consumedY = dy
mTotalUnconsumed -= dy
moveSpinnerInfinitely(mTotalUnconsumed.toFloat())
}
// Now let our nested parent consume the leftovers
dispatchNestedPreScroll(parent, target, dx, dy - consumedY, consumed, null)
consumed[1] += consumedY
}
/**
* 拷贝 NestedScrollingChildHelper 里的 dispatchNestedPreScroll 方法
* 替换掉 ViewParentCompat.onNestedPreScroll 中的第二个参数 “this” 为 "子target"
*/
private fun dispatchNestedPreScroll(
parent: ViewParent, target: View, dx: Int, dy: Int, consumed: IntArray,
offsetInWindow: IntArray?, @ViewCompat.NestedScrollType type: Int = ViewCompat.TYPE_TOUCH
): Boolean {
if (mNestedChild.isNestedScrollingEnabled) {
if (dx != 0 || dy != 0) {
var startX = 0
var startY = 0
if (offsetInWindow != null) {
this.getLocationInWindow(offsetInWindow)
startX = offsetInWindow[0]
startY = offsetInWindow[1]
}
consumed[0] = 0
consumed[1] = 0
ViewParentCompat.onNestedPreScroll(parent, target, dx, dy, consumed, type)
if (offsetInWindow != null) {
this.getLocationInWindow(offsetInWindow)
offsetInWindow[0] -= startX
offsetInWindow[1] -= startY
}
return consumed[0] != 0 || consumed[1] != 0
} else if (offsetInWindow != null) {
offsetInWindow[0] = 0
offsetInWindow[1] = 0
}
}
return false
}
}
这个代码只是解决了头部判断是否到顶的问题,footer问题没见过,也没去解决
你可以用我的代码试试看,如果不能解决问题,可以加我q:508342550,我下午有空
使用Motionlayout嵌套SmartRefreshLayout,实现头部收缩效果,布局如下
motionScene配置的是向上滑动时收缩header,结果触发loadmore时footer会覆盖卡片,而不是在卡片下方显示。noMoreData状态显示没有问题。 是我使用问题还是bug,期待有人解答