diff --git a/.project b/.project new file mode 100644 index 0000000..2129f28 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + NestedTouchScrollingLayout + Project NestedTouchScrollingLayout created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..e889521 --- /dev/null +++ b/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/README.md b/README.md index c550c4d..fac389e 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ mNestedTouchScrollingLayout.registerNestScrollChildCallback(new NestedTouchScrol ### Next - [x] hold all touch event, and dispath touch event to child view. - [x] fix ACTION_UP dispatch child click event. -- [ ] support bottomsheet. +- [x] support bottomsheet. - [ ] support CoordinatorLayout (AppbarLayout). - [ ] add damping draging. diff --git a/app/.classpath b/app/.classpath new file mode 100644 index 0000000..eb19361 --- /dev/null +++ b/app/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/.project b/app/.project new file mode 100644 index 0000000..ac485d7 --- /dev/null +++ b/app/.project @@ -0,0 +1,23 @@ + + + app + Project app created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/app/.settings/org.eclipse.buildship.core.prefs b/app/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..b1886ad --- /dev/null +++ b/app/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/app/build.gradle b/app/build.gradle index 8c5fe20..18cf8f4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,7 +28,7 @@ dependencies { implementation 'com.android.support:recyclerview-v7:28.0.0' -// api project(':library') + api project(':library') // implementation 'com.github.JarvisGG:NestedTouchScrollingLayout:v1.0.2' - implementation 'com.jarvis.library.NestedTouchScrollingLayout:library:1.0.2' +// implementation 'com.jarvis.library.NestedTouchScrollingLayout:library:1.0.2' } diff --git a/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/RecyclerViewActivity.java b/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/RecyclerViewActivity.java index 969d50b..ff0d771 100644 --- a/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/RecyclerViewActivity.java +++ b/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/RecyclerViewActivity.java @@ -77,6 +77,11 @@ public void run() { }); } + @Override + public void onFingerUp(float velocityY) { + + } + @Override public void onNestChildHorizationScroll(boolean show) { diff --git a/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/WebViewActivity.java b/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/WebViewActivity.java index 8d577d3..0ebfe1e 100644 --- a/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/WebViewActivity.java +++ b/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/WebViewActivity.java @@ -48,6 +48,11 @@ public void onNestChildScrollRelease(float deltaY, int velocityY) { mContainer.recover(0); } + @Override + public void onFingerUp(float velocityY) { + + } + @Override public void onNestChildHorizationScroll(boolean show) { diff --git a/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/BaseChildFragment.java b/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/BaseChildFragment.java index 25310f6..775a40c 100644 --- a/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/BaseChildFragment.java +++ b/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/BaseChildFragment.java @@ -45,6 +45,11 @@ public void onNestChildScrollRelease(float deltaY, int velocityY) { mPager.setCurrentItem(targetPos); } + @Override + public void onFingerUp(float velocityY) { + + } + @Override public void onNestChildHorizationScroll(boolean show) { diff --git a/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/RecyclerViewFragment.java b/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/RecyclerViewFragment.java index 761e180..477c927 100644 --- a/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/RecyclerViewFragment.java +++ b/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/RecyclerViewFragment.java @@ -66,6 +66,11 @@ public void onNestChildScrollRelease(float deltaY, int velocityY) { mNestedTouchScrollingLayout.recover(0, null, 300); } + @Override + public void onFingerUp(float velocityY) { + + } + @Override public void onNestChildHorizationScroll(boolean show) { diff --git a/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/WebViewFragment.java b/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/WebViewFragment.java index 83c428c..52602be 100644 --- a/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/WebViewFragment.java +++ b/app/src/main/java/jarvis/com/nestedtouchscrollinglayout/fragment/WebViewFragment.java @@ -64,6 +64,11 @@ public void onNestChildScrollRelease(float deltaY, int velocityY) { mNestedTouchScrollingLayout.recover(0); } + @Override + public void onFingerUp(float velocityY) { + + } + @Override public void onNestChildHorizationScroll(boolean show) { diff --git a/library/.classpath b/library/.classpath new file mode 100644 index 0000000..eb19361 --- /dev/null +++ b/library/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/library/.project b/library/.project new file mode 100644 index 0000000..08c81e7 --- /dev/null +++ b/library/.project @@ -0,0 +1,23 @@ + + + library + Project library created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/library/.settings/org.eclipse.buildship.core.prefs b/library/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..b1886ad --- /dev/null +++ b/library/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/library/build.gradle b/library/build.gradle index 783f5f7..308a19a 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -43,7 +43,7 @@ def gitUrl = 'https://github.com/JarvisGG/NestedTouchScrollingLayout.git' def libName = "NestedTouchScrollingLayout" group = "com.jarvis.library.NestedTouchScrollingLayout" -version = "1.0.2" +version = "1.1.0" task sourcesJar(type: Jar) { diff --git a/library/src/main/java/jarvis/com/library/NestedTouchScrollingLayout.java b/library/src/main/java/jarvis/com/library/NestedTouchScrollingLayout.java index 028f5fd..15838c8 100644 --- a/library/src/main/java/jarvis/com/library/NestedTouchScrollingLayout.java +++ b/library/src/main/java/jarvis/com/library/NestedTouchScrollingLayout.java @@ -5,10 +5,12 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; +import android.support.annotation.IntDef; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.view.NestedScrollingParent; import android.support.v4.view.animation.PathInterpolatorCompat; +import android.support.v4.widget.NestedScrollView; import android.util.AttributeSet; import android.util.Property; import android.view.MotionEvent; @@ -20,6 +22,8 @@ import android.webkit.WebView; import android.widget.FrameLayout; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; @@ -32,6 +36,19 @@ public class NestedTouchScrollingLayout extends FrameLayout implements NestedScr private static final String TAG = "NestedTouchScrolling"; + @IntDef({ + SheetDirection.ALL, + SheetDirection.TOP, + SheetDirection.BOTTOM + }) + + @Retention(RetentionPolicy.SOURCE) + public @interface SheetDirection { + int ALL = 0x000; + int TOP = 0x001; + int BOTTOM = 0x002; + } + private View mChildView; private ObjectAnimator mTransYAnim; @@ -51,6 +68,16 @@ public class NestedTouchScrollingLayout extends FrameLayout implements NestedScr private float mOriginTranslate = 0; + /** + * 假如 cover BottomSheet 场景,sheetView ** 会 ** 从哪个方向弹出 + */ + private @SheetDirection int mSheetDirection = SheetDirection.ALL; + + /** + ************* 键盘收起,导致 reLayout,getHeight 发生改变,所以一开始就锁定高度 + */ + private int mTouchParentViewOriginMeasureHeight = 0; + /** * 针对包含的子 View 为 webview 的情况 */ @@ -75,13 +102,15 @@ public class NestedTouchScrollingLayout extends FrameLayout implements NestedScr private boolean isFingerHolderTouch = false; + private boolean isParentDispatchTouchEvent = true; + private List mNestChildScrollChangeCallbacks; private final Property SHEET_TRANSLATION = new Property(Float.class, "sheetTranslation") { @Override public Float get(NestedTouchScrollingLayout object) { - return getHeight() - object.mSheetTranslation; + return mTouchParentViewOriginMeasureHeight - object.mSheetTranslation; } @Override @@ -103,6 +132,8 @@ public interface INestChildScrollChange { void onNestChildScrollRelease(float deltaY, int velocityY); + void onFingerUp(float velocityY); + void onNestChildHorizationScroll(boolean show); } @@ -130,6 +161,13 @@ public NestedTouchScrollingLayout(@NonNull Context context, @Nullable AttributeS private void init() { mNestChildScrollChangeCallbacks = new ArrayList<>(); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); + + post(new Runnable() { + @Override + public void run() { + mTouchParentViewOriginMeasureHeight = NestedTouchScrollingLayout.this.getMeasuredHeight(); + } + }); } @Override @@ -179,12 +217,16 @@ public boolean dispatchTouchEvent(MotionEvent ev) { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - return true; + if (isParentDispatchTouchEvent) { + return true; + } else { + return super.onInterceptTouchEvent(ev); + } } @Override public boolean onTouchEvent(MotionEvent event) { - if (getChildAt(0) == null) { + if (getChildAt(0) == null || !isParentDispatchTouchEvent) { return super.onTouchEvent(event); } if (isAnimating()) { @@ -194,6 +236,7 @@ public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { mOriginTranslate = mChildView.getTranslationY(); + mTouchParentViewOriginMeasureHeight = this.getMeasuredHeight(); mParentOwnsTouch = false; mDownY = event.getY(); @@ -245,7 +288,7 @@ public boolean onTouchEvent(MotionEvent event) { if (mParentOwnsTouch) { - if (isHoldTouch && (!isChildCanScroll(event, deltaY))) { + if (isHoldTouch && !isChildCanScroll(event, deltaY) && deltaY != 0) { mDownY = event.getY(); velocityTracker.clear(); isHoldTouch = false; @@ -257,10 +300,10 @@ public boolean onTouchEvent(MotionEvent event) { cancelEvent.recycle(); } - if (!isHoldTouch && isChildCanScroll(event, deltaY)) { + if (!isHoldTouch && isChildCanScroll(event, deltaY) && deltaY != 0) { setSheetTranslation(maxSheetTranslation); isHoldTouch = true; - if (!(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL)) { + if (event.getAction() == MotionEvent.ACTION_MOVE) { MotionEvent downEvent = MotionEvent.obtain(event); downEvent.setAction(MotionEvent.ACTION_DOWN); getChildAt(0).dispatchTouchEvent(downEvent); @@ -292,13 +335,21 @@ public boolean onTouchEvent(MotionEvent event) { private boolean isChildCanScroll(MotionEvent event, float deltaY) { boolean fingerDown = deltaY - mOriginTranslate < 0; - boolean canScrollDown = canScrollDown(getChildAt(0), event.getX(), event.getY() + (mSheetTranslation - getHeight())); + boolean canScrollDown = canScrollDown(getChildAt(0), event.getX(), event.getY() + (mSheetTranslation - getHeight()), false); boolean fingerUp = deltaY - mOriginTranslate > 0; - boolean canScrollUp = canScrollUp(getChildAt(0), event.getX(), event.getY() + (mSheetTranslation - getHeight())); + boolean canScrollUp = canScrollUp(getChildAt(0), event.getX(), event.getY() + (mSheetTranslation - getHeight()), false); return (fingerDown && canScrollUp) || (fingerUp && canScrollDown); } - protected boolean canScrollUp(View view, float x, float y) { + /** + * child can scroll + * @param view + * @param x + * @param y + * @param lockRect + * @return + */ + protected boolean canScrollUp(View view, float x, float y, boolean lockRect) { if (view instanceof WebView) { return canWebViewScrollUp(); @@ -312,7 +363,8 @@ protected boolean canScrollUp(View view, float x, float y) { int childRight = child.getRight() - view.getScrollX(); int childBottom = child.getBottom() - view.getScrollY(); boolean intersects = x > childLeft && x < childRight && y > childTop && y < childBottom; - if (intersects && canScrollUp(child, x - childLeft, y - childTop)) { + if ((!lockRect || intersects) + && canScrollUp(child, x - childLeft, y - childTop, lockRect)) { return true; } } @@ -320,7 +372,7 @@ protected boolean canScrollUp(View view, float x, float y) { return view.canScrollVertically(-1); } - protected boolean canScrollDown(View view, float x, float y) { + protected boolean canScrollDown(View view, float x, float y, boolean lockRect) { if (view instanceof WebView) { return canWebViewScrollDown(); } @@ -333,7 +385,8 @@ protected boolean canScrollDown(View view, float x, float y) { int childRight = child.getRight() - view.getScrollX(); int childBottom = child.getBottom() - view.getScrollY(); boolean intersects = x > childLeft && x < childRight && y > childTop && y < childBottom; - if (intersects && canScrollDown(child, x - childLeft, y - childTop)) { + if ((!lockRect || intersects) + && canScrollDown(child, x - childLeft, y - childTop, lockRect)) { return true; } } @@ -406,16 +459,22 @@ private boolean canWebViewScrollDown() { private void setSheetTranslation(float newTranslation) { this.mSheetTranslation = newTranslation; - int bottomClip = (int) (getHeight() - Math.ceil(mSheetTranslation)); + int bottomClip = (int) (mTouchParentViewOriginMeasureHeight - Math.ceil(mSheetTranslation)); setTranslation(bottomClip); } public void seAnimtTranslation(float transY) { - this.mSheetTranslation = getHeight() - transY; + this.mSheetTranslation = mTouchParentViewOriginMeasureHeight - transY; setTranslation(transY); } public void setTranslation(float transY) { + if (mSheetDirection == SheetDirection.BOTTOM && transY < 0) { + return; + } + if (mSheetDirection == SheetDirection.TOP && transY > 0) { + return; + } notifyNestScrollChildChangeCallback(transY); if (mChildView != null) { mChildView.setTranslationY(transY); @@ -454,6 +513,7 @@ public void onAnimationEnd(@NonNull Animator animation) { } }); currentAnimator.start(); + } private void interceptHorizationTouch(MotionEvent event, float deltaX, float deltaY) { @@ -497,6 +557,13 @@ private void onActionRelease(MotionEvent event) { mTransYAnim.setDuration(200L); mTransYAnim.setInterpolator(PathInterpolatorCompat.create(0.4F, 0.0F, 0.2F, 1.0F)); + mTransYAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + + } + }); + mTransYAnim.start(); } @@ -534,11 +601,21 @@ private void notifyNestScrollChildHorizationCallback(boolean show) { } } + private void notifyOnFingerUp(float velocityY) { + for (INestChildScrollChange change : mNestChildScrollChangeCallbacks) { + change.onFingerUp(velocityY); + } + } + @Override protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); } + public void setSheetDirection(@SheetDirection int direction) { + mSheetDirection = direction; + } + private float countDragDistanceFromMotionEvent(@NonNull MotionEvent event) { float distance = event.getRawY(); return distance; @@ -592,4 +669,29 @@ public boolean isFingerHolderTouch() { public float getMinFlingVelocity() { return minFlingVelocity; } + + + public void expand() { + expand(null); + } + + public void peek(int offset) { + peek(offset, null); + } + + public void hiden() { + hiden(null); + } + + public void expand(Runnable runnable) { + recover(0, runnable); + } + + public void peek(int offset, Runnable runnable) { + recover(offset, runnable); + } + + public void hiden(Runnable runnable) { + recover(getMeasuredHeight(), runnable); + } }