From 41f9e64741e1794c11e585e096802a43e6ba2521 Mon Sep 17 00:00:00 2001 From: ooftf Date: Mon, 17 Jun 2019 15:26:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=A8=AA=E7=AB=96=E5=B1=8F?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E5=B4=A9=E6=BA=83=E9=97=AE=E9=A2=98=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=94=AF=E6=8C=81Nested=E8=81=94=E5=8A=A8?= =?UTF-8?q?=E7=9A=84NestVerticalPagerLayout=EF=BC=8C=E4=B8=8D=E7=94=A8?= =?UTF-8?q?=E7=BC=96=E5=86=99=E8=BE=B9=E7=95=8C=E5=88=86=E6=9E=90=E5=99=A8?= =?UTF-8?q?=20=E8=81=94=E5=8A=A8=E6=95=88=E6=9E=9C=E7=95=A5=E6=9C=89?= =?UTF-8?q?=E4=B8=8D=E5=90=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/layout/activity_main.xml | 2 +- .../com/ooftf/vertical/VerticalPagerLayout.kt | 37 +++-- ...erLayout.kt => NestVerticalPagerLayout.kt} | 142 +++++++++++++----- .../NestedScrollingParentHelperPro.java | 78 ++++++++++ 4 files changed, 201 insertions(+), 58 deletions(-) rename lib/src/main/java/com/ooftf/vertical/nested/{VerticalPagerLayout.kt => NestVerticalPagerLayout.kt} (59%) create mode 100644 lib/src/main/java/com/ooftf/vertical/nested/NestedScrollingParentHelperPro.java diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 0d4e565..a67f7e0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,7 +5,7 @@ android:layout_height="match_parent" tools:context="com.ooftf.verticalpager.MainActivity"> - getCurrentPage() + offscreenPageLimit } - .forEach { - removeForItemInfo(it) - } - (getCurrentPage() - offscreenPageLimit..getCurrentPage() + offscreenPageLimit).forEach { - addNewView(it) + adapter?.let { + it.startUpdate(this) + items + .filter { it.position < getCurrentPage() - offscreenPageLimit || it.position > getCurrentPage() + offscreenPageLimit } + .forEach { + removeForItemInfo(it) + } + var start = Math.max(0, getCurrentPage() - offscreenPageLimit) + var end = Math.min(it.count - 1, getCurrentPage() + offscreenPageLimit) + (start..end).forEach { + addNewView(it) + } + it.setPrimaryItem(this, getCurrentPage(), itemInfoForPosition(getCurrentPage()).obj) + it.finishUpdate(this) } - adapter?.setPrimaryItem(this, getCurrentPage(), itemInfoForPosition(getCurrentPage()).obj) - adapter?.finishUpdate(this) - } /** @@ -279,17 +281,20 @@ class VerticalPagerLayout : FrameLayout { val height = b - t (0 until childCount).forEach { var itemInfo = itemInfoForView(getChildAt(it)) - getChildAt(it).layout(0, itemInfo.position * height, r - l, (itemInfo.position + 1) * height) + itemInfo?.let { itemInfo -> + getChildAt(it).layout(0, itemInfo.position * height, r - l, (itemInfo.position + 1) * height) + } + } } - private fun itemInfoForView(child: View): ItemInfo { + private fun itemInfoForView(child: View): ItemInfo? { items.forEach { if (adapter!!.isViewFromObject(child, it.obj)) { return it } } - throw NullPointerException() + return null } override fun computeScroll() { diff --git a/lib/src/main/java/com/ooftf/vertical/nested/VerticalPagerLayout.kt b/lib/src/main/java/com/ooftf/vertical/nested/NestVerticalPagerLayout.kt similarity index 59% rename from lib/src/main/java/com/ooftf/vertical/nested/VerticalPagerLayout.kt rename to lib/src/main/java/com/ooftf/vertical/nested/NestVerticalPagerLayout.kt index fcaf360..ee7ac37 100644 --- a/lib/src/main/java/com/ooftf/vertical/nested/VerticalPagerLayout.kt +++ b/lib/src/main/java/com/ooftf/vertical/nested/NestVerticalPagerLayout.kt @@ -4,7 +4,6 @@ import android.content.Context import android.os.Build import android.support.annotation.RequiresApi import android.support.v4.view.NestedScrollingParent2 -import android.support.v4.view.NestedScrollingParentHelper import android.support.v4.view.PagerAdapter import android.util.AttributeSet import android.util.Log @@ -18,27 +17,56 @@ import android.widget.Scroller * 高仿淘宝商品页上下分页布局 * Created by master on 2016/3/28. */ -class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 { - var helper = NestedScrollingParentHelper(this) +class NestVerticalPagerLayout : FrameLayout, NestedScrollingParent2 { + var helper = NestedScrollingParentHelperPro(this) override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray?, type: Int) { - moved = true - Log.e("onNestedPreScroll", "dy::" + dy) - if (scrollY % height != 0) { - scrollBy(0, dy) - consumed?.set(1, dy) + helper.onNestedPreScroll(target, dx, dy, consumed, type) + if (isIntecepted && type == 0) { + var consumedY: Int + val expect = scrollY + dy + when { + expect <= 0 -> { + consumedY = 0 - scrollY; + scrollBy(0, consumedY) + } + expect >= height * (adapter!!.count - 1) -> { + consumedY = height * (adapter!!.count - 1) - scrollY + scrollBy(0, consumedY) + } + else -> { + consumedY = dy + scrollBy(0, consumedY) + } + } + consumed?.set(1, consumedY) } + Log.e("onNestedPreScroll", "dy:$dy,type::$type") } override fun onStopNestedScroll(target: View, type: Int) { helper.onStopNestedScroll(target, type) - Log.e("onStopNestedScroll", "onStopNestedScroll") - judgePage(true) + Log.e("onStopNestedScroll", "type:$type,speedY::${helper.speedY}") + if (isIntecepted && type == 0) { + if (helper.speedY > 3) { + setCurrentItem(getCurrentPage() + 1) + } else if (helper.speedY < -3) { + setCurrentItem(getCurrentPage() - 1) + } else { + setCurrentItem(getCurrentPage()) + } + isIntecepted = false + } } override fun onStartNestedScroll(child: View, target: View, axes: Int, type: Int): Boolean { - mScroller.forceFinished(true) - Log.e("onStartNestedScroll", "onStartNestedScroll") - moved = false + Log.e("onStartNestedScroll", "type::$type") + if (type == 0) { + mScroller.forceFinished(true) + if (scrollY % height != 0) { + isIntecepted = true + } + } + return true } @@ -47,17 +75,36 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 { helper.onNestedScrollAccepted(child, target, axes, type) } - var moved = false + var isIntecepted = false override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, type: Int) { - Log.e("onNestedScroll", "dyConsumed::" + dyConsumed + ",dyUnconsumed::" + dyUnconsumed) - scrollBy(0, dyUnconsumed) + helper.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type) + Log.e("onNestedScroll", "dyConsumed::$dyConsumed,dyUnconsumed::$dyUnconsumed") + if (type == 0 && dyUnconsumed != 0) { + var consumedY: Int + val expect = scrollY + dyUnconsumed + when { + expect <= 0 -> { + consumedY = 0 - scrollY; + scrollBy(0, consumedY) + } + expect >= height * (adapter!!.count - 1) -> { + consumedY = height * (adapter!!.count - 1) - scrollY + scrollBy(0, consumedY) + } + else -> { + consumedY = dyUnconsumed + scrollBy(0, consumedY) + } + } + isIntecepted = true + } } /** * 松开时布局滑动动画时间 */ - private var SCROLL_DURATION = 700 + private var SCROLL_DURATION = 600 var offscreenPageLimit = 1; private var mScroller: Scroller @@ -68,9 +115,10 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 { resetLayout() } - override fun onInterceptHoverEvent(event: MotionEvent?): Boolean { - Log.e("onInterceptHoverEvent", "...") - return super.onInterceptHoverEvent(event) + + override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { + Log.e("onInterceptTouchEvent", "...") + return super.onInterceptTouchEvent(ev) } /** @@ -104,23 +152,29 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 { override fun scrollTo(x: Int, y: Int) { refreshViews() + Log.e("scrollTo", "x:$x,y:$y") super.scrollTo(x, y) } private fun refreshViews() { //移除不必要View adapter ?: return - adapter?.startUpdate(this) - items - .filter { it.position < getCurrentPage() - offscreenPageLimit || it.position > getCurrentPage() + offscreenPageLimit } - .forEach { - removeForItemInfo(it) - } - (getCurrentPage() - offscreenPageLimit..getCurrentPage() + offscreenPageLimit).forEach { - addNewView(it) + adapter?.let { + it.startUpdate(this) + items + .filter { it.position < getCurrentPage() - offscreenPageLimit || it.position > getCurrentPage() + offscreenPageLimit } + .forEach { + removeForItemInfo(it) + } + var start = Math.max(0, getCurrentPage() - offscreenPageLimit) + var end = Math.min(it.count - 1, getCurrentPage() + offscreenPageLimit) + (start..end).forEach { + addNewView(it) + } + it.setPrimaryItem(this, getCurrentPage(), itemInfoForPosition(getCurrentPage()).obj) + it.finishUpdate(this) } - adapter?.setPrimaryItem(this, getCurrentPage(), itemInfoForPosition(getCurrentPage()).obj) - adapter?.finishUpdate(this) + } @@ -161,6 +215,7 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 { return viewForItemInfo(item) } + private fun viewForItemInfo(itemInfo: ItemInfo): View { (0 until childCount).forEach { if (adapter!!.isViewFromObject(getChildAt(it), itemInfo.obj)) { @@ -180,13 +235,6 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 { } - /** - * 判断应该停留在哪一页 - */ - private fun judgePage(smooth: Boolean) { - setCurrentItem(getCurrentPage(), smooth) - } - /** * 滚动到指定页面 */ @@ -220,24 +268,36 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 { */ private fun getCurrentPage(): Int { if (height == 0) return 0 - return Math.round(scrollY.toFloat() / height) + val round = Math.round(scrollY.toFloat() / height) + if (round < 0) { + return 0 + } + adapter?.let { + if (round > it.count - 1) { + return it.count - 1 + } + } + return round } override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { val height = b - t (0 until childCount).forEach { var itemInfo = itemInfoForView(getChildAt(it)) - getChildAt(it).layout(0, itemInfo.position * height, r - l, (itemInfo.position + 1) * height) + itemInfo?.let { itemInfo -> + getChildAt(it).layout(0, itemInfo.position * height, r - l, (itemInfo.position + 1) * height) + } + } } - private fun itemInfoForView(child: View): ItemInfo { + private fun itemInfoForView(child: View): ItemInfo? { items.forEach { if (adapter!!.isViewFromObject(child, it.obj)) { return it } } - throw NullPointerException() + return null } override fun computeScroll() { diff --git a/lib/src/main/java/com/ooftf/vertical/nested/NestedScrollingParentHelperPro.java b/lib/src/main/java/com/ooftf/vertical/nested/NestedScrollingParentHelperPro.java new file mode 100644 index 0000000..8e56fdb --- /dev/null +++ b/lib/src/main/java/com/ooftf/vertical/nested/NestedScrollingParentHelperPro.java @@ -0,0 +1,78 @@ +package com.ooftf.vertical.nested; + +import android.support.annotation.NonNull; +import android.support.v4.view.NestedScrollingParentHelper; +import android.support.v4.view.ViewCompat; +import android.view.View; +import android.view.ViewGroup; + +/** + * @author ooftf + * @email 994749769@qq.com + * @date 2019/6/17 0017 + */ +public class NestedScrollingParentHelperPro extends NestedScrollingParentHelper { + /** + * Construct a new helper for a given ViewGroup + * + * @param viewGroup + */ + public NestedScrollingParentHelperPro(@NonNull ViewGroup viewGroup) { + super(viewGroup); + } + + @Override + public void onNestedScrollAccepted(@NonNull View child, @NonNull View target, int axes) { + super.onNestedScrollAccepted(child, target, axes); + speedY = 0; + lastTime = 0; + } + + @Override + public void onNestedScrollAccepted(@NonNull View child, @NonNull View target, int axes, int type) { + super.onNestedScrollAccepted(child, target, axes, type); + if(type == 0){ + speedY = 0; + lastTime = 0; + } + } + + @Override + public int getNestedScrollAxes() { + return super.getNestedScrollAxes(); + } + + @Override + public void onStopNestedScroll(@NonNull View target) { + super.onStopNestedScroll(target); + } + + @Override + public void onStopNestedScroll(@NonNull View target, int type) { + super.onStopNestedScroll(target, type); + } + + double speedY; + long lastTime; + + public void onNestedScroll(@NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) { + super.onStopNestedScroll(target, type); + + } + + + public void onNestedPreScroll(@NonNull View target, int dx, int dy, int[] consumed, int type) { + if(type ==0){ + long temp = System.currentTimeMillis(); + if (lastTime != 0) { + speedY = (double) dy / (temp - lastTime); + } + lastTime = temp; + } + + } + + public double getSpeedY() { + return speedY; + } +}