diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..797c2f4b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: android +android: + components: + - tools + - platform-tools + - build-tools-25.0.2 + - android-25 + - extra-android-support + - extra + - extra-android-m2repository +script: + - ./gradlew assembleDebug \ No newline at end of file diff --git a/README.md b/README.md index 4cf4a10a..55c53938 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ -# Android Swipe Layout +# Android Swipe Layout [![Build Status](https://travis-ci.org/daimajia/AndroidSwipeLayout.svg?branch=master)](https://travis-ci.org/daimajia/AndroidSwipeLayout) [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/daimajia/AndroidSwipeLayout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Insight.io](https://insight.io/repoBadge/github.com/daimajia/AndroidSwipeLayout)](https://insight.io/github.com/daimajia/AndroidSwipeLayout) + This is the brother of [AndroidViewHover](https://github.com/daimajia/AndroidViewHover). One year ago, I started to make an app named [EverMemo](https://play.google.com/store/apps/details?id=com.zhan_dui.evermemo) with my good friends. The designer gave me a design picture, the design like this: @@ -71,6 +73,8 @@ dependencies { ### Step 2 +**Make sure to use the internal adapter instead of your own!** + [Wiki Usage](https://github.com/daimajia/AndroidSwipeLayout/wiki/usage) ## Wiki diff --git a/build.gradle b/build.gradle index 21b3e999..82697f55 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' + classpath 'com.android.tools.build:gradle:2.3.0' classpath 'com.github.dcendents:android-maven-plugin:1.2' // NOTE: Do not place your application dependencies here; they belong diff --git a/demo/build.gradle b/demo/build.gradle index 586f375b..09dca2ba 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -26,7 +26,7 @@ android { dependencies { compile project(":library") - compile 'com.android.support:recyclerview-v7:21.0.0' + compile 'com.android.support:recyclerview-v7:25.1.1' compile 'com.daimajia.easing:library:1.0.0@aar' compile 'com.daimajia.androidanimations:library:1.1.2@aar' compile 'com.nineoldandroids:library:2.4.0' diff --git a/demo/src/main/java/com/daimajia/swipedemo/adapter/util/RecyclerItemClickListener.java b/demo/src/main/java/com/daimajia/swipedemo/adapter/util/RecyclerItemClickListener.java index af4021b1..613e8e52 100644 --- a/demo/src/main/java/com/daimajia/swipedemo/adapter/util/RecyclerItemClickListener.java +++ b/demo/src/main/java/com/daimajia/swipedemo/adapter/util/RecyclerItemClickListener.java @@ -37,4 +37,9 @@ public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + + } } diff --git a/gradle.properties b/gradle.properties index efb99e76..beab8970 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,7 +22,7 @@ VERSION_NAME=1.2.0 VERSION_CODE=22 GROUP=com.daimajia.swipelayout -ANDROID_BUILD_MIN_SDK_VERSION=8 -ANDROID_BUILD_TARGET_SDK_VERSION=21 -ANDROID_BUILD_SDK_VERSION=21 -ANDROID_BUILD_TOOLS_VERSION=21.0.0 +ANDROID_BUILD_MIN_SDK_VERSION=9 +ANDROID_BUILD_TARGET_SDK_VERSION=25 +ANDROID_BUILD_SDK_VERSION=25 +ANDROID_BUILD_TOOLS_VERSION=25.0.2 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index af3deba8..776d2a5a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 10 15:27:10 PDT 2013 +#Thu Mar 09 16:07:03 CST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-2.2.1-all.zip \ No newline at end of file +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/library/build.gradle b/library/build.gradle index 00c2f126..906272e1 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -5,18 +5,17 @@ android { buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION defaultConfig { - minSdkVersion 8 + minSdkVersion 9 targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION) } } dependencies { - compile 'com.android.support:recyclerview-v7:21.0.0' - compile 'com.android.support:support-v4:22.1.1' + compile 'com.android.support:recyclerview-v7:25.2.0' + compile 'com.android.support:support-v4:25.2.0' } apply from: './gradle-mvn-push.gradle' -apply plugin: 'android-maven' // build a jar with source files task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs diff --git a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java index d8ee9bde..6703123c 100644 --- a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java +++ b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java @@ -3,7 +3,6 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; -import android.support.annotation.Nullable; import android.support.v4.view.GravityCompat; import android.support.v4.view.ViewCompat; import android.support.v4.widget.ViewDragHelper; @@ -52,12 +51,15 @@ public class SwipeLayout extends FrameLayout { private List mSwipeDeniers = new ArrayList<>(); private Map> mRevealListeners = new HashMap<>(); private Map mShowEntirely = new HashMap<>(); + private Map mViewBoundCache = new HashMap<>();//save all children's bound, restore in onLayout private DoubleClickListener mDoubleClickListener; private boolean mSwipeEnabled = true; private boolean[] mSwipesEnabled = new boolean[]{true, true, true, true}; private boolean mClickToClose = false; + private float mWillOpenPercentAfterOpen = 0.75f; + private float mWillOpenPercentAfterClose = 0.25f; public enum DragEdge { Left, @@ -392,9 +394,35 @@ else if (mCurrentDragEdge == DragEdge.Bottom && newTop > getPaddingTop()) dispatchSwipeEvent(evLeft, evTop, dx, dy); invalidate(); + + captureChildrenBound(); } }; + /** + * save children's bounds, so they can restore the bound in {@link #onLayout(boolean, int, int, int, int)} + */ + private void captureChildrenBound() { + View currentBottomView = getCurrentBottomView(); + if (getOpenStatus() == Status.Close) { + mViewBoundCache.remove(currentBottomView); + return; + } + + View[] views = new View[]{getSurfaceView(), currentBottomView}; + for (View child : views) { + Rect rect = mViewBoundCache.get(child); + if (rect == null) { + rect = new Rect(); + mViewBoundCache.put(child, rect); + } + rect.left = child.getLeft(); + rect.top = child.getTop(); + rect.right = child.getRight(); + rect.bottom = child.getBottom(); + } + } + /** * the dispatchRevealEvent method may not always get accurate position, it * makes the view may not always get the event when the view is totally @@ -763,30 +791,36 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { } void layoutPullOut() { - Rect rect = computeSurfaceLayoutArea(false); View surfaceView = getSurfaceView(); + Rect surfaceRect = mViewBoundCache.get(surfaceView); + if (surfaceRect == null) surfaceRect = computeSurfaceLayoutArea(false); if (surfaceView != null) { - surfaceView.layout(rect.left, rect.top, rect.right, rect.bottom); + surfaceView.layout(surfaceRect.left, surfaceRect.top, surfaceRect.right, surfaceRect.bottom); bringChildToFront(surfaceView); } - rect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, rect); View currentBottomView = getCurrentBottomView(); + Rect bottomViewRect = mViewBoundCache.get(currentBottomView); + if (bottomViewRect == null) + bottomViewRect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, surfaceRect); if (currentBottomView != null) { - currentBottomView.layout(rect.left, rect.top, rect.right, rect.bottom); + currentBottomView.layout(bottomViewRect.left, bottomViewRect.top, bottomViewRect.right, bottomViewRect.bottom); } } void layoutLayDown() { - Rect rect = computeSurfaceLayoutArea(false); View surfaceView = getSurfaceView(); + Rect surfaceRect = mViewBoundCache.get(surfaceView); + if (surfaceRect == null) surfaceRect = computeSurfaceLayoutArea(false); if (surfaceView != null) { - surfaceView.layout(rect.left, rect.top, rect.right, rect.bottom); + surfaceView.layout(surfaceRect.left, surfaceRect.top, surfaceRect.right, surfaceRect.bottom); bringChildToFront(surfaceView); } - rect = computeBottomLayoutAreaViaSurface(ShowMode.LayDown, rect); View currentBottomView = getCurrentBottomView(); + Rect bottomViewRect = mViewBoundCache.get(currentBottomView); + if (bottomViewRect == null) + bottomViewRect = computeBottomLayoutAreaViaSurface(ShowMode.LayDown, surfaceRect); if (currentBottomView != null) { - currentBottomView.layout(rect.left, rect.top, rect.right, rect.bottom); + currentBottomView.layout(bottomViewRect.left, bottomViewRect.top, bottomViewRect.right, bottomViewRect.bottom); } } @@ -1011,6 +1045,46 @@ public void setBottomSwipeEnabled(boolean bottomSwipeEnabled) { this.mSwipesEnabled[DragEdge.Bottom.ordinal()] = bottomSwipeEnabled; } + /*** + * Returns the percentage of revealing at which the view below should the view finish opening + * if it was already open before dragging + * + * @returns The percentage of view revealed to trigger, default value is 0.25 + */ + public float getWillOpenPercentAfterOpen() { + return mWillOpenPercentAfterOpen; + } + + /*** + * Allows to stablish at what percentage of revealing the view below should the view finish opening + * if it was already open before dragging + * + * @param willOpenPercentAfterOpen The percentage of view revealed to trigger, default value is 0.25 + */ + public void setWillOpenPercentAfterOpen(float willOpenPercentAfterOpen) { + this.mWillOpenPercentAfterOpen = willOpenPercentAfterOpen; + } + + /*** + * Returns the percentage of revealing at which the view below should the view finish opening + * if it was already closed before dragging + * + * @returns The percentage of view revealed to trigger, default value is 0.25 + */ + public float getWillOpenPercentAfterClose() { + return mWillOpenPercentAfterClose; + } + + /*** + * Allows to stablish at what percentage of revealing the view below should the view finish opening + * if it was already closed before dragging + * + * @param willOpenPercentAfterClose The percentage of view revealed to trigger, default value is 0.75 + */ + public void setWillOpenPercentAfterClose(float willOpenPercentAfterClose) { + this.mWillOpenPercentAfterClose = willOpenPercentAfterClose; + } + private boolean insideAdapterView() { return getAdapterView() != null; } @@ -1195,7 +1269,6 @@ public View getSurfaceView() { /** * return null if there is no bottom view */ - @Nullable public View getCurrentBottomView() { List bottoms = getBottomViews(); if (mCurrentDragEdge.ordinal() < bottoms.size()) { @@ -1258,7 +1331,7 @@ protected void processHandRelease(float xvel, float yvel, boolean isCloseBeforeD if (currentDragEdge == null || surfaceView == null) { return; } - float willOpenPercent = (isCloseBeforeDragged ? .25f : .75f); + float willOpenPercent = (isCloseBeforeDragged ? mWillOpenPercentAfterClose : mWillOpenPercentAfterOpen); if (currentDragEdge == DragEdge.Left) { if (xvel > minVelocity) open(); else if (xvel < -minVelocity) close(); @@ -1497,7 +1570,7 @@ public void setDragEdge(DragEdge dragEdge) { setCurrentDragEdge(dragEdge); } - protected void onViewRemoved(View child) { + public void onViewRemoved(View child) { for (Map.Entry entry : new HashMap(mDragEdges).entrySet()) { if (entry.getValue() == child) { mDragEdges.remove(entry.getKey());