diff --git a/.travis.yml b/.travis.yml index 8ffcb287..32af2e8b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ android: - platform-tools - extra-android-m2repository - extra-google-m2repository - - build-tools-23.0.2 + - build-tools-23.0.3 - android-23 # Enable travis container based infrastructure diff --git a/README.md b/README.md index 387853a2..15029b4d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,15 @@ As seen in Umano Android App (now acquired by Dropbox): ![SlidingUpPanelLayout](https://raw.github.com/umano/AndroidSlidingUpPanelDemo/master/slidinguppanel.png) -### Importing the library +### Known Uses in Popular Apps + +* [Soundcloud] (https://play.google.com/store/apps/details?id=com.soundcloud.android) +* [Dropbox Paper] (https://play.google.com/store/apps/details?id=com.dropbox.paper) +* [Snaptee] (https://play.google.com/store/apps/details?id=co.snaptee.android) + +If you are using the library and you would like to have your app listed, simply let us know. + +### Importing the Library Simply add the following dependency to your `build.gradle` file to use the latest version: @@ -19,7 +27,7 @@ dependencies { repositories { mavenCentral() } - compile 'com.sothree.slidinguppanel:library:3.3.0' + compile 'com.sothree.slidinguppanel:library:3.3.1' } ``` @@ -131,6 +139,9 @@ If you have an awesome pull request, send it over! ### Changelog +* 3.3.1 + * Lots of bug fixes from various pull requests. + * Removed the nineoldandroids dependency. Use ViewCompat instead. * 3.3.0 * You can now set a `FadeOnClickListener`, for when the faded area of the main content is clicked. * `PanelSlideListener` has a new format (multiple of them can be set now @@ -156,13 +167,6 @@ If you have an awesome pull request, send it over! * 2.0.0 - Cleaned up various public method calls. Added animated `showPanel`/`hidePanel` methods. * 1.0.1 - Initial Release -### Known Users - -* [Soundcloud Android App] (https://play.google.com/store/apps/details?id=com.soundcloud.android) -* Umano Android App (Acquired by Dropbox) - -If you are using the library and you would like to have your app listed, simply send us a pull request. - ### Licence > Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/build.gradle b/build.gradle index 9d66dfce..d49db880 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.android.tools.build:gradle:2.1.2' } } @@ -23,6 +23,6 @@ allprojects { } task wrapper(type: Wrapper) { - gradleVersion = '2.11' + gradleVersion = '2.13' distributionUrl = "https://services.gradle.org/distributions/gradle-${gradleVersion}-all.zip" } diff --git a/demo/build.gradle b/demo/build.gradle index eda3a283..86f0df2e 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 23 - buildToolsVersion "23.0.2" + buildToolsVersion "23.0.3" lintOptions { abortOnError false @@ -15,7 +15,7 @@ android { } dependencies { - compile 'com.android.support:support-v4:23.2.1' - compile 'com.android.support:appcompat-v7:23.2.1' + compile 'com.android.support:support-v4:23.4.0' + compile 'com.android.support:appcompat-v7:23.4.0' compile project(':library') } diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml index 4107af09..b818fef0 100644 --- a/demo/src/main/AndroidManifest.xml +++ b/demo/src/main/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="16" + android:versionName="3.3.1"> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then diff --git a/gradlew.bat b/gradlew.bat index 72d362da..f6d5974e 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/library/build.gradle b/library/build.gradle index 5306d859..0f92c0bf 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -5,16 +5,15 @@ repositories { } dependencies { - compile 'com.android.support:support-v4:23.2.1' - compile 'com.android.support:support-annotations:23.2.1' - compile 'com.android.support:recyclerview-v7:23.2.1' - compile 'com.nineoldandroids:library:2.4.0' + compile 'com.android.support:support-v4:23.4.0' + compile 'com.android.support:support-annotations:23.4.0' + compile 'com.android.support:recyclerview-v7:23.4.0' } android { compileSdkVersion 23 - buildToolsVersion "23.0.2" + buildToolsVersion "23.0.3" lintOptions { abortOnError false } -} \ No newline at end of file +} diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml index 2d9f13bc..11c048c5 100644 --- a/library/src/main/AndroidManifest.xml +++ b/library/src/main/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="16" + android:versionName="3.3.1"> diff --git a/library/src/main/java/com/sothree/slidinguppanel/SlidingUpPanelLayout.java b/library/src/main/java/com/sothree/slidinguppanel/SlidingUpPanelLayout.java index c6cdff2c..1081803b 100644 --- a/library/src/main/java/com/sothree/slidinguppanel/SlidingUpPanelLayout.java +++ b/library/src/main/java/com/sothree/slidinguppanel/SlidingUpPanelLayout.java @@ -9,8 +9,11 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.support.annotation.NonNull; +import android.support.v4.app.BundleCompat; import android.support.v4.view.MotionEventCompat; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; @@ -22,7 +25,6 @@ import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; -import com.nineoldandroids.view.animation.AnimatorProxy; import com.sothree.slidinguppanel.library.R; import java.util.ArrayList; @@ -75,6 +77,10 @@ public class SlidingUpPanelLayout extends ViewGroup { private static final int[] DEFAULT_ATTRS = new int[]{ android.R.attr.gravity }; + /** + * Tag for the sliding state stored inside the bundle + */ + public static final String SLIDING_STATE = "sliding_state"; /** * Minimum velocity that will be detected as a fling @@ -495,7 +501,9 @@ public void setMinFlingVelocity(int val) { * @param listener */ public void addPanelSlideListener(PanelSlideListener listener) { - mPanelSlideListeners.add(listener); + synchronized (mPanelSlideListeners) { + mPanelSlideListeners.add(listener); + } } /** @@ -504,7 +512,9 @@ public void addPanelSlideListener(PanelSlideListener listener) { * @param listener */ public void removePanelSlideListener(PanelSlideListener listener) { - mPanelSlideListeners.remove(listener); + synchronized (mPanelSlideListeners) { + mPanelSlideListeners.remove(listener); + } } /** @@ -635,15 +645,21 @@ public boolean isClipPanel() { return mClipPanel; } + void dispatchOnPanelSlide(View panel) { - for (PanelSlideListener l : mPanelSlideListeners) { - l.onPanelSlide(panel, mSlideOffset); + synchronized (mPanelSlideListeners) { + for (PanelSlideListener l : mPanelSlideListeners) { + l.onPanelSlide(panel, mSlideOffset); + } } } + void dispatchOnPanelStateChanged(View panel, PanelState previousState, PanelState newState) { - for (PanelSlideListener l : mPanelSlideListeners) { - l.onPanelStateChanged(panel, previousState, newState); + synchronized (mPanelSlideListeners) { + for (PanelSlideListener l : mPanelSlideListeners) { + l.onPanelStateChanged(panel, previousState, newState); + } } sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } @@ -716,9 +732,9 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int heightMode = MeasureSpec.getMode(heightMeasureSpec); final int heightSize = MeasureSpec.getSize(heightMeasureSpec); - if (widthMode != MeasureSpec.EXACTLY) { + if (widthMode != MeasureSpec.EXACTLY && widthMode != MeasureSpec.AT_MOST) { throw new IllegalStateException("Width must have an exact value or MATCH_PARENT"); - } else if (heightMode != MeasureSpec.EXACTLY) { + } else if (heightMode != MeasureSpec.EXACTLY && heightMode != MeasureSpec.AT_MOST) { throw new IllegalStateException("Height must have an exact value or MATCH_PARENT"); } @@ -890,6 +906,12 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { // mIsUnableToDrag = false; mInitialMotionX = x; mInitialMotionY = y; + if (!isViewUnder(mDragView, (int) x, (int) y)) { + mDragHelper.cancel(); + mIsUnableToDrag = true; + return false; + } + break; case MotionEvent.ACTION_MOVE: { @@ -900,8 +922,8 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { return false; } else if ((ady > dragSlop && adx > ady)) { mDragHelper.cancel(); -// mIsUnableToDrag = true; -// return false; + mIsUnableToDrag = true; + return false; } break; } @@ -1128,16 +1150,14 @@ private void setPanelStateInternal(PanelState state) { private void applyParallaxForCurrentSlideOffset() { if (mParallaxOffset > 0) { int mainViewOffset = getCurrentParallaxOffset(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - mMainView.setTranslationY(mainViewOffset); - } else { - AnimatorProxy.wrap(mMainView).setTranslationY(mainViewOffset); - } + ViewCompat.setTranslationY(mMainView, mainViewOffset); } } private void onPanelDragged(int newTop) { - mLastNotDraggingSlideState = mSlideState; + if (mSlideState != PanelState.DRAGGING) { + mLastNotDraggingSlideState = mSlideState; + } setPanelStateInternal(PanelState.DRAGGING); // Recompute the slide offset based on the new top position mSlideOffset = computeSlideOffset(newTop); @@ -1167,7 +1187,7 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean result; final int save = canvas.save(Canvas.CLIP_SAVE_FLAG); - if (mSlideableView != child) { // if main view + if (mSlideableView != null && mSlideableView != child) { // if main view // Clip against the slider; no sense drawing what will immediately be covered, // Unless the panel is set to overlay content canvas.getClipBounds(mTmpRect); @@ -1311,22 +1331,21 @@ public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { @Override public Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); - - SavedState ss = new SavedState(superState); - if (mSlideState != PanelState.DRAGGING) { - ss.mSlideState = mSlideState; - } else { - ss.mSlideState = mLastNotDraggingSlideState; - } - return ss; + Bundle bundle = new Bundle(); + bundle.putParcelable("superState", super.onSaveInstanceState()); + bundle.putSerializable(SLIDING_STATE, mSlideState != PanelState.DRAGGING ? mSlideState : mLastNotDraggingSlideState); + return bundle; } @Override public void onRestoreInstanceState(Parcelable state) { - SavedState ss = (SavedState) state; - super.onRestoreInstanceState(ss.getSuperState()); - mSlideState = ss.mSlideState != null ? ss.mSlideState : DEFAULT_SLIDE_STATE; + if(state instanceof Bundle) { + Bundle bundle = (Bundle) state; + mSlideState = (PanelState) bundle.getSerializable(SLIDING_STATE); + mSlideState = mSlideState == null ? DEFAULT_SLIDE_STATE : mSlideState; + state = bundle.getParcelable("superState"); + } + super.onRestoreInstanceState(state); } private class DragHelperCallback extends ViewDragHelper.Callback { @@ -1466,42 +1485,4 @@ public LayoutParams(Context c, AttributeSet attrs) { ta.recycle(); } } - - static class SavedState extends BaseSavedState { - PanelState mSlideState; - - SavedState(Parcelable superState) { - super(superState); - } - - private SavedState(Parcel in) { - super(in); - String panelStateString = in.readString(); - try { - mSlideState = panelStateString != null ? Enum.valueOf(PanelState.class, panelStateString) - : PanelState.COLLAPSED; - } catch (IllegalArgumentException e) { - mSlideState = PanelState.COLLAPSED; - } - } - - @Override - public void writeToParcel(Parcel out, int flags) { - super.writeToParcel(out, flags); - out.writeString(mSlideState == null ? null : mSlideState.toString()); - } - - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - @Override - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } }