粘性线性布局
SpringNSView
class SpringNSView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) :
LinearLayout(context, attrs, defStyleAttr), NestedScrollingParent2 {
private var mScroller: Scroller = Scroller(context)
override fun onNestedScrollAccepted(child: View, target: View, axes: Int, type: Int) {
Log.e("SpringNSView", "onNestedScrollAccepted")
}
override fun onStopNestedScroll(target: View, type: Int) {
mScroller.startScroll(scrollX, scrollY, -scrollX, -scrollY, 500)
invalidate()
}
override fun onStartNestedScroll(child: View, target: View, axes: Int, type: Int): Boolean {
return true
}
override fun computeScroll() {
super.computeScroll()
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.currX, mScroller.currY)
invalidate()
}
}
override fun onNestedScroll(
target: View,
dxConsumed: Int,
dyConsumed: Int,
dxUnconsumed: Int,
dyUnconsumed: Int,
type: Int
) {
}
override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
if (type == 1) {
return
}
mScroller.forceFinished(true)
if (orientation == HORIZONTAL) {
preScrollHorizontally(target, dx, type, consumed)
} else {
preScrollVertically(target, dy, type, consumed)
}
}
private fun preScrollHorizontally(
target: View,
dx: Int,
type: Int,
consumed: IntArray
) {
val b = !target.canScrollHorizontally(-1)
val b2 = !target.canScrollHorizontally(1)
Log.e("SpringNSView", "onNestedPreScroll:$dx...$scrollX..$type..$b")
if ((b && dx < 0) || scrollX < 0) {
var i = if (dx < 0) {
scrollX + dx / (1 * abs(scrollX / 10) + 1)
} else {
scrollX + dx
}
if (i > 0) {
i = 0
} else if (i < -measuredWidth / 2)
i = -measuredWidth / 2
consumed[0] = dx
scrollTo(i, scrollY)
}
if ((b2 && dx > 0) || scrollX > 0) {
var i = if (dx > 0) {
scrollX + dx / (1 * abs(scrollX / 10) + 1)
} else {
scrollX + dx
}
if (i > measuredWidth / 2) {
i = measuredWidth / 2
} else if (i < 0)
i = 0
consumed[0] = dx
scrollTo(i, scrollY)
}
}
private fun preScrollVertically(
target: View,
dy: Int,
type: Int,
consumed: IntArray
) {
val b = !target.canScrollVertically(-1)
val b2 = !target.canScrollVertically(1)
Log.e("SpringNSView", "onNestedPreScroll:$dy...$scrollY..$type..$b")
if ((b && dy < 0) || scrollY < 0) {
var i = if (dy < 0) {
scrollY + dy / (1 * abs(scrollY / 10) + 1)
} else {
scrollY + dy
}
if (i > 0) {
i = 0
} else if (i < -measuredHeight / 2)
i = -measuredHeight / 2
consumed[1] = dy
scrollTo(scrollX, i)
}
if ((b2 && dy > 0) || scrollY > 0) {
var i = if (dy > 0) {
scrollY + dy / (1 * abs(scrollY / 10) + 1)
} else {
scrollY + dy
}
if (i > measuredHeight / 2) {
i = measuredHeight / 2
} else if (i < 0)
i = 0
consumed[1] = dy
scrollTo(scrollX, i)
}
}
override fun onNestedFling(
target: View,
velocityX: Float,
velocityY: Float,
consumed: Boolean
): Boolean {
return false
}
override fun onNestedPreFling(target: View, velocityX: Float, velocityY: Float): Boolean {
return false
}
}
xml 方向左右android:orientation="horizontal" 上下 vertical
<?xml version="1.0" encoding="utf-8"?>
<com.zmp.pagedemo.view.SpringNSView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.zmp.pagedemo.view.SpringNSView>