From 9791c52d86a6cc6d028f8381dd700d3fbceab310 Mon Sep 17 00:00:00 2001 From: Sven Braune Date: Tue, 21 May 2019 14:41:35 +0200 Subject: [PATCH 1/4] # removed android annotations --- app/build.gradle | 24 ++++++++-------- .../com/demo/ExampleInstrumentedTest.java | 4 +-- .../java/kaufland/com/demo/MainActivity.java | 12 ++++---- .../com/demo/example/EasyExample.java | 2 +- .../example/MyItemRecyclerViewAdapter.java | 6 +--- .../RecylerViewWithRestoreFragment.java | 7 ++--- app/src/main/res/layout/activity_main.xml | 6 ++-- app/src/main/res/layout/app_bar_main.xml | 10 +++---- .../main/res/layout/easy_example_fragment.xml | 28 +++++++++---------- .../fragment_recyclerview_with_restore.xml | 2 +- .../main/res/layout/match_parent_example.xml | 16 +++++------ build.gradle | 8 ++++-- gradle/wrapper/gradle-wrapper.properties | 4 +-- swipelibrary/build.gradle | 24 +++++----------- .../swipelibrary/ExampleInstrumentedTest.java | 4 +-- .../kaufland/com/swipelibrary/DragView.java | 18 ++---------- .../com/swipelibrary/DraggingProxy.java | 14 +++------- .../com/swipelibrary/KDragViewHelper.java | 26 ++++++++--------- .../com/swipelibrary/LayoutCache.java | 3 -- .../com/swipelibrary/SurfaceView.java | 10 ++----- .../swipelibrary/SwipeDirectionDetector.java | 5 +--- .../com/swipelibrary/SwipeLayout.java | 24 ++++++---------- .../kaufland/com/swipelibrary/SwipeState.java | 5 ---- .../com/swipelibrary/SwipeViewLayouter.java | 4 --- 24 files changed, 103 insertions(+), 163 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 2ba496a..5c1d85f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,15 +1,15 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 + compileSdkVersion 28 buildToolsVersion "${androidBuildToolsVersion}" defaultConfig { applicationId "kaufland.com.demo" minSdkVersion 17 - targetSdkVersion 24 + targetSdkVersion 28 versionCode 1 versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { @@ -20,15 +20,15 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + implementation fileTree(dir: 'libs', include: ['*.jar']) + androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0-alpha4', { exclude group: 'com.android.support', module: 'support-annotations' }) - compile project(path: ':swipelibrary') - compile "com.android.support:appcompat-v7:${androidSupportVersion}" - compile "com.android.support:design:${androidSupportVersion}" - compile "com.android.support:support-v4:${androidSupportVersion}" - compile "com.android.support:recyclerview-v7:${androidSupportVersion}" - compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha9' - testCompile "junit:junit:${jUnitVersion}" + implementation project(path: ':swipelibrary') + implementation "androidx.appcompat:appcompat:${androidSupportVersion}" + implementation "com.google.android.material:material:${androidSupportVersion}" + implementation "androidx.legacy:legacy-support-v4:${androidSupportVersion}" + implementation "androidx.recyclerview:recyclerview:${androidSupportVersion}" + implementation 'androidx.constraintlayout:constraintlayout:1.1.2' + testImplementation "junit:junit:${jUnitVersion}" } diff --git a/app/src/androidTest/java/kaufland/com/demo/ExampleInstrumentedTest.java b/app/src/androidTest/java/kaufland/com/demo/ExampleInstrumentedTest.java index 3273c35..06e81b8 100644 --- a/app/src/androidTest/java/kaufland/com/demo/ExampleInstrumentedTest.java +++ b/app/src/androidTest/java/kaufland/com/demo/ExampleInstrumentedTest.java @@ -1,8 +1,8 @@ package kaufland.com.demo; import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/app/src/main/java/kaufland/com/demo/MainActivity.java b/app/src/main/java/kaufland/com/demo/MainActivity.java index 355078f..a66d3f5 100644 --- a/app/src/main/java/kaufland/com/demo/MainActivity.java +++ b/app/src/main/java/kaufland/com/demo/MainActivity.java @@ -1,12 +1,12 @@ package kaufland.com.demo; import android.os.Bundle; -import android.support.design.widget.NavigationView; -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; +import com.google.android.material.navigation.NavigationView; +import androidx.core.view.GravityCompat; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; diff --git a/app/src/main/java/kaufland/com/demo/example/EasyExample.java b/app/src/main/java/kaufland/com/demo/example/EasyExample.java index 85c0548..ac54112 100644 --- a/app/src/main/java/kaufland/com/demo/example/EasyExample.java +++ b/app/src/main/java/kaufland/com/demo/example/EasyExample.java @@ -2,7 +2,7 @@ import android.app.Fragment; import android.os.Bundle; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/kaufland/com/demo/example/MyItemRecyclerViewAdapter.java b/app/src/main/java/kaufland/com/demo/example/MyItemRecyclerViewAdapter.java index 4b3b6a8..8843b45 100644 --- a/app/src/main/java/kaufland/com/demo/example/MyItemRecyclerViewAdapter.java +++ b/app/src/main/java/kaufland/com/demo/example/MyItemRecyclerViewAdapter.java @@ -1,12 +1,9 @@ package kaufland.com.demo.example; -import android.inputmethodservice.Keyboard; -import android.os.Looper; -import android.support.v7.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; import android.widget.Toast; import kaufland.com.demo.R; @@ -19,7 +16,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Handler; /** * {@link RecyclerView.Adapter} that can display a {@link DummyItem} and makes a call to the diff --git a/app/src/main/java/kaufland/com/demo/example/RecylerViewWithRestoreFragment.java b/app/src/main/java/kaufland/com/demo/example/RecylerViewWithRestoreFragment.java index fd6eb2d..b4d4fe9 100644 --- a/app/src/main/java/kaufland/com/demo/example/RecylerViewWithRestoreFragment.java +++ b/app/src/main/java/kaufland/com/demo/example/RecylerViewWithRestoreFragment.java @@ -4,9 +4,8 @@ import android.content.Context; import android.os.Bundle; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -15,8 +14,6 @@ import kaufland.com.demo.example.dummy.DummyContent; import kaufland.com.demo.example.dummy.DummyContent.DummyItem; -import java.util.List; - /** * A fragment representing a list of Items. *

diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 17330ae..7f99138 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,5 @@ - - - + diff --git a/app/src/main/res/layout/app_bar_main.xml b/app/src/main/res/layout/app_bar_main.xml index 06649ea..bb96f25 100644 --- a/app/src/main/res/layout/app_bar_main.xml +++ b/app/src/main/res/layout/app_bar_main.xml @@ -1,5 +1,5 @@ - - - - + - + diff --git a/app/src/main/res/layout/easy_example_fragment.xml b/app/src/main/res/layout/easy_example_fragment.xml index 8fb5ca9..0791ed7 100644 --- a/app/src/main/res/layout/easy_example_fragment.xml +++ b/app/src/main/res/layout/easy_example_fragment.xml @@ -14,7 +14,7 @@ tools:context="kaufland.com.demo.MainActivity"> - - - + - - + - - - + + - - - + - - - + + diff --git a/app/src/main/res/layout/fragment_recyclerview_with_restore.xml b/app/src/main/res/layout/fragment_recyclerview_with_restore.xml index 6fe9d04..7a8880b 100644 --- a/app/src/main/res/layout/fragment_recyclerview_with_restore.xml +++ b/app/src/main/res/layout/fragment_recyclerview_with_restore.xml @@ -1,5 +1,5 @@ - - - - + - - + - - - + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index e3478e6..6eedaf6 100644 --- a/build.gradle +++ b/build.gradle @@ -3,14 +3,15 @@ buildscript { repositories { jcenter() + google() } ext { - androidSupportVersion = '25.0.1' - androidBuildToolsVersion = '25.0.1' + androidSupportVersion = '1.0.0-beta01' + androidBuildToolsVersion = '28.0.3' jUnitVersion = '4.12' } dependencies { - classpath 'com.android.tools.build:gradle:2.3.0' + classpath 'com.android.tools.build:gradle:3.3.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -20,6 +21,7 @@ buildscript { allprojects { repositories { jcenter() + google() } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 44a5f01..3fbaeab 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Mar 29 10:26:33 CEST 2017 +#Tue May 21 10:00:45 CEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip diff --git a/swipelibrary/build.gradle b/swipelibrary/build.gradle index e9846fb..c822672 100644 --- a/swipelibrary/build.gradle +++ b/swipelibrary/build.gradle @@ -1,19 +1,18 @@ apply plugin: 'com.android.library' -apply plugin: 'android-apt' apply plugin: 'maven' apply plugin: 'jacoco' apply plugin: 'pmd' android { - compileSdkVersion 25 + compileSdkVersion 28 buildToolsVersion "${androidBuildToolsVersion}" defaultConfig { minSdkVersion 17 - targetSdkVersion 24 + targetSdkVersion 28 versionCode 1 versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } lintOptions { @@ -52,13 +51,6 @@ buildscript { } } -apt { - arguments { - library 'true' - androidManifestFile variant.outputs[0]?.processResources?.manifestFile - } -} - task wrapper(type: Wrapper) { gradleVersion = '2.2.0' } @@ -80,12 +72,10 @@ task jacocoTestReport(type: JacocoReport, dependsOn: 'testDebugUnitTest', group: } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + implementation fileTree(dir: 'libs', include: ['*.jar']) + androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0-alpha4', { exclude group: 'com.android.support', module: 'support-annotations' }) - compile "com.android.support:appcompat-v7:${androidSupportVersion}" - apt "org.androidannotations:androidannotations:4.2.0" - compile 'org.androidannotations:androidannotations-api:4.2.0' - testCompile 'junit:junit:4.12' + implementation "androidx.appcompat:appcompat:${androidSupportVersion}" + testImplementation 'junit:junit:4.12' } diff --git a/swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.java b/swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.java index 78fd424..8c3dfae 100644 --- a/swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.java +++ b/swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.java @@ -1,8 +1,8 @@ package kaufland.com.swipelibrary; import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.java index 178042e..46b87f5 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.java +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.java @@ -2,21 +2,10 @@ import android.content.Context; import android.content.res.TypedArray; -import android.graphics.Rect; import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.FrameLayout; import android.widget.LinearLayout; -import org.androidannotations.annotations.EViewGroup; -import static kaufland.com.swipelibrary.SwipeLayout.BOTTOM_DRAG_VIEW; -import static kaufland.com.swipelibrary.SwipeLayout.LEFT_DRAG_VIEW; -import static kaufland.com.swipelibrary.SwipeLayout.RIGHT_DRAG_VIEW; -import static kaufland.com.swipelibrary.SwipeLayout.TOP_DRAG_VIEW; - -@EViewGroup public class DragView extends LinearLayout { private int mSettlePointResourceId; @@ -29,17 +18,16 @@ public class DragView extends LinearLayout { private boolean mBouncePossible; - DragView(Context context) { + public DragView(Context context) { super(context); - } - DragView(Context context, AttributeSet attrs) { + public DragView(Context context, AttributeSet attrs) { super(context, attrs); initStyleable(context, attrs); } - DragView(Context context, AttributeSet attrs, int defStyleAttr) { + public DragView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initStyleable(context, attrs); } diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.java index 529c5ad..64d5ae9 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.java +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.java @@ -1,31 +1,25 @@ package kaufland.com.swipelibrary; -import android.graphics.Rect; import android.view.View; import android.view.ViewGroup; -import org.androidannotations.annotations.Bean; -import org.androidannotations.annotations.EBean; - import kaufland.com.swipelibrary.dragengine.DraggingEngine; import static kaufland.com.swipelibrary.SwipeLayout.LEFT_DRAG_VIEW; import static kaufland.com.swipelibrary.SwipeLayout.RIGHT_DRAG_VIEW; import static kaufland.com.swipelibrary.SwipeLayout.SURFACE_VIEW; -import static kaufland.com.swipelibrary.SwipeState.DragViewState.LEFT_OPEN; import static kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.HORIZONTAL; /** * Created by sbra0902 on 30.03.17. */ -@EBean + public class DraggingProxy { - @Bean - protected SwipeViewLayouter mSwipeViewLayouter; - @Bean - protected LayoutCache mLayoutCache; + protected SwipeViewLayouter mSwipeViewLayouter = new SwipeViewLayouter(); + + protected LayoutCache mLayoutCache = new LayoutCache(); private boolean isInitilized; diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.java index f879a9a..e99c1b1 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.java +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.java @@ -1,11 +1,11 @@ package kaufland.com.swipelibrary; import android.content.Context; -import android.support.v4.view.MotionEventCompat; -import android.support.v4.view.VelocityTrackerCompat; -import android.support.v4.view.ViewCompat; -import android.support.v4.widget.ScrollerCompat; -import android.support.v4.widget.ViewDragHelper; +import androidx.core.view.MotionEventCompat; +import androidx.core.view.VelocityTrackerCompat; +import androidx.core.view.ViewCompat; +import androidx.core.widget.ScrollerCompat; +import androidx.customview.widget.ViewDragHelper; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; @@ -117,7 +117,7 @@ public class KDragViewHelper { private ScrollerCompat mScroller; - private final android.support.v4.widget.ViewDragHelper.Callback mCallback; + private final ViewDragHelper.Callback mCallback; private View mCapturedView; private boolean mReleaseInProgress; @@ -150,7 +150,7 @@ public void run() { * @param cb Callback to provide information and receive events * @return a new ViewDragHelper instance */ - public static KDragViewHelper create(ViewGroup forParent, android.support.v4.widget.ViewDragHelper.Callback cb) { + public static KDragViewHelper create(ViewGroup forParent, ViewDragHelper.Callback cb) { return new KDragViewHelper(forParent.getContext(), forParent, cb); } @@ -163,7 +163,7 @@ public static KDragViewHelper create(ViewGroup forParent, android.support.v4.wid * @param cb Callback to provide information and receive events * @return a new ViewDragHelper instance */ - public static KDragViewHelper create(ViewGroup forParent, float sensitivity, android.support.v4.widget.ViewDragHelper.Callback cb) { + public static KDragViewHelper create(ViewGroup forParent, float sensitivity, ViewDragHelper.Callback cb) { final KDragViewHelper helper = create(forParent, cb); helper.mTouchSlop = (int) (helper.mTouchSlop * (1 / sensitivity)); return helper; @@ -177,7 +177,7 @@ public static KDragViewHelper create(ViewGroup forParent, float sensitivity, and * @param context Context to initialize config-dependent params from * @param forParent Parent view to monitor */ - private KDragViewHelper(Context context, ViewGroup forParent, android.support.v4.widget.ViewDragHelper.Callback cb) { + private KDragViewHelper(Context context, ViewGroup forParent, ViewDragHelper.Callback cb) { if (forParent == null) { throw new IllegalArgumentException("Parent view may not be null"); } @@ -230,8 +230,8 @@ public int getViewDragState() { /** * Enable edge tracking for the selected edges of the parent view. - * The callback's {@link android.support.v4.widget.ViewDragHelper.Callback#onEdgeTouched(int, int)} and - * {@link android.support.v4.widget.ViewDragHelper.Callback#onEdgeDragStarted(int, int)} methods will only be invoked + * The callback's {@link ViewDragHelper.Callback#onEdgeTouched(int, int)} and + * {@link ViewDragHelper.Callback#onEdgeDragStarted(int, int)} methods will only be invoked * for edges for which edge tracking has been enabled. * * @param edgeFlags Combination of edge flags describing the edges to watch @@ -257,7 +257,7 @@ public int getEdgeSize() { /** * Capture a specific child view for dragging within the parent. The callback will be notified - * but {@link android.support.v4.widget.ViewDragHelper.Callback#tryCaptureView(android.view.View, int)} will not be asked permission to + * but {@link ViewDragHelper.Callback#tryCaptureView(android.view.View, int)} will not be asked permission to * capture this view. * * @param childView Child view to capture @@ -1273,7 +1273,7 @@ public boolean isViewUnder(View view, int x, int y) { /** * Find the topmost child under the given point within the parent view's coordinate system. - * The child order is determined using {@link android.support.v4.widget.ViewDragHelper.Callback#getOrderedChildIndex(int)}. + * The child order is determined using {@link ViewDragHelper.Callback#getOrderedChildIndex(int)}. * * @param x X position to test in the parent's coordinate system * @param y Y position to test in the parent's coordinate system diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.java index 0fc0bf7..a7a46ed 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.java +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.java @@ -3,8 +3,6 @@ import android.graphics.PointF; import android.view.View; -import org.androidannotations.annotations.EBean; - import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -12,7 +10,6 @@ /** * Created by sbra0902 on 21.06.17. */ -@EBean public class LayoutCache { diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.java index c125f91..af62f67 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.java +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.java @@ -1,22 +1,16 @@ package kaufland.com.swipelibrary; import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Rect; import android.os.Build; -import android.support.annotation.Px; -import android.support.annotation.RequiresApi; -import android.support.v4.widget.ViewDragHelper; import android.util.AttributeSet; -import android.util.Log; import android.widget.FrameLayout; -import org.androidannotations.annotations.EViewGroup; +import androidx.annotation.RequiresApi; /** * Created by sbra0902 on 06.03.17. */ -@EViewGroup + public class SurfaceView extends FrameLayout { public SurfaceView(Context context) { diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.java index 6d60c2c..cbdb25a 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.java +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.java @@ -1,14 +1,11 @@ package kaufland.com.swipelibrary; import android.graphics.Rect; -import android.view.ViewTreeObserver; - -import org.androidannotations.annotations.EBean; /** * Created by sbra0902 on 29.03.17. */ -@EBean + public class SwipeDirectionDetector { private int xDown; diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.java index f1e5503..79ea8ca 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.java +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.java @@ -2,21 +2,18 @@ import android.content.Context; import android.graphics.Canvas; -import android.graphics.Rect; -import android.support.v4.view.MotionEventCompat; -import android.support.v4.view.ViewCompat; -import android.support.v4.widget.ViewDragHelper; + +import androidx.core.view.MotionEventCompat; +import androidx.core.view.ViewCompat; +import androidx.customview.widget.ViewDragHelper; import android.util.AttributeSet; -import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; -import android.view.ViewTreeObserver; import android.widget.FrameLayout; -import org.androidannotations.annotations.Bean; -import org.androidannotations.annotations.EViewGroup; + import java.security.InvalidParameterException; @@ -26,7 +23,7 @@ import static kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.HORIZONTAL; import static kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.VERTICAL; -@EViewGroup + public class SwipeLayout extends FrameLayout { private static final int SWIPE_CLOSING_POINT = 0; @@ -39,14 +36,11 @@ public class SwipeLayout extends FrameLayout { private static final String TAG = SwipeLayout.class.getSimpleName(); - @Bean - protected SwipeState mSwipeState; + protected SwipeState mSwipeState = new SwipeState(); - @Bean - protected SwipeDirectionDetector mSwipeDirectionDetector; + protected SwipeDirectionDetector mSwipeDirectionDetector = new SwipeDirectionDetector(); - @Bean - protected DraggingProxy mDraggingProxy; + protected DraggingProxy mDraggingProxy = new DraggingProxy(); private KDragViewHelper mDragHelper; diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.java index 9eef876..3e45beb 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.java +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.java @@ -1,10 +1,5 @@ package kaufland.com.swipelibrary; -import android.util.Log; - -import org.androidannotations.annotations.EBean; - -@EBean public class SwipeState { private boolean isOpen; diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.java index 796c618..560f260 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.java +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.java @@ -1,11 +1,8 @@ package kaufland.com.swipelibrary; -import android.graphics.Rect; import android.view.View; import android.view.ViewGroup; -import org.androidannotations.annotations.EBean; - import java.security.InvalidParameterException; import java.util.HashMap; import java.util.Map; @@ -22,7 +19,6 @@ import static kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.VERTICAL; -@EBean public class SwipeViewLayouter { private Map mViewEngines = new HashMap<>(); From 9843afa7cff58c07a348823a461bb277436a30bc Mon Sep 17 00:00:00 2001 From: Sven Braune Date: Wed, 22 May 2019 10:10:50 +0200 Subject: [PATCH 2/4] # migrated to Kotlin --- .../com/demo/example/EasyExample.java | 4 +- build.gradle | 2 + swipelibrary/build.gradle | 6 + .../swipelibrary/ExampleInstrumentedTest.java | 26 - .../swipelibrary/ExampleInstrumentedTest.kt | 27 + .../kaufland/com/swipelibrary/DragView.java | 76 - .../kaufland/com/swipelibrary/DragView.kt | 45 + .../com/swipelibrary/DraggingProxy.java | 143 -- .../com/swipelibrary/DraggingProxy.kt | 138 ++ .../com/swipelibrary/KDragViewHelper.java | 1315 ----------------- .../com/swipelibrary/KDragViewHelper.kt | 1285 ++++++++++++++++ .../com/swipelibrary/LayoutCache.java | 49 - .../kaufland/com/swipelibrary/LayoutCache.kt | 45 + .../com/swipelibrary/SimpleSwipeListener.java | 19 - .../com/swipelibrary/SimpleSwipeListener.kt | 16 + .../com/swipelibrary/SurfaceView.java | 32 - .../kaufland/com/swipelibrary/SurfaceView.kt | 25 + .../swipelibrary/SwipeDirectionDetector.java | 71 - .../swipelibrary/SwipeDirectionDetector.kt | 64 + .../com/swipelibrary/SwipeLayout.java | 431 ------ .../kaufland/com/swipelibrary/SwipeLayout.kt | 378 +++++ .../com/swipelibrary/SwipeResult.java | 29 - .../kaufland/com/swipelibrary/SwipeResult.kt | 23 + .../kaufland/com/swipelibrary/SwipeState.java | 32 - .../kaufland/com/swipelibrary/SwipeState.kt | 16 + .../com/swipelibrary/SwipeViewLayouter.java | 113 -- .../com/swipelibrary/SwipeViewLayouter.kt | 93 ++ .../dragengine/DraggingEngine.java | 37 - .../swipelibrary/dragengine/DraggingEngine.kt | 37 + .../dragengine/LeftDragViewEngine.java | 135 -- .../dragengine/LeftDragViewEngine.kt | 96 ++ .../dragengine/RightDragViewEngine.java | 137 -- .../dragengine/RightDragViewEngine.kt | 95 ++ .../dragengine/SurfaceViewEngine.java | 261 ---- .../dragengine/SurfaceViewEngine.kt | 193 +++ .../com/swipelibrary/ExampleUnitTest.java | 17 - .../com/swipelibrary/ExampleUnitTest.kt | 18 + 37 files changed, 2604 insertions(+), 2925 deletions(-) delete mode 100644 swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.java create mode 100644 swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SimpleSwipeListener.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SimpleSwipeListener.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeResult.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeResult.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/DraggingEngine.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/DraggingEngine.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/LeftDragViewEngine.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/LeftDragViewEngine.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/RightDragViewEngine.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/RightDragViewEngine.kt delete mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/SurfaceViewEngine.java create mode 100644 swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/SurfaceViewEngine.kt delete mode 100644 swipelibrary/src/test/java/kaufland/com/swipelibrary/ExampleUnitTest.java create mode 100644 swipelibrary/src/test/java/kaufland/com/swipelibrary/ExampleUnitTest.kt diff --git a/app/src/main/java/kaufland/com/demo/example/EasyExample.java b/app/src/main/java/kaufland/com/demo/example/EasyExample.java index ac54112..5ab9475 100644 --- a/app/src/main/java/kaufland/com/demo/example/EasyExample.java +++ b/app/src/main/java/kaufland/com/demo/example/EasyExample.java @@ -86,13 +86,13 @@ public void onClick(View view) { view.findViewById(R.id.btn_open_left).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mViewById.openSwipe(SwipeLayout.LEFT_DRAG_VIEW); + mViewById.openSwipe(SwipeLayout.Companion.getLEFT_DRAG_VIEW()); } }); view.findViewById(R.id.btn_open_right).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mViewById.openSwipe(SwipeLayout.RIGHT_DRAG_VIEW); + mViewById.openSwipe(SwipeLayout.Companion.getRIGHT_DRAG_VIEW()); } }); view.findViewById(R.id.btn_disable_left_drag).setOnClickListener(new View.OnClickListener() { diff --git a/build.gradle b/build.gradle index 6eedaf6..70fe3ee 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext.kotlin_version = '1.3.31' repositories { jcenter() google() @@ -12,6 +13,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/swipelibrary/build.gradle b/swipelibrary/build.gradle index c822672..7b96204 100644 --- a/swipelibrary/build.gradle +++ b/swipelibrary/build.gradle @@ -1,4 +1,6 @@ apply plugin: 'com.android.library' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-android' apply plugin: 'maven' apply plugin: 'jacoco' apply plugin: 'pmd' @@ -78,4 +80,8 @@ dependencies { }) implementation "androidx.appcompat:appcompat:${androidSupportVersion}" testImplementation 'junit:junit:4.12' + compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} +repositories { + mavenCentral() } diff --git a/swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.java b/swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.java deleted file mode 100644 index 8c3dfae..0000000 --- a/swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package kaufland.com.swipelibrary; - -import android.content.Context; -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumentation test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("kaufland.com.swipelibrary.test", appContext.getPackageName()); - } -} diff --git a/swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.kt b/swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..416dc55 --- /dev/null +++ b/swipelibrary/src/androidTest/java/kaufland/com/swipelibrary/ExampleInstrumentedTest.kt @@ -0,0 +1,27 @@ +package kaufland.com.swipelibrary + +import android.content.Context +import androidx.test.InstrumentationRegistry +import androidx.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumentation test, which will execute on an Android device. + * + * @see [Testing documentation](http://d.android.com/tools/testing) + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + @Throws(Exception::class) + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getTargetContext() + + assertEquals("kaufland.com.swipelibrary.test", appContext.packageName) + } +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.java deleted file mode 100644 index 46b87f5..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.java +++ /dev/null @@ -1,76 +0,0 @@ -package kaufland.com.swipelibrary; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.widget.LinearLayout; - - -public class DragView extends LinearLayout { - - private int mSettlePointResourceId; - - private int mViewPosition; - - private boolean mDraggable = true; - - private boolean mIsInitialized; - - private boolean mBouncePossible; - - public DragView(Context context) { - super(context); - } - - public DragView(Context context, AttributeSet attrs) { - super(context, attrs); - initStyleable(context, attrs); - } - - public DragView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initStyleable(context, attrs); - } - - private void initStyleable(Context context, AttributeSet attrs) { - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DragView, 0, 0); - try{ - mViewPosition = typedArray.getInt(R.styleable.DragView_position, 0); - mSettlePointResourceId = typedArray.getResourceId(R.styleable.DragView_settleView, -1); - mBouncePossible = typedArray.getBoolean(R.styleable.DragView_bouncePossible, false); - } finally { - typedArray.recycle(); - } - } - - - public int getSettlePointResourceId() { - return mSettlePointResourceId; - } - - public void setDraggable(boolean canDrag) { - mDraggable = canDrag; - } - - public boolean isDraggable() { - return mDraggable; - } - - boolean isInitialized() { - return mIsInitialized; - } - - public int getViewPosition() { - return mViewPosition; - } - - public boolean isBouncePossible() { - return mBouncePossible; - } - - public void setBouncePossible(boolean bouncePossible) { - mBouncePossible = bouncePossible; - } - - -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.kt new file mode 100644 index 0000000..50d7668 --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/DragView.kt @@ -0,0 +1,45 @@ +package kaufland.com.swipelibrary + +import android.content.Context +import android.content.res.TypedArray +import android.util.AttributeSet +import android.widget.LinearLayout + + +class DragView : LinearLayout { + + var settlePointResourceId: Int = 0 + private set + + var viewPosition: Int = 0 + private set + + var isDraggable = true + + internal val isInitialized: Boolean = false + + var isBouncePossible: Boolean = false + + constructor(context: Context) : super(context) {} + + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { + initStyleable(context, attrs) + } + + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + initStyleable(context, attrs) + } + + private fun initStyleable(context: Context, attrs: AttributeSet) { + val typedArray = context.obtainStyledAttributes(attrs, R.styleable.DragView, 0, 0) + try { + viewPosition = typedArray.getInt(R.styleable.DragView_position, 0) + settlePointResourceId = typedArray.getResourceId(R.styleable.DragView_settleView, -1) + isBouncePossible = typedArray.getBoolean(R.styleable.DragView_bouncePossible, false) + } finally { + typedArray.recycle() + } + } + + +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.java deleted file mode 100644 index 64d5ae9..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.java +++ /dev/null @@ -1,143 +0,0 @@ -package kaufland.com.swipelibrary; - -import android.view.View; -import android.view.ViewGroup; - -import kaufland.com.swipelibrary.dragengine.DraggingEngine; - -import static kaufland.com.swipelibrary.SwipeLayout.LEFT_DRAG_VIEW; -import static kaufland.com.swipelibrary.SwipeLayout.RIGHT_DRAG_VIEW; -import static kaufland.com.swipelibrary.SwipeLayout.SURFACE_VIEW; -import static kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.HORIZONTAL; - -/** - * Created by sbra0902 on 30.03.17. - */ - -public class DraggingProxy { - - - protected SwipeViewLayouter mSwipeViewLayouter = new SwipeViewLayouter(); - - protected LayoutCache mLayoutCache = new LayoutCache(); - - private boolean isInitilized; - - - public void init(ViewGroup parent) { - isInitilized = true; - mSwipeViewLayouter.init(parent); - initInitialPosition(); - } - - - public void requestLayout() { - for (View dragView : mSwipeViewLayouter.getViews().values()) { - dragView.forceLayout(); - } - } - - public int clampViewPositionHorizontal(View child, int left) { - - for (DraggingEngine dragView : mSwipeViewLayouter.getViewEngines().values()) { - if (dragView.getDragView().equals(child)) { - return dragView.clampViewPositionHorizontal(child, left); - } - } - return left; - } - - public SwipeResult determineSwipeHorizontalState(float velocity, SwipeDirectionDetector swipeDirectionDetector, SwipeState swipeState, SwipeLayout.SwipeListener swipeListener, View child) { - for (DraggingEngine dragView : mSwipeViewLayouter.getViewEngines().values()) { - - SwipeResult result = dragView.determineSwipeHorizontalState(velocity, swipeDirectionDetector, swipeState, swipeListener, child); - if (result != null) { - return result; - } - - } - return new SwipeResult(0); - } - - public void initInitialPosition() { - - for (DraggingEngine dragView : mSwipeViewLayouter.getViewEngines().values()) { - dragView.initializePosition(mSwipeViewLayouter.getDragDirection()); - } - } - - public void moveView(View changedView, int positionChanges) { - - for (DraggingEngine engine : mSwipeViewLayouter.getViewEngines().values()) { - engine.moveView(positionChanges, (SurfaceView) mSwipeViewLayouter.getViews().get(SURFACE_VIEW), changedView); - } - - } - - public void restoreState(SwipeState.DragViewState state) { - - for (DraggingEngine view : mSwipeViewLayouter.getViewEngines().values()) { - view.restoreState(state, (SurfaceView) mSwipeViewLayouter.getViews().get(SURFACE_VIEW)); - view.getDragView().forceLayout(); - } - } - - public SwipeViewLayouter.DragDirection getDragDirection() { - return mSwipeViewLayouter.getDragDirection(); - } - - public boolean isCapturedViewDraggable(View child) { - - boolean draggable = false; - - for (View view : mSwipeViewLayouter.getViews().values()) { - - draggable = draggable || child.getId() == view.getId(); - } - - return draggable; - } - - public boolean canSwipe(SwipeDirectionDetector swipeDirectionDetector, SwipeState.DragViewState state) { - - boolean canSwipe = false; - - float absDiffX = Math.abs(swipeDirectionDetector.getDifX()); - float absDiffY = Math.abs(swipeDirectionDetector.getDifY()); - float diffX = swipeDirectionDetector.getDifX(); - float diffY = swipeDirectionDetector.getDifY(); - boolean isLeftDraggable = mSwipeViewLayouter.getDragViewEngineByPosition(LEFT_DRAG_VIEW) != null ? ((DragView)mSwipeViewLayouter.getViews().get(LEFT_DRAG_VIEW)).isDraggable() : false; - boolean isRightDraggable = mSwipeViewLayouter.getDragViewEngineByPosition(RIGHT_DRAG_VIEW) != null ? ((DragView)mSwipeViewLayouter.getViews().get(RIGHT_DRAG_VIEW)).isDraggable() : false; - - if (mSwipeViewLayouter.getDragDirection() == HORIZONTAL) { - if (diffX > 0) { - canSwipe = absDiffX > absDiffY && (isLeftDraggable || mSwipeViewLayouter.getSurfaceView().getX() < 0); - } else { - canSwipe = absDiffX > absDiffY && (isRightDraggable || mSwipeViewLayouter.getSurfaceView().getX() > 0); - } - - } - - return canSwipe; - } - - public boolean isInitilized() { - return isInitilized; - } - - public View getSurfaceView() { - return mSwipeViewLayouter.getSurfaceView(); - } - - public int getSurfaceOpenOffsetByDragView(int dragView) { - return mSwipeViewLayouter.getViewEngines().get(dragView).getOpenOffset(); - } - - public void captureChildrenBound() { - mLayoutCache.captureChildrenBound(mSwipeViewLayouter.getViews().values()); - } - - public void restoreChildrenBound() { - mLayoutCache.restoreOnLayout(); - } -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.kt new file mode 100644 index 0000000..635259c --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/DraggingProxy.kt @@ -0,0 +1,138 @@ +package kaufland.com.swipelibrary + +import android.view.View +import android.view.ViewGroup + +import kaufland.com.swipelibrary.dragengine.DraggingEngine + +import kaufland.com.swipelibrary.SwipeLayout.Companion.LEFT_DRAG_VIEW +import kaufland.com.swipelibrary.SwipeLayout.Companion.RIGHT_DRAG_VIEW +import kaufland.com.swipelibrary.SwipeLayout.Companion.SURFACE_VIEW +import kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.HORIZONTAL + +/** + * Created by sbra0902 on 30.03.17. + */ + +class DraggingProxy { + + + private var mSwipeViewLayouter = SwipeViewLayouter() + + private var mLayoutCache = LayoutCache() + + var isInitilized: Boolean = false + private set + + val dragDirection: SwipeViewLayouter.DragDirection + get() = mSwipeViewLayouter.dragDirection + + val surfaceView: View + get() = mSwipeViewLayouter.surfaceView + + + fun init(parent: ViewGroup) { + isInitilized = true + mSwipeViewLayouter.init(parent) + initInitialPosition() + } + + + fun requestLayout() { + for (dragView in mSwipeViewLayouter.views.values) { + dragView.forceLayout() + } + } + + fun clampViewPositionHorizontal(child: View, left: Int): Int { + + for (dragView in mSwipeViewLayouter.viewEngines.values) { + if (dragView.dragView == child) { + return dragView.clampViewPositionHorizontal(child, left) + } + } + return left + } + + fun determineSwipeHorizontalState(velocity: Float, swipeDirectionDetector: SwipeDirectionDetector, swipeState: SwipeState, swipeListener: SwipeLayout.SwipeListener?, child: View): SwipeResult { + for (dragView in mSwipeViewLayouter.viewEngines.values) { + + val result = dragView.determineSwipeHorizontalState(velocity, swipeDirectionDetector, swipeState, swipeListener, child) + if (result != null) { + return result + } + + } + return SwipeResult(0) + } + + fun initInitialPosition() { + + for (dragView in mSwipeViewLayouter.viewEngines.values) { + dragView.initializePosition(mSwipeViewLayouter.dragDirection) + } + } + + fun moveView(changedView: View, positionChanges: Int) { + + for (engine in mSwipeViewLayouter.viewEngines.values) { + engine.moveView(positionChanges.toFloat(), mSwipeViewLayouter.views[SwipeLayout.SURFACE_VIEW] as SurfaceView, changedView) + } + + } + + fun restoreState(state: SwipeState.DragViewState) { + + for (view in mSwipeViewLayouter.viewEngines.values) { + view.restoreState(state, mSwipeViewLayouter.views[SwipeLayout.SURFACE_VIEW] as SurfaceView) + view.dragView?.forceLayout() + } + } + + fun isCapturedViewDraggable(child: View): Boolean { + + var draggable = false + + for (view in mSwipeViewLayouter.views.values) { + + draggable = draggable || child.id == view.id + } + + return draggable + } + + fun canSwipe(swipeDirectionDetector: SwipeDirectionDetector, state: SwipeState.DragViewState): Boolean { + + var canSwipe = false + + val absDiffX = Math.abs(swipeDirectionDetector.difX).toFloat() + val absDiffY = Math.abs(swipeDirectionDetector.difY).toFloat() + val diffX = swipeDirectionDetector.difX.toFloat() + val diffY = swipeDirectionDetector.difY.toFloat() + val isLeftDraggable = if (mSwipeViewLayouter.DragViewEngineByPosition(SwipeLayout.LEFT_DRAG_VIEW) != null) (mSwipeViewLayouter.views[SwipeLayout.LEFT_DRAG_VIEW] as DragView).isDraggable else false + val isRightDraggable = if (mSwipeViewLayouter.DragViewEngineByPosition(SwipeLayout.RIGHT_DRAG_VIEW) != null) (mSwipeViewLayouter.views[SwipeLayout.RIGHT_DRAG_VIEW] as DragView).isDraggable else false + + if (mSwipeViewLayouter.dragDirection == HORIZONTAL) { + if (diffX > 0) { + canSwipe = absDiffX > absDiffY && (isLeftDraggable || mSwipeViewLayouter.surfaceView.x < 0) + } else { + canSwipe = absDiffX > absDiffY && (isRightDraggable || mSwipeViewLayouter.surfaceView.x > 0) + } + + } + + return canSwipe + } + + fun getSurfaceOpenOffsetByDragView(dragView: Int): Int { + return mSwipeViewLayouter.viewEngines[dragView]!!.openOffset() + } + + fun captureChildrenBound() { + mLayoutCache.captureChildrenBound(mSwipeViewLayouter.views.values) + } + + fun restoreChildrenBound() { + mLayoutCache.restoreOnLayout() + } +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.java deleted file mode 100644 index e99c1b1..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.java +++ /dev/null @@ -1,1315 +0,0 @@ -package kaufland.com.swipelibrary; - -import android.content.Context; -import androidx.core.view.MotionEventCompat; -import androidx.core.view.VelocityTrackerCompat; -import androidx.core.view.ViewCompat; -import androidx.core.widget.ScrollerCompat; -import androidx.customview.widget.ViewDragHelper; -import android.util.Log; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.view.animation.Interpolator; - -import java.util.Arrays; - -/** - * Created by sbra0902 on 17.03.17. - */ - -public class KDragViewHelper { - - private static final String TAG = "ViewDragHelper"; - - /** - * A null/invalid pointer ID. - */ - public static final int INVALID_POINTER = -1; - - /** - * A view is not currently being dragged or animating as a result of a fling/snap. - */ - public static final int STATE_IDLE = 0; - - /** - * A view is currently being dragged. The position is currently changing as a result - * of user input or simulated user input. - */ - public static final int STATE_DRAGGING = 1; - - /** - * A view is currently settling into place as a result of a fling or - * predefined non-interactive motion. - */ - public static final int STATE_SETTLING = 2; - - /** - * Edge flag indicating that the left edge should be affected. - */ - public static final int EDGE_LEFT = 1 << 0; - - /** - * Edge flag indicating that the right edge should be affected. - */ - public static final int EDGE_RIGHT = 1 << 1; - - /** - * Edge flag indicating that the top edge should be affected. - */ - public static final int EDGE_TOP = 1 << 2; - - /** - * Edge flag indicating that the bottom edge should be affected. - */ - public static final int EDGE_BOTTOM = 1 << 3; - - /** - * Edge flag set indicating all edges should be affected. - */ - public static final int EDGE_ALL = EDGE_LEFT | EDGE_TOP | EDGE_RIGHT | EDGE_BOTTOM; - - /** - * Indicates that a check should occur along the horizontal axis - */ - public static final int DIRECTION_HORIZONTAL = 1 << 0; - - /** - * Indicates that a check should occur along the vertical axis - */ - public static final int DIRECTION_VERTICAL = 1 << 1; - - /** - * Indicates that a check should occur along all axes - */ - public static final int DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; - - private static final int EDGE_SIZE = 20; // dp - - private static final int BASE_SETTLE_DURATION = 256; // ms - private static final int MAX_SETTLE_DURATION = 600; // ms - - // Current drag state; idle, dragging or settling - private int mDragState; - - // Distance to travel before a drag may begin - private int mTouchSlop; - - // Last known position/pointer tracking - private int mActivePointerId = INVALID_POINTER; - private float[] mInitialMotionX; - private float[] mInitialMotionY; - private float[] mLastMotionX; - private float[] mLastMotionY; - private int[] mInitialEdgesTouched; - private int[] mEdgeDragsInProgress; - private int[] mEdgeDragsLocked; - private int mPointersDown; - - private VelocityTracker mVelocityTracker; - private float mMaxVelocity; - private float mMinVelocity; - - private int mEdgeSize; - private int mTrackingEdges; - - private ScrollerCompat mScroller; - - private final ViewDragHelper.Callback mCallback; - - private View mCapturedView; - private boolean mReleaseInProgress; - - private final ViewGroup mParentView; - - - /** - * Interpolator defining the animation curve for mScroller - */ - private static final Interpolator sInterpolator = new Interpolator() { - @Override - public float getInterpolation(float t) { - t -= 1.0f; - return t * t * t * t * t + 1.0f; - } - }; - - private final Runnable mSetIdleRunnable = new Runnable() { - @Override - public void run() { - setDragState(STATE_IDLE); - } - }; - - /** - * Factory method to create a new ViewDragHelper. - * - * @param forParent Parent view to monitor - * @param cb Callback to provide information and receive events - * @return a new ViewDragHelper instance - */ - public static KDragViewHelper create(ViewGroup forParent, ViewDragHelper.Callback cb) { - return new KDragViewHelper(forParent.getContext(), forParent, cb); - } - - /** - * Factory method to create a new ViewDragHelper. - * - * @param forParent Parent view to monitor - * @param sensitivity Multiplier for how sensitive the helper should be about detecting - * the start of a drag. Larger values are more sensitive. 1.0f is normal. - * @param cb Callback to provide information and receive events - * @return a new ViewDragHelper instance - */ - public static KDragViewHelper create(ViewGroup forParent, float sensitivity, ViewDragHelper.Callback cb) { - final KDragViewHelper helper = create(forParent, cb); - helper.mTouchSlop = (int) (helper.mTouchSlop * (1 / sensitivity)); - return helper; - } - - /** - * Apps should use ViewDragHelper.create() to get a new instance. - * This will allow VDH to use internal compatibility implementations for different - * platform versions. - * - * @param context Context to initialize config-dependent params from - * @param forParent Parent view to monitor - */ - private KDragViewHelper(Context context, ViewGroup forParent, ViewDragHelper.Callback cb) { - if (forParent == null) { - throw new IllegalArgumentException("Parent view may not be null"); - } - if (cb == null) { - throw new IllegalArgumentException("Callback may not be null"); - } - - mParentView = forParent; - mCallback = cb; - - final ViewConfiguration vc = ViewConfiguration.get(context); - final float density = context.getResources().getDisplayMetrics().density; - mEdgeSize = (int) (EDGE_SIZE * density + 0.5f); - - mTouchSlop = vc.getScaledTouchSlop(); - mMaxVelocity = vc.getScaledMaximumFlingVelocity(); - mMinVelocity = vc.getScaledMinimumFlingVelocity(); - mScroller = ScrollerCompat.create(context, sInterpolator); - } - - /** - * Set the minimum velocity that will be detected as having a magnitude greater than zero - * in pixels per second. Callback methods accepting a velocity will be clamped appropriately. - * - * @param minVel Minimum velocity to detect - */ - public void setMinVelocity(float minVel) { - mMinVelocity = minVel; - } - - /** - * Return the currently configured minimum velocity. Any flings with a magnitude less - * than this value in pixels per second. Callback methods accepting a velocity will receive - * zero as a velocity value if the real detected velocity was below this threshold. - * - * @return the minimum velocity that will be detected - */ - public float getMinVelocity() { - return mMinVelocity; - } - - /** - * Retrieve the current drag state of this helper. This will return one of - * {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}. - * @return The current drag state - */ - public int getViewDragState() { - return mDragState; - } - - /** - * Enable edge tracking for the selected edges of the parent view. - * The callback's {@link ViewDragHelper.Callback#onEdgeTouched(int, int)} and - * {@link ViewDragHelper.Callback#onEdgeDragStarted(int, int)} methods will only be invoked - * for edges for which edge tracking has been enabled. - * - * @param edgeFlags Combination of edge flags describing the edges to watch - * @see #EDGE_LEFT - * @see #EDGE_TOP - * @see #EDGE_RIGHT - * @see #EDGE_BOTTOM - */ - public void setEdgeTrackingEnabled(int edgeFlags) { - mTrackingEdges = edgeFlags; - } - - /** - * Return the size of an edge. This is the range in pixels along the edges of this view - * that will actively detect edge touches or drags if edge tracking is enabled. - * - * @return The size of an edge in pixels - * @see #setEdgeTrackingEnabled(int) - */ - public int getEdgeSize() { - return mEdgeSize; - } - - /** - * Capture a specific child view for dragging within the parent. The callback will be notified - * but {@link ViewDragHelper.Callback#tryCaptureView(android.view.View, int)} will not be asked permission to - * capture this view. - * - * @param childView Child view to capture - * @param activePointerId ID of the pointer that is dragging the captured child view - */ - public void captureChildView(View childView, int activePointerId) { - if (childView.getParent() != mParentView) { - throw new IllegalArgumentException("captureChildView: parameter must be a descendant " - + "of the ViewDragHelper's tracked parent view (" + mParentView + ")"); - } - - mCapturedView = childView; - mActivePointerId = activePointerId; - mCallback.onViewCaptured(childView, activePointerId); - setDragState(STATE_DRAGGING); - } - - /** - * @return The currently captured view, or null if no view has been captured. - */ - public View getCapturedView() { - return mCapturedView; - } - - /** - * @return The ID of the pointer currently dragging the captured view, - * or {@link #INVALID_POINTER}. - */ - public int getActivePointerId() { - return mActivePointerId; - } - - /** - * @return The minimum distance in pixels that the user must travel to initiate a drag - */ - public int getTouchSlop() { - return mTouchSlop; - } - - /** - * The result of a call to this method is equivalent to - * {@link #processTouchEvent(android.view.MotionEvent)} receiving an ACTION_CANCEL event. - */ - public void cancel() { - mActivePointerId = INVALID_POINTER; - clearMotionHistory(); - - if (mVelocityTracker != null) { - mVelocityTracker.recycle(); - mVelocityTracker = null; - } - } - - /** - * {@link #cancel()}, but also abort all motion in progress and snap to the end of any - * animation. - */ - public void abort() { - cancel(); - if (mDragState == STATE_SETTLING) { - final int oldX = mScroller.getCurrX(); - final int oldY = mScroller.getCurrY(); - mScroller.abortAnimation(); - final int newX = mScroller.getCurrX(); - final int newY = mScroller.getCurrY(); - mCallback.onViewPositionChanged(mCapturedView, newX, newY, newX - oldX, newY - oldY); - } - setDragState(STATE_IDLE); - } - - /** - * Animate the view child to the given (left, top) position. - * If this method returns true, the caller should invoke {@link #continueSettling(boolean)} - * on each subsequent frame to continue the motion until it returns false. If this method - * returns false there is no further work to do to complete the movement. - * - *

This operation does not count as a capture event, though {@link #getCapturedView()} - * will still report the sliding view while the slide is in progress.

- * - * @param child Child view to capture and animate - * @param finalLeft Final left position of child - * @param finalTop Final top position of child - * @return true if animation should continue through {@link #continueSettling(boolean)} calls - */ - public boolean smoothSlideViewTo(View child, int finalLeft, int finalTop) { - mCapturedView = child; - mActivePointerId = INVALID_POINTER; - - boolean continueSliding = forceSettleCapturedViewAt(finalLeft, finalTop, 0, 0); - if (!continueSliding && mDragState == STATE_IDLE && mCapturedView != null) { - // If we're in an IDLE state to begin with and aren't moving anywhere, we - // end up having a non-null capturedView with an IDLE dragState - mCapturedView = null; - } - - return continueSliding; - } - - /** - * Settle the captured view at the given (left, top) position. - * The appropriate velocity from prior motion will be taken into account. - * If this method returns true, the caller should invoke {@link #continueSettling(boolean)} - * on each subsequent frame to continue the motion until it returns false. If this method - * returns false there is no further work to do to complete the movement. - * - * @param finalLeft Settled left edge position for the captured view - * @param finalTop Settled top edge position for the captured view - * @return true if animation should continue through {@link #continueSettling(boolean)} calls - */ - public boolean settleCapturedViewAt(int finalLeft, int finalTop) { - if (!mReleaseInProgress) { - throw new IllegalStateException("Cannot settleCapturedViewAt outside of a call to " - + "Callback#onViewReleased"); - } - - return forceSettleCapturedViewAt(finalLeft, finalTop, - (int) VelocityTrackerCompat.getXVelocity(mVelocityTracker, mActivePointerId), - (int) VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId)); - } - - /** - * Settle the captured view at the given (left, top) position. - * - * @param finalLeft Target left position for the captured view - * @param finalTop Target top position for the captured view - * @param xvel Horizontal velocity - * @param yvel Vertical velocity - * @return true if animation should continue through {@link #continueSettling(boolean)} calls - */ - private boolean forceSettleCapturedViewAt(int finalLeft, int finalTop, int xvel, int yvel) { - final int startLeft = (int) mCapturedView.getX(); - final int startTop = (int) mCapturedView.getY(); - final int dx = finalLeft - startLeft; - final int dy = finalTop - startTop; - - if (dx == 0 && dy == 0) { - // Nothing to do. Send callbacks, be done. - mScroller.abortAnimation(); - setDragState(STATE_IDLE); - return false; - } - - final int duration = computeSettleDuration(mCapturedView, dx, dy, xvel, yvel); - mScroller.startScroll(startLeft, startTop, dx, dy, duration); - - setDragState(STATE_SETTLING); - return true; - } - - private int computeSettleDuration(View child, int dx, int dy, int xvel, int yvel) { - xvel = clampMag(xvel, (int) mMinVelocity, (int) mMaxVelocity); - yvel = clampMag(yvel, (int) mMinVelocity, (int) mMaxVelocity); - final int absDx = Math.abs(dx); - final int absDy = Math.abs(dy); - final int absXVel = Math.abs(xvel); - final int absYVel = Math.abs(yvel); - final int addedVel = absXVel + absYVel; - final int addedDistance = absDx + absDy; - - final float xweight = xvel != 0 ? (float) absXVel / addedVel : - (float) absDx / addedDistance; - final float yweight = yvel != 0 ? (float) absYVel / addedVel : - (float) absDy / addedDistance; - - int xduration = computeAxisDuration(dx, xvel, mCallback.getViewHorizontalDragRange(child)); - int yduration = computeAxisDuration(dy, yvel, mCallback.getViewVerticalDragRange(child)); - - return (int) (xduration * xweight + yduration * yweight); - } - - private int computeAxisDuration(int delta, int velocity, int motionRange) { - if (delta == 0) { - return 0; - } - - final int width = mParentView.getWidth(); - final int halfWidth = width / 2; - final float distanceRatio = Math.min(1f, (float) Math.abs(delta) / width); - final float distance = halfWidth + halfWidth - * distanceInfluenceForSnapDuration(distanceRatio); - - int duration; - velocity = Math.abs(velocity); - if (velocity > 0) { - duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); - } else { - final float range = (float) Math.abs(delta) / motionRange; - duration = (int) ((range + 1) * BASE_SETTLE_DURATION); - } - return Math.min(duration, MAX_SETTLE_DURATION); - } - - /** - * Clamp the magnitude of value for absMin and absMax. - * If the value is below the minimum, it will be clamped to zero. - * If the value is above the maximum, it will be clamped to the maximum. - * - * @param value Value to clamp - * @param absMin Absolute value of the minimum significant value to return - * @param absMax Absolute value of the maximum value to return - * @return The clamped value with the same sign as value - */ - private int clampMag(int value, int absMin, int absMax) { - final int absValue = Math.abs(value); - if (absValue < absMin) return 0; - if (absValue > absMax) return value > 0 ? absMax : -absMax; - return value; - } - - /** - * Clamp the magnitude of value for absMin and absMax. - * If the value is below the minimum, it will be clamped to zero. - * If the value is above the maximum, it will be clamped to the maximum. - * - * @param value Value to clamp - * @param absMin Absolute value of the minimum significant value to return - * @param absMax Absolute value of the maximum value to return - * @return The clamped value with the same sign as value - */ - private float clampMag(float value, float absMin, float absMax) { - final float absValue = Math.abs(value); - if (absValue < absMin) return 0; - if (absValue > absMax) return value > 0 ? absMax : -absMax; - return value; - } - - private float distanceInfluenceForSnapDuration(float f) { - f -= 0.5f; // center the values about 0. - f *= 0.3f * Math.PI / 2.0f; - return (float) Math.sin(f); - } - - /** - * Settle the captured view based on standard free-moving fling behavior. - * The caller should invoke {@link #continueSettling(boolean)} on each subsequent frame - * to continue the motion until it returns false. - * - * @param minLeft Minimum X position for the view's left edge - * @param minTop Minimum Y position for the view's top edge - * @param maxLeft Maximum X position for the view's left edge - * @param maxTop Maximum Y position for the view's top edge - */ - public void flingCapturedView(int minLeft, int minTop, int maxLeft, int maxTop) { - if (!mReleaseInProgress) { - throw new IllegalStateException("Cannot flingCapturedView outside of a call to " - + "Callback#onViewReleased"); - } - - mScroller.fling((int) mCapturedView.getX(), (int) mCapturedView.getY(), - (int) VelocityTrackerCompat.getXVelocity(mVelocityTracker, mActivePointerId), - (int) VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId), - minLeft, maxLeft, minTop, maxTop); - - setDragState(STATE_SETTLING); - } - - /** - * Move the captured settling view by the appropriate amount for the current time. - * If continueSettling returns true, the caller should call it again - * on the next frame to continue. - * - * @param deferCallbacks true if state callbacks should be deferred via posted message. - * Set this to true if you are calling this method from - * {@link android.view.View#computeScroll()} or similar methods - * invoked as part of layout or drawing. - * @return true if settle is still in progress - */ - public boolean continueSettling(boolean deferCallbacks) { - if (mDragState == STATE_SETTLING) { - boolean keepGoing = mScroller.computeScrollOffset(); - final int x = mScroller.getCurrX(); - final int y = mScroller.getCurrY(); - final int dx = (int) (x - mCapturedView.getX()); - final int dy = (int) (y - mCapturedView.getY()); - - if (dx != 0) { - ViewCompat.offsetLeftAndRight(mCapturedView, dx); - } - if (dy != 0) { - ViewCompat.offsetTopAndBottom(mCapturedView, dy); - } - - if (dx != 0 || dy != 0) { - mCallback.onViewPositionChanged(mCapturedView, x, y, dx, dy); - } - - if (keepGoing && x == mScroller.getFinalX() && y == mScroller.getFinalY()) { - // Close enough. The interpolator/scroller might think we're still moving - // but the user sure doesn't. - mScroller.abortAnimation(); - keepGoing = false; - } - - if (!keepGoing) { - if (deferCallbacks) { - mParentView.post(mSetIdleRunnable); - } else { - setDragState(STATE_IDLE); - } - } - } - - return mDragState == STATE_SETTLING; - } - - /** - * Like all callback events this must happen on the UI thread, but release - * involves some extra semantics. During a release (mReleaseInProgress) - * is the only time it is valid to call {@link #settleCapturedViewAt(int, int)} - * or {@link #flingCapturedView(int, int, int, int)}. - */ - private void dispatchViewReleased(float xvel, float yvel) { - mReleaseInProgress = true; - mCallback.onViewReleased(mCapturedView, xvel, yvel); - mReleaseInProgress = false; - - if (mDragState == STATE_DRAGGING) { - // onViewReleased didn't call a method that would have changed this. Go idle. - setDragState(STATE_IDLE); - } - } - - private void clearMotionHistory() { - if (mInitialMotionX == null) { - return; - } - Arrays.fill(mInitialMotionX, 0); - Arrays.fill(mInitialMotionY, 0); - Arrays.fill(mLastMotionX, 0); - Arrays.fill(mLastMotionY, 0); - Arrays.fill(mInitialEdgesTouched, 0); - Arrays.fill(mEdgeDragsInProgress, 0); - Arrays.fill(mEdgeDragsLocked, 0); - mPointersDown = 0; - } - - private void clearMotionHistory(int pointerId) { - if (mInitialMotionX == null || !isPointerDown(pointerId)) { - return; - } - mInitialMotionX[pointerId] = 0; - mInitialMotionY[pointerId] = 0; - mLastMotionX[pointerId] = 0; - mLastMotionY[pointerId] = 0; - mInitialEdgesTouched[pointerId] = 0; - mEdgeDragsInProgress[pointerId] = 0; - mEdgeDragsLocked[pointerId] = 0; - mPointersDown &= ~(1 << pointerId); - } - - private void ensureMotionHistorySizeForId(int pointerId) { - if (mInitialMotionX == null || mInitialMotionX.length <= pointerId) { - float[] imx = new float[pointerId + 1]; - float[] imy = new float[pointerId + 1]; - float[] lmx = new float[pointerId + 1]; - float[] lmy = new float[pointerId + 1]; - int[] iit = new int[pointerId + 1]; - int[] edip = new int[pointerId + 1]; - int[] edl = new int[pointerId + 1]; - - if (mInitialMotionX != null) { - System.arraycopy(mInitialMotionX, 0, imx, 0, mInitialMotionX.length); - System.arraycopy(mInitialMotionY, 0, imy, 0, mInitialMotionY.length); - System.arraycopy(mLastMotionX, 0, lmx, 0, mLastMotionX.length); - System.arraycopy(mLastMotionY, 0, lmy, 0, mLastMotionY.length); - System.arraycopy(mInitialEdgesTouched, 0, iit, 0, mInitialEdgesTouched.length); - System.arraycopy(mEdgeDragsInProgress, 0, edip, 0, mEdgeDragsInProgress.length); - System.arraycopy(mEdgeDragsLocked, 0, edl, 0, mEdgeDragsLocked.length); - } - - mInitialMotionX = imx; - mInitialMotionY = imy; - mLastMotionX = lmx; - mLastMotionY = lmy; - mInitialEdgesTouched = iit; - mEdgeDragsInProgress = edip; - mEdgeDragsLocked = edl; - } - } - - private void saveInitialMotion(float x, float y, int pointerId) { - ensureMotionHistorySizeForId(pointerId); - mInitialMotionX[pointerId] = mLastMotionX[pointerId] = x; - mInitialMotionY[pointerId] = mLastMotionY[pointerId] = y; - mInitialEdgesTouched[pointerId] = getEdgesTouched((int) x, (int) y); - mPointersDown |= 1 << pointerId; - } - - private void saveLastMotion(MotionEvent ev) { - final int pointerCount = ev.getPointerCount(); - for (int i = 0; i < pointerCount; i++) { - final int pointerId = ev.getPointerId(i); - // If pointer is invalid then skip saving on ACTION_MOVE. - if (!isValidPointerForActionMove(pointerId)) { - continue; - } - final float x = ev.getX(i); - final float y = ev.getY(i); - mLastMotionX[pointerId] = x; - mLastMotionY[pointerId] = y; - } - } - - /** - * Check if the given pointer ID represents a pointer that is currently down (to the best - * of the ViewDragHelper's knowledge). - * - *

The state used to report this information is populated by the methods - * {@link #shouldInterceptTouchEvent(android.view.MotionEvent)} or - * {@link #processTouchEvent(android.view.MotionEvent)}. If one of these methods has not - * been called for all relevant MotionEvents to track, the information reported - * by this method may be stale or incorrect.

- * - * @param pointerId pointer ID to check; corresponds to IDs provided by MotionEvent - * @return true if the pointer with the given ID is still down - */ - public boolean isPointerDown(int pointerId) { - return (mPointersDown & 1 << pointerId) != 0; - } - - void setDragState(int state) { - mParentView.removeCallbacks(mSetIdleRunnable); - if (mDragState != state) { - mDragState = state; - mCallback.onViewDragStateChanged(state); - if (mDragState == STATE_IDLE) { - mCapturedView = null; - } - } - } - - /** - * Attempt to capture the view with the given pointer ID. The callback will be involved. - * This will put us into the "dragging" state. If we've already captured this view with - * this pointer this method will immediately return true without consulting the callback. - * - * @param toCapture View to capture - * @param pointerId Pointer to capture with - * @return true if capture was successful - */ - boolean tryCaptureViewForDrag(View toCapture, int pointerId) { - if (toCapture == mCapturedView && mActivePointerId == pointerId) { - // Already done! - return true; - } - if (toCapture != null && mCallback.tryCaptureView(toCapture, pointerId)) { - mActivePointerId = pointerId; - captureChildView(toCapture, pointerId); - return true; - } - return false; - } - - /** - * Tests scrollability within child views of v given a delta of dx. - * - * @param v View to test for horizontal scrollability - * @param checkV Whether the view v passed should itself be checked for scrollability (true), - * or just its children (false). - * @param dx Delta scrolled in pixels along the X axis - * @param dy Delta scrolled in pixels along the Y axis - * @param x X coordinate of the active touch point - * @param y Y coordinate of the active touch point - * @return true if child views of v can be scrolled by delta of dx. - */ - protected boolean canScroll(View v, boolean checkV, int dx, int dy, int x, int y) { - if (v instanceof ViewGroup) { - final ViewGroup group = (ViewGroup) v; - final int scrollX = v.getScrollX(); - final int scrollY = v.getScrollY(); - final int count = group.getChildCount(); - // Count backwards - let topmost views consume scroll distance first. - for (int i = count - 1; i >= 0; i--) { - // TODO: Add versioned support here for transformed views. - // This will not work for transformed views in Honeycomb+ - final View child = group.getChildAt(i); - if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() - && y + scrollY >= child.getTop() && y + scrollY < child.getBottom() - && canScroll(child, true, dx, dy, x + scrollX - child.getLeft(), - y + scrollY - child.getTop())) { - return true; - } - } - } - - return checkV && (ViewCompat.canScrollHorizontally(v, -dx) - || ViewCompat.canScrollVertically(v, -dy)); - } - - /** - * Check if this event as provided to the parent view's onInterceptTouchEvent should - * cause the parent to intercept the touch event stream. - * - * @param ev MotionEvent provided to onInterceptTouchEvent - * @return true if the parent view should return true from onInterceptTouchEvent - */ - public boolean shouldInterceptTouchEvent(MotionEvent ev) { - final int action = MotionEventCompat.getActionMasked(ev); - final int actionIndex = MotionEventCompat.getActionIndex(ev); - - if (action == MotionEvent.ACTION_DOWN) { - // Reset things for a new event stream, just in case we didn't get - // the whole previous stream. - cancel(); - } - - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - mVelocityTracker.addMovement(ev); - - switch (action) { - case MotionEvent.ACTION_DOWN: { - final float x = ev.getX(); - final float y = ev.getY(); - final int pointerId = ev.getPointerId(0); - saveInitialMotion(x, y, pointerId); - - final View toCapture = findTopChildUnder((int) x, (int) y); - - // Catch a settling view if possible. - if (toCapture == mCapturedView && mDragState == STATE_SETTLING) { - tryCaptureViewForDrag(toCapture, pointerId); - } - - final int edgesTouched = mInitialEdgesTouched[pointerId]; - if ((edgesTouched & mTrackingEdges) != 0) { - mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId); - } - break; - } - - case MotionEventCompat.ACTION_POINTER_DOWN: { - final int pointerId = ev.getPointerId(actionIndex); - final float x = ev.getX(actionIndex); - final float y = ev.getY(actionIndex); - - saveInitialMotion(x, y, pointerId); - - // A ViewDragHelper can only manipulate one view at a time. - if (mDragState == STATE_IDLE) { - final int edgesTouched = mInitialEdgesTouched[pointerId]; - if ((edgesTouched & mTrackingEdges) != 0) { - mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId); - } - } else if (mDragState == STATE_SETTLING) { - // Catch a settling view if possible. - final View toCapture = findTopChildUnder((int) x, (int) y); - if (toCapture == mCapturedView) { - tryCaptureViewForDrag(toCapture, pointerId); - } - } - break; - } - - case MotionEvent.ACTION_MOVE: { - if (mInitialMotionX == null || mInitialMotionY == null) break; - - // First to cross a touch slop over a draggable view wins. Also report edge drags. - final int pointerCount = ev.getPointerCount(); - for (int i = 0; i < pointerCount; i++) { - final int pointerId = ev.getPointerId(i); - - // If pointer is invalid then skip the ACTION_MOVE. - if (!isValidPointerForActionMove(pointerId)) continue; - - final float x = ev.getX(i); - final float y = ev.getY(i); - final float dx = x - mInitialMotionX[pointerId]; - final float dy = y - mInitialMotionY[pointerId]; - - final View toCapture = findTopChildUnder((int) x, (int) y); - final boolean pastSlop = toCapture != null && checkTouchSlop(toCapture, dx, dy); - if (pastSlop) { - // check the callback's - // getView[Horizontal|Vertical]DragRange methods to know - // if you can move at all along an axis, then see if it - // would clamp to the same value. If you can't move at - // all in every dimension with a nonzero range, bail. - final int oldLeft = (int) toCapture.getX(); - final int targetLeft = oldLeft + (int) dx; - final int newLeft = mCallback.clampViewPositionHorizontal(toCapture, - targetLeft, (int) dx); - final int oldTop = toCapture.getTop(); - final int targetTop = oldTop + (int) dy; - final int newTop = mCallback.clampViewPositionVertical(toCapture, targetTop, - (int) dy); - final int horizontalDragRange = mCallback.getViewHorizontalDragRange( - toCapture); - final int verticalDragRange = mCallback.getViewVerticalDragRange(toCapture); - if ((horizontalDragRange == 0 || horizontalDragRange > 0 - && newLeft == oldLeft) && (verticalDragRange == 0 - || verticalDragRange > 0 && newTop == oldTop)) { - break; - } - } - reportNewEdgeDrags(dx, dy, pointerId); - if (mDragState == STATE_DRAGGING) { - // Callback might have started an edge drag - break; - } - - if (pastSlop && tryCaptureViewForDrag(toCapture, pointerId)) { - break; - } - } - saveLastMotion(ev); - break; - } - - case MotionEventCompat.ACTION_POINTER_UP: { - final int pointerId = ev.getPointerId(actionIndex); - clearMotionHistory(pointerId); - break; - } - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: { - cancel(); - break; - } - } - - return mDragState == STATE_DRAGGING; - } - - /** - * Process a touch event received by the parent view. This method will dispatch callback events - * as needed before returning. The parent view's onTouchEvent implementation should call this. - * - * @param ev The touch event received by the parent view - */ - public void processTouchEvent(MotionEvent ev) { - final int action = MotionEventCompat.getActionMasked(ev); - final int actionIndex = MotionEventCompat.getActionIndex(ev); - - if (action == MotionEvent.ACTION_DOWN) { - // Reset things for a new event stream, just in case we didn't get - // the whole previous stream. - cancel(); - } - - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - mVelocityTracker.addMovement(ev); - - switch (action) { - case MotionEvent.ACTION_DOWN: { - final float x = ev.getX(); - final float y = ev.getY(); - final int pointerId = ev.getPointerId(0); - final View toCapture = findTopChildUnder((int) x, (int) y); - - saveInitialMotion(x, y, pointerId); - - // Since the parent is already directly processing this touch event, - // there is no reason to delay for a slop before dragging. - // Start immediately if possible. - tryCaptureViewForDrag(toCapture, pointerId); - - final int edgesTouched = mInitialEdgesTouched[pointerId]; - if ((edgesTouched & mTrackingEdges) != 0) { - mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId); - } - break; - } - - case MotionEventCompat.ACTION_POINTER_DOWN: { - final int pointerId = ev.getPointerId(actionIndex); - final float x = ev.getX(actionIndex); - final float y = ev.getY(actionIndex); - - saveInitialMotion(x, y, pointerId); - - // A ViewDragHelper can only manipulate one view at a time. - if (mDragState == STATE_IDLE) { - // If we're idle we can do anything! Treat it like a normal down event. - - final View toCapture = findTopChildUnder((int) x, (int) y); - tryCaptureViewForDrag(toCapture, pointerId); - - final int edgesTouched = mInitialEdgesTouched[pointerId]; - if ((edgesTouched & mTrackingEdges) != 0) { - mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId); - } - } else if (isCapturedViewUnder((int) x, (int) y)) { - // We're still tracking a captured view. If the same view is under this - // point, we'll swap to controlling it with this pointer instead. - // (This will still work if we're "catching" a settling view.) - - tryCaptureViewForDrag(mCapturedView, pointerId); - } - break; - } - - case MotionEvent.ACTION_MOVE: { - if (mDragState == STATE_DRAGGING) { - // If pointer is invalid then skip the ACTION_MOVE. - if (!isValidPointerForActionMove(mActivePointerId)) break; - - final int index = ev.findPointerIndex(mActivePointerId); - final float x = ev.getX(index); - final float y = ev.getY(index); - final int idx = (int) (x - mLastMotionX[mActivePointerId]); - final int idy = (int) (y - mLastMotionY[mActivePointerId]); - - dragTo((int) (mCapturedView.getX() + idx), (int) (mCapturedView.getY() + idy), idx, idy); - - saveLastMotion(ev); - } else { - // Check to see if any pointer is now over a draggable view. - final int pointerCount = ev.getPointerCount(); - for (int i = 0; i < pointerCount; i++) { - final int pointerId = ev.getPointerId(i); - - // If pointer is invalid then skip the ACTION_MOVE. - if (!isValidPointerForActionMove(pointerId)) continue; - - final float x = ev.getX(i); - final float y = ev.getY(i); - final float dx = x - mInitialMotionX[pointerId]; - final float dy = y - mInitialMotionY[pointerId]; - - reportNewEdgeDrags(dx, dy, pointerId); - if (mDragState == STATE_DRAGGING) { - // Callback might have started an edge drag. - break; - } - - final View toCapture = findTopChildUnder((int) x, (int) y); - if (checkTouchSlop(toCapture, dx, dy) - && tryCaptureViewForDrag(toCapture, pointerId)) { - break; - } - } - saveLastMotion(ev); - } - break; - } - - case MotionEventCompat.ACTION_POINTER_UP: { - final int pointerId = ev.getPointerId(actionIndex); - if (mDragState == STATE_DRAGGING && pointerId == mActivePointerId) { - // Try to find another pointer that's still holding on to the captured view. - int newActivePointer = INVALID_POINTER; - final int pointerCount = ev.getPointerCount(); - for (int i = 0; i < pointerCount; i++) { - final int id = ev.getPointerId(i); - if (id == mActivePointerId) { - // This one's going away, skip. - continue; - } - - final float x = ev.getX(i); - final float y = ev.getY(i); - if (findTopChildUnder((int) x, (int) y) == mCapturedView - && tryCaptureViewForDrag(mCapturedView, id)) { - newActivePointer = mActivePointerId; - break; - } - } - - if (newActivePointer == INVALID_POINTER) { - // We didn't find another pointer still touching the view, release it. - releaseViewForPointerUp(); - } - } - clearMotionHistory(pointerId); - break; - } - - case MotionEvent.ACTION_UP: { - if (mDragState == STATE_DRAGGING) { - releaseViewForPointerUp(); - } - cancel(); - break; - } - - case MotionEvent.ACTION_CANCEL: { - if (mDragState == STATE_DRAGGING) { - dispatchViewReleased(0, 0); - } - cancel(); - break; - } - } - } - - private void reportNewEdgeDrags(float dx, float dy, int pointerId) { - int dragsStarted = 0; - if (checkNewEdgeDrag(dx, dy, pointerId, EDGE_LEFT)) { - dragsStarted |= EDGE_LEFT; - } - if (checkNewEdgeDrag(dy, dx, pointerId, EDGE_TOP)) { - dragsStarted |= EDGE_TOP; - } - if (checkNewEdgeDrag(dx, dy, pointerId, EDGE_RIGHT)) { - dragsStarted |= EDGE_RIGHT; - } - if (checkNewEdgeDrag(dy, dx, pointerId, EDGE_BOTTOM)) { - dragsStarted |= EDGE_BOTTOM; - } - - if (dragsStarted != 0) { - mEdgeDragsInProgress[pointerId] |= dragsStarted; - mCallback.onEdgeDragStarted(dragsStarted, pointerId); - } - } - - private boolean checkNewEdgeDrag(float delta, float odelta, int pointerId, int edge) { - final float absDelta = Math.abs(delta); - final float absODelta = Math.abs(odelta); - - if ((mInitialEdgesTouched[pointerId] & edge) != edge || (mTrackingEdges & edge) == 0 - || (mEdgeDragsLocked[pointerId] & edge) == edge - || (mEdgeDragsInProgress[pointerId] & edge) == edge - || (absDelta <= mTouchSlop && absODelta <= mTouchSlop)) { - return false; - } - if (absDelta < absODelta * 0.5f && mCallback.onEdgeLock(edge)) { - mEdgeDragsLocked[pointerId] |= edge; - return false; - } - return (mEdgeDragsInProgress[pointerId] & edge) == 0 && absDelta > mTouchSlop; - } - - /** - * Check if we've crossed a reasonable touch slop for the given child view. - * If the child cannot be dragged along the horizontal or vertical axis, motion - * along that axis will not count toward the slop check. - * - * @param child Child to check - * @param dx Motion since initial position along X axis - * @param dy Motion since initial position along Y axis - * @return true if the touch slop has been crossed - */ - private boolean checkTouchSlop(View child, float dx, float dy) { - if (child == null) { - return false; - } - final boolean checkHorizontal = mCallback.getViewHorizontalDragRange(child) > 0; - final boolean checkVertical = mCallback.getViewVerticalDragRange(child) > 0; - - if (checkHorizontal && checkVertical) { - return dx * dx + dy * dy > mTouchSlop * mTouchSlop; - } else if (checkHorizontal) { - return Math.abs(dx) > mTouchSlop; - } else if (checkVertical) { - return Math.abs(dy) > mTouchSlop; - } - return false; - } - - /** - * Check if any pointer tracked in the current gesture has crossed - * the required slop threshold. - * - *

This depends on internal state populated by - * {@link #shouldInterceptTouchEvent(android.view.MotionEvent)} or - * {@link #processTouchEvent(android.view.MotionEvent)}. You should only rely on - * the results of this method after all currently available touch data - * has been provided to one of these two methods.

- * - * @param directions Combination of direction flags, see {@link #DIRECTION_HORIZONTAL}, - * {@link #DIRECTION_VERTICAL}, {@link #DIRECTION_ALL} - * @return true if the slop threshold has been crossed, false otherwise - */ - public boolean checkTouchSlop(int directions) { - final int count = mInitialMotionX.length; - for (int i = 0; i < count; i++) { - if (checkTouchSlop(directions, i)) { - return true; - } - } - return false; - } - - /** - * Check if the specified pointer tracked in the current gesture has crossed - * the required slop threshold. - * - *

This depends on internal state populated by - * {@link #shouldInterceptTouchEvent(android.view.MotionEvent)} or - * {@link #processTouchEvent(android.view.MotionEvent)}. You should only rely on - * the results of this method after all currently available touch data - * has been provided to one of these two methods.

- * - * @param directions Combination of direction flags, see {@link #DIRECTION_HORIZONTAL}, - * {@link #DIRECTION_VERTICAL}, {@link #DIRECTION_ALL} - * @param pointerId ID of the pointer to slop check as specified by MotionEvent - * @return true if the slop threshold has been crossed, false otherwise - */ - public boolean checkTouchSlop(int directions, int pointerId) { - if (!isPointerDown(pointerId)) { - return false; - } - - final boolean checkHorizontal = (directions & DIRECTION_HORIZONTAL) == DIRECTION_HORIZONTAL; - final boolean checkVertical = (directions & DIRECTION_VERTICAL) == DIRECTION_VERTICAL; - - final float dx = mLastMotionX[pointerId] - mInitialMotionX[pointerId]; - final float dy = mLastMotionY[pointerId] - mInitialMotionY[pointerId]; - - if (checkHorizontal && checkVertical) { - return dx * dx + dy * dy > mTouchSlop * mTouchSlop; - } else if (checkHorizontal) { - return Math.abs(dx) > mTouchSlop; - } else if (checkVertical) { - return Math.abs(dy) > mTouchSlop; - } - return false; - } - - /** - * Check if any of the edges specified were initially touched in the currently active gesture. - * If there is no currently active gesture this method will return false. - * - * @param edges Edges to check for an initial edge touch. See {@link #EDGE_LEFT}, - * {@link #EDGE_TOP}, {@link #EDGE_RIGHT}, {@link #EDGE_BOTTOM} and - * {@link #EDGE_ALL} - * @return true if any of the edges specified were initially touched in the current gesture - */ - public boolean isEdgeTouched(int edges) { - final int count = mInitialEdgesTouched.length; - for (int i = 0; i < count; i++) { - if (isEdgeTouched(edges, i)) { - return true; - } - } - return false; - } - - /** - * Check if any of the edges specified were initially touched by the pointer with - * the specified ID. If there is no currently active gesture or if there is no pointer with - * the given ID currently down this method will return false. - * - * @param edges Edges to check for an initial edge touch. See {@link #EDGE_LEFT}, - * {@link #EDGE_TOP}, {@link #EDGE_RIGHT}, {@link #EDGE_BOTTOM} and - * {@link #EDGE_ALL} - * @return true if any of the edges specified were initially touched in the current gesture - */ - public boolean isEdgeTouched(int edges, int pointerId) { - return isPointerDown(pointerId) && (mInitialEdgesTouched[pointerId] & edges) != 0; - } - - private void releaseViewForPointerUp() { - mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity); - final float xvel = clampMag( - VelocityTrackerCompat.getXVelocity(mVelocityTracker, mActivePointerId), - mMinVelocity, mMaxVelocity); - final float yvel = clampMag( - VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId), - mMinVelocity, mMaxVelocity); - dispatchViewReleased(xvel, yvel); - } - - private void dragTo(int left, int top, int dx, int dy) { - int clampedX = left; - int clampedY = top; - final int oldLeft = (int) mCapturedView.getX(); - final int oldTop = (int) mCapturedView.getY(); - if (dx != 0) { - clampedX = mCallback.clampViewPositionHorizontal(mCapturedView, left, dx); - ViewCompat.offsetLeftAndRight(mCapturedView, clampedX - oldLeft); - } - if (dy != 0) { - clampedY = mCallback.clampViewPositionVertical(mCapturedView, top, dy); - ViewCompat.offsetTopAndBottom(mCapturedView, clampedY - oldTop); - } - - if (dx != 0 || dy != 0) { - final int clampedDx = clampedX - oldLeft; - final int clampedDy = clampedY - oldTop; - mCallback.onViewPositionChanged(mCapturedView, clampedX, clampedY, - clampedDx, clampedDy); - } - } - - /** - * Determine if the currently captured view is under the given point in the - * parent view's coordinate system. If there is no captured view this method - * will return false. - * - * @param x X position to test in the parent's coordinate system - * @param y Y position to test in the parent's coordinate system - * @return true if the captured view is under the given point, false otherwise - */ - public boolean isCapturedViewUnder(int x, int y) { - return isViewUnder(mCapturedView, x, y); - } - - /** - * Determine if the supplied view is under the given point in the - * parent view's coordinate system. - * - * @param view Child view of the parent to hit test - * @param x X position to test in the parent's coordinate system - * @param y Y position to test in the parent's coordinate system - * @return true if the supplied view is under the given point, false otherwise - */ - public boolean isViewUnder(View view, int x, int y) { - if (view == null) { - return false; - } - return x >= view.getX() - && x < view.getX() + view.getWidth() - && y >= view.getY() - && y < view.getY() + view.getHeight(); - } - - /** - * Find the topmost child under the given point within the parent view's coordinate system. - * The child order is determined using {@link ViewDragHelper.Callback#getOrderedChildIndex(int)}. - * - * @param x X position to test in the parent's coordinate system - * @param y Y position to test in the parent's coordinate system - * @return The topmost child view under (x, y) or null if none found. - */ - public View findTopChildUnder(int x, int y) { - final int childCount = mParentView.getChildCount(); - for (int i = childCount - 1; i >= 0; i--) { - final View child = mParentView.getChildAt(mCallback.getOrderedChildIndex(i)); - if (x >= child.getX() && x < child.getX() + child.getWidth() - && y >= child.getY() && y < child.getY() + child.getHeight()) { - return child; - } - } - return null; - } - - private int getEdgesTouched(int x, int y) { - int result = 0; - - if (x < mParentView.getX() + mEdgeSize) result |= EDGE_LEFT; - if (y < mParentView.getY() + mEdgeSize) result |= EDGE_TOP; - if (x > mParentView.getX() + mParentView.getWidth() - mEdgeSize) result |= EDGE_RIGHT; - if (y > mParentView.getY() + mParentView.getHeight() - mEdgeSize) result |= EDGE_BOTTOM; - - return result; - } - - private boolean isValidPointerForActionMove(int pointerId) { - if (!isPointerDown(pointerId)) { - Log.e(TAG, "Ignoring pointerId=" + pointerId + " because ACTION_DOWN was not received " - + "for this pointer before ACTION_MOVE. It likely happened because " - + " ViewDragHelper did not receive all the events in the event stream."); - return false; - } - return true; - } - -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.kt new file mode 100644 index 0000000..70c2b1f --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/KDragViewHelper.kt @@ -0,0 +1,1285 @@ +package kaufland.com.swipelibrary + +import android.content.Context +import androidx.core.view.MotionEventCompat +import androidx.core.view.VelocityTrackerCompat +import androidx.core.view.ViewCompat +import androidx.core.widget.ScrollerCompat +import androidx.customview.widget.ViewDragHelper +import android.util.Log +import android.view.MotionEvent +import android.view.VelocityTracker +import android.view.View +import android.view.ViewConfiguration +import android.view.ViewGroup +import android.view.animation.Interpolator + +import java.util.Arrays + +/** + * Created by sbra0902 on 17.03.17. + */ + +class KDragViewHelper +/** + * Apps should use ViewDragHelper.create() to get a new instance. + * This will allow VDH to use internal compatibility implementations for different + * platform versions. + * + * @param context Context to initialize config-dependent params from + * @param forParent Parent view to monitor + */ +private constructor(context: Context, private val mParentView: ViewGroup?, private val mCallback: ViewDragHelper.Callback) { + + // Current drag state; idle, dragging or settling + /** + * Retrieve the current drag state of this helper. This will return one of + * [.STATE_IDLE], [.STATE_DRAGGING] or [.STATE_SETTLING]. + * @return The current drag state + */ + var viewDragState: Int = 0 + private set + + // Distance to travel before a drag may begin + /** + * @return The minimum distance in pixels that the user must travel to initiate a drag + */ + var touchSlop: Int = 0 + private set + + // Last known position/pointer tracking + /** + * @return The ID of the pointer currently dragging the captured view, + * or [.INVALID_POINTER]. + */ + var activePointerId = INVALID_POINTER + private set + private var mInitialMotionX: FloatArray? = null + private var mInitialMotionY: FloatArray? = null + private var mLastMotionX: FloatArray? = null + private var mLastMotionY: FloatArray? = null + private var mInitialEdgesTouched: IntArray? = null + private var mEdgeDragsInProgress: IntArray? = null + private var mEdgeDragsLocked: IntArray? = null + private var mPointersDown: Int = 0 + + private var mVelocityTracker: VelocityTracker? = null + private val mMaxVelocity: Float + /** + * Return the currently configured minimum velocity. Any flings with a magnitude less + * than this value in pixels per second. Callback methods accepting a velocity will receive + * zero as a velocity value if the real detected velocity was below this threshold. + * + * @return the minimum velocity that will be detected + */ + /** + * Set the minimum velocity that will be detected as having a magnitude greater than zero + * in pixels per second. Callback methods accepting a velocity will be clamped appropriately. + * + * @param minVel Minimum velocity to detect + */ + var minVelocity: Float = 0.toFloat() + + /** + * Return the size of an edge. This is the range in pixels along the edges of this view + * that will actively detect edge touches or drags if edge tracking is enabled. + * + * @return The size of an edge in pixels + * @see .setEdgeTrackingEnabled + */ + val edgeSize: Int + private var mTrackingEdges: Int = 0 + + private val mScroller: ScrollerCompat + + /** + * @return The currently captured view, or null if no view has been captured. + */ + var capturedView: View? = null + private set + private var mReleaseInProgress: Boolean = false + + private val mSetIdleRunnable = Runnable { setDragState(STATE_IDLE) } + + init { + if (mParentView == null) { + throw IllegalArgumentException("Parent view may not be null") + } + if (mCallback == null) { + throw IllegalArgumentException("Callback may not be null") + } + + val vc = ViewConfiguration.get(context) + val density = context.resources.displayMetrics.density + edgeSize = (EDGE_SIZE * density + 0.5f).toInt() + + touchSlop = vc.scaledTouchSlop + mMaxVelocity = vc.scaledMaximumFlingVelocity.toFloat() + minVelocity = vc.scaledMinimumFlingVelocity.toFloat() + mScroller = ScrollerCompat.create(context, sInterpolator) + } + + /** + * Enable edge tracking for the selected edges of the parent view. + * The callback's [ViewDragHelper.Callback.onEdgeTouched] and + * [ViewDragHelper.Callback.onEdgeDragStarted] methods will only be invoked + * for edges for which edge tracking has been enabled. + * + * @param edgeFlags Combination of edge flags describing the edges to watch + * @see .EDGE_LEFT + * + * @see .EDGE_TOP + * + * @see .EDGE_RIGHT + * + * @see .EDGE_BOTTOM + */ + fun setEdgeTrackingEnabled(edgeFlags: Int) { + mTrackingEdges = edgeFlags + } + + /** + * Capture a specific child view for dragging within the parent. The callback will be notified + * but [ViewDragHelper.Callback.tryCaptureView] will not be asked permission to + * capture this view. + * + * @param childView Child view to capture + * @param activePointerId ID of the pointer that is dragging the captured child view + */ + fun captureChildView(childView: View, activePointerId: Int) { + if (childView.parent !== mParentView) { + throw IllegalArgumentException("captureChildView: parameter must be a descendant " + + "of the ViewDragHelper's tracked parent view (" + mParentView + ")") + } + + capturedView = childView + this.activePointerId = activePointerId + mCallback.onViewCaptured(childView, activePointerId) + setDragState(STATE_DRAGGING) + } + + /** + * The result of a call to this method is equivalent to + * [.processTouchEvent] receiving an ACTION_CANCEL event. + */ + fun cancel() { + activePointerId = INVALID_POINTER + clearMotionHistory() + + if (mVelocityTracker != null) { + mVelocityTracker!!.recycle() + mVelocityTracker = null + } + } + + /** + * [.cancel], but also abort all motion in progress and snap to the end of any + * animation. + */ + fun abort() { + cancel() + if (viewDragState == STATE_SETTLING) { + val oldX = mScroller.currX + val oldY = mScroller.currY + mScroller.abortAnimation() + val newX = mScroller.currX + val newY = mScroller.currY + mCallback.onViewPositionChanged(capturedView!!, newX, newY, newX - oldX, newY - oldY) + } + setDragState(STATE_IDLE) + } + + /** + * Animate the view `child` to the given (left, top) position. + * If this method returns true, the caller should invoke [.continueSettling] + * on each subsequent frame to continue the motion until it returns false. If this method + * returns false there is no further work to do to complete the movement. + * + * + * This operation does not count as a capture event, though [.getCapturedView] + * will still report the sliding view while the slide is in progress. + * + * @param child Child view to capture and animate + * @param finalLeft Final left position of child + * @param finalTop Final top position of child + * @return true if animation should continue through [.continueSettling] calls + */ + fun smoothSlideViewTo(child: View, finalLeft: Int, finalTop: Int): Boolean { + capturedView = child + activePointerId = INVALID_POINTER + + val continueSliding = forceSettleCapturedViewAt(finalLeft, finalTop, 0, 0) + if (!continueSliding && viewDragState == STATE_IDLE && capturedView != null) { + // If we're in an IDLE state to begin with and aren't moving anywhere, we + // end up having a non-null capturedView with an IDLE dragState + capturedView = null + } + + return continueSliding + } + + /** + * Settle the captured view at the given (left, top) position. + * The appropriate velocity from prior motion will be taken into account. + * If this method returns true, the caller should invoke [.continueSettling] + * on each subsequent frame to continue the motion until it returns false. If this method + * returns false there is no further work to do to complete the movement. + * + * @param finalLeft Settled left edge position for the captured view + * @param finalTop Settled top edge position for the captured view + * @return true if animation should continue through [.continueSettling] calls + */ + fun settleCapturedViewAt(finalLeft: Int, finalTop: Int): Boolean { + if (!mReleaseInProgress) { + throw IllegalStateException("Cannot settleCapturedViewAt outside of a call to " + "Callback#onViewReleased") + } + + return forceSettleCapturedViewAt(finalLeft, finalTop, + VelocityTrackerCompat.getXVelocity(mVelocityTracker!!, activePointerId).toInt(), + VelocityTrackerCompat.getYVelocity(mVelocityTracker!!, activePointerId).toInt()) + } + + /** + * Settle the captured view at the given (left, top) position. + * + * @param finalLeft Target left position for the captured view + * @param finalTop Target top position for the captured view + * @param xvel Horizontal velocity + * @param yvel Vertical velocity + * @return true if animation should continue through [.continueSettling] calls + */ + private fun forceSettleCapturedViewAt(finalLeft: Int, finalTop: Int, xvel: Int, yvel: Int): Boolean { + val startLeft = capturedView!!.x.toInt() + val startTop = capturedView!!.y.toInt() + val dx = finalLeft - startLeft + val dy = finalTop - startTop + + if (dx == 0 && dy == 0) { + // Nothing to do. Send callbacks, be done. + mScroller.abortAnimation() + setDragState(STATE_IDLE) + return false + } + + val duration = computeSettleDuration(capturedView!!, dx, dy, xvel, yvel) + mScroller.startScroll(startLeft, startTop, dx, dy, duration) + + setDragState(STATE_SETTLING) + return true + } + + private fun computeSettleDuration(child: View, dx: Int, dy: Int, xvel: Int, yvel: Int): Int { + var xvel = xvel + var yvel = yvel + xvel = clampMag(xvel, minVelocity.toInt(), mMaxVelocity.toInt()) + yvel = clampMag(yvel, minVelocity.toInt(), mMaxVelocity.toInt()) + val absDx = Math.abs(dx) + val absDy = Math.abs(dy) + val absXVel = Math.abs(xvel) + val absYVel = Math.abs(yvel) + val addedVel = absXVel + absYVel + val addedDistance = absDx + absDy + + val xweight = if (xvel != 0) + absXVel.toFloat() / addedVel + else + absDx.toFloat() / addedDistance + val yweight = if (yvel != 0) + absYVel.toFloat() / addedVel + else + absDy.toFloat() / addedDistance + + val xduration = computeAxisDuration(dx, xvel, mCallback!!.getViewHorizontalDragRange(child)) + val yduration = computeAxisDuration(dy, yvel, mCallback!!.getViewVerticalDragRange(child)) + + return (xduration * xweight + yduration * yweight).toInt() + } + + private fun computeAxisDuration(delta: Int, velocity: Int, motionRange: Int): Int { + var velocity = velocity + if (delta == 0) { + return 0 + } + + val width = mParentView!!.width + val halfWidth = width / 2 + val distanceRatio = Math.min(1f, Math.abs(delta).toFloat() / width) + val distance = halfWidth + halfWidth * distanceInfluenceForSnapDuration(distanceRatio) + + val duration: Int + velocity = Math.abs(velocity) + if (velocity > 0) { + duration = 4 * Math.round(1000 * Math.abs(distance / velocity)) + } else { + val range = Math.abs(delta).toFloat() / motionRange + duration = ((range + 1) * BASE_SETTLE_DURATION).toInt() + } + return Math.min(duration, MAX_SETTLE_DURATION) + } + + /** + * Clamp the magnitude of value for absMin and absMax. + * If the value is below the minimum, it will be clamped to zero. + * If the value is above the maximum, it will be clamped to the maximum. + * + * @param value Value to clamp + * @param absMin Absolute value of the minimum significant value to return + * @param absMax Absolute value of the maximum value to return + * @return The clamped value with the same sign as `value` + */ + private fun clampMag(value: Int, absMin: Int, absMax: Int): Int { + val absValue = Math.abs(value) + if (absValue < absMin) return 0 + return if (absValue > absMax) if (value > 0) absMax else -absMax else value + } + + /** + * Clamp the magnitude of value for absMin and absMax. + * If the value is below the minimum, it will be clamped to zero. + * If the value is above the maximum, it will be clamped to the maximum. + * + * @param value Value to clamp + * @param absMin Absolute value of the minimum significant value to return + * @param absMax Absolute value of the maximum value to return + * @return The clamped value with the same sign as `value` + */ + private fun clampMag(value: Float, absMin: Float, absMax: Float): Float { + val absValue = Math.abs(value) + if (absValue < absMin) return 0f + return if (absValue > absMax) if (value > 0) absMax else -absMax else value + } + + private fun distanceInfluenceForSnapDuration(f: Float): Float { + var f = f + f -= 0.5f // center the values about 0. + f *= (0.3f * Math.PI / 2.0f).toFloat() + return Math.sin(f.toDouble()).toFloat() + } + + /** + * Settle the captured view based on standard free-moving fling behavior. + * The caller should invoke [.continueSettling] on each subsequent frame + * to continue the motion until it returns false. + * + * @param minLeft Minimum X position for the view's left edge + * @param minTop Minimum Y position for the view's top edge + * @param maxLeft Maximum X position for the view's left edge + * @param maxTop Maximum Y position for the view's top edge + */ + fun flingCapturedView(minLeft: Int, minTop: Int, maxLeft: Int, maxTop: Int) { + if (!mReleaseInProgress) { + throw IllegalStateException("Cannot flingCapturedView outside of a call to " + "Callback#onViewReleased") + } + + mScroller.fling(capturedView!!.x.toInt(), capturedView!!.y.toInt(), + VelocityTrackerCompat.getXVelocity(mVelocityTracker!!, activePointerId).toInt(), + VelocityTrackerCompat.getYVelocity(mVelocityTracker!!, activePointerId).toInt(), + minLeft, maxLeft, minTop, maxTop) + + setDragState(STATE_SETTLING) + } + + /** + * Move the captured settling view by the appropriate amount for the current time. + * If `continueSettling` returns true, the caller should call it again + * on the next frame to continue. + * + * @param deferCallbacks true if state callbacks should be deferred via posted message. + * Set this to true if you are calling this method from + * [android.view.View.computeScroll] or similar methods + * invoked as part of layout or drawing. + * @return true if settle is still in progress + */ + fun continueSettling(deferCallbacks: Boolean): Boolean { + if (viewDragState == STATE_SETTLING) { + var keepGoing = mScroller.computeScrollOffset() + val x = mScroller.currX + val y = mScroller.currY + val dx = (x - capturedView!!.x).toInt() + val dy = (y - capturedView!!.y).toInt() + + if (dx != 0) { + ViewCompat.offsetLeftAndRight(capturedView!!, dx) + } + if (dy != 0) { + ViewCompat.offsetTopAndBottom(capturedView!!, dy) + } + + if (dx != 0 || dy != 0) { + mCallback.onViewPositionChanged(capturedView!!, x, y, dx, dy) + } + + if (keepGoing && x == mScroller.finalX && y == mScroller.finalY) { + // Close enough. The interpolator/scroller might think we're still moving + // but the user sure doesn't. + mScroller.abortAnimation() + keepGoing = false + } + + if (!keepGoing) { + if (deferCallbacks) { + mParentView?.post(mSetIdleRunnable) + } else { + setDragState(STATE_IDLE) + } + } + } + + return viewDragState == STATE_SETTLING + } + + /** + * Like all callback events this must happen on the UI thread, but release + * involves some extra semantics. During a release (mReleaseInProgress) + * is the only time it is valid to call [.settleCapturedViewAt] + * or [.flingCapturedView]. + */ + private fun dispatchViewReleased(xvel: Float, yvel: Float) { + mReleaseInProgress = true + mCallback.onViewReleased(capturedView!!, xvel, yvel) + mReleaseInProgress = false + + if (viewDragState == STATE_DRAGGING) { + // onViewReleased didn't call a method that would have changed this. Go idle. + setDragState(STATE_IDLE) + } + } + + private fun clearMotionHistory() { + if (mInitialMotionX == null) { + return + } + Arrays.fill(mInitialMotionX!!, 0f) + Arrays.fill(mInitialMotionY!!, 0f) + Arrays.fill(mLastMotionX!!, 0f) + Arrays.fill(mLastMotionY!!, 0f) + Arrays.fill(mInitialEdgesTouched!!, 0) + Arrays.fill(mEdgeDragsInProgress!!, 0) + Arrays.fill(mEdgeDragsLocked!!, 0) + mPointersDown = 0 + } + + private fun clearMotionHistory(pointerId: Int) { + if (mInitialMotionX == null || !isPointerDown(pointerId)) { + return + } + mInitialMotionX!![pointerId] = 0f + mInitialMotionY!![pointerId] = 0f + mLastMotionX!![pointerId] = 0f + mLastMotionY!![pointerId] = 0f + mInitialEdgesTouched!![pointerId] = 0 + mEdgeDragsInProgress!![pointerId] = 0 + mEdgeDragsLocked!![pointerId] = 0 + mPointersDown = mPointersDown and (1 shl pointerId).inv() + } + + private fun ensureMotionHistorySizeForId(pointerId: Int) { + if (mInitialMotionX == null || mInitialMotionX!!.size <= pointerId) { + val imx = FloatArray(pointerId + 1) + val imy = FloatArray(pointerId + 1) + val lmx = FloatArray(pointerId + 1) + val lmy = FloatArray(pointerId + 1) + val iit = IntArray(pointerId + 1) + val edip = IntArray(pointerId + 1) + val edl = IntArray(pointerId + 1) + + if (mInitialMotionX != null) { + System.arraycopy(mInitialMotionX!!, 0, imx, 0, mInitialMotionX!!.size) + System.arraycopy(mInitialMotionY!!, 0, imy, 0, mInitialMotionY!!.size) + System.arraycopy(mLastMotionX!!, 0, lmx, 0, mLastMotionX!!.size) + System.arraycopy(mLastMotionY!!, 0, lmy, 0, mLastMotionY!!.size) + System.arraycopy(mInitialEdgesTouched!!, 0, iit, 0, mInitialEdgesTouched!!.size) + System.arraycopy(mEdgeDragsInProgress!!, 0, edip, 0, mEdgeDragsInProgress!!.size) + System.arraycopy(mEdgeDragsLocked!!, 0, edl, 0, mEdgeDragsLocked!!.size) + } + + mInitialMotionX = imx + mInitialMotionY = imy + mLastMotionX = lmx + mLastMotionY = lmy + mInitialEdgesTouched = iit + mEdgeDragsInProgress = edip + mEdgeDragsLocked = edl + } + } + + private fun saveInitialMotion(x: Float, y: Float, pointerId: Int) { + ensureMotionHistorySizeForId(pointerId) + mLastMotionX!![pointerId] = x + mInitialMotionX!![pointerId] = mLastMotionX!![pointerId] + mLastMotionY!![pointerId] = y + mInitialMotionY!![pointerId] = mLastMotionY!![pointerId] + mInitialEdgesTouched!![pointerId] = getEdgesTouched(x.toInt(), y.toInt()) + mPointersDown = mPointersDown or (1 shl pointerId) + } + + private fun saveLastMotion(ev: MotionEvent) { + val pointerCount = ev.pointerCount + for (i in 0 until pointerCount) { + val pointerId = ev.getPointerId(i) + // If pointer is invalid then skip saving on ACTION_MOVE. + if (!isValidPointerForActionMove(pointerId)) { + continue + } + val x = ev.getX(i) + val y = ev.getY(i) + mLastMotionX!![pointerId] = x + mLastMotionY!![pointerId] = y + } + } + + /** + * Check if the given pointer ID represents a pointer that is currently down (to the best + * of the ViewDragHelper's knowledge). + * + * + * The state used to report this information is populated by the methods + * [.shouldInterceptTouchEvent] or + * [.processTouchEvent]. If one of these methods has not + * been called for all relevant MotionEvents to track, the information reported + * by this method may be stale or incorrect. + * + * @param pointerId pointer ID to check; corresponds to IDs provided by MotionEvent + * @return true if the pointer with the given ID is still down + */ + fun isPointerDown(pointerId: Int): Boolean { + return mPointersDown and (1 shl pointerId) != 0 + } + + internal fun setDragState(state: Int) { + mParentView?.removeCallbacks(mSetIdleRunnable) + if (viewDragState != state) { + viewDragState = state + mCallback.onViewDragStateChanged(state) + if (viewDragState == STATE_IDLE) { + capturedView = null + } + } + } + + /** + * Attempt to capture the view with the given pointer ID. The callback will be involved. + * This will put us into the "dragging" state. If we've already captured this view with + * this pointer this method will immediately return true without consulting the callback. + * + * @param toCapture View to capture + * @param pointerId Pointer to capture with + * @return true if capture was successful + */ + internal fun tryCaptureViewForDrag(toCapture: View?, pointerId: Int): Boolean { + if (toCapture === capturedView && activePointerId == pointerId) { + // Already done! + return true + } + if (toCapture != null && mCallback.tryCaptureView(toCapture, pointerId)) { + activePointerId = pointerId + captureChildView(toCapture, pointerId) + return true + } + return false + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels along the X axis + * @param dy Delta scrolled in pixels along the Y axis + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected fun canScroll(v: View, checkV: Boolean, dx: Int, dy: Int, x: Int, y: Int): Boolean { + if (v is ViewGroup) { + val group = v + val scrollX = v.getScrollX() + val scrollY = v.getScrollY() + val count = group.childCount + // Count backwards - let topmost views consume scroll distance first. + for (i in count - 1 downTo 0) { + // TODO: Add versioned support here for transformed views. + // This will not work for transformed views in Honeycomb+ + val child = group.getChildAt(i) + if (x + scrollX >= child.left && x + scrollX < child.right + && y + scrollY >= child.top && y + scrollY < child.bottom + && canScroll(child, true, dx, dy, x + scrollX - child.left, + y + scrollY - child.top)) { + return true + } + } + } + + return checkV && (ViewCompat.canScrollHorizontally(v, -dx) || ViewCompat.canScrollVertically(v, -dy)) + } + + /** + * Check if this event as provided to the parent view's onInterceptTouchEvent should + * cause the parent to intercept the touch event stream. + * + * @param ev MotionEvent provided to onInterceptTouchEvent + * @return true if the parent view should return true from onInterceptTouchEvent + */ + fun shouldInterceptTouchEvent(ev: MotionEvent): Boolean { + val action = MotionEventCompat.getActionMasked(ev) + val actionIndex = MotionEventCompat.getActionIndex(ev) + + if (action == MotionEvent.ACTION_DOWN) { + // Reset things for a new event stream, just in case we didn't get + // the whole previous stream. + cancel() + } + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain() + } + mVelocityTracker!!.addMovement(ev) + + when (action) { + MotionEvent.ACTION_DOWN -> { + val x = ev.x + val y = ev.y + val pointerId = ev.getPointerId(0) + saveInitialMotion(x, y, pointerId) + + val toCapture = findTopChildUnder(x.toInt(), y.toInt()) + + // Catch a settling view if possible. + if (toCapture === capturedView && viewDragState == STATE_SETTLING) { + tryCaptureViewForDrag(toCapture, pointerId) + } + + val edgesTouched = mInitialEdgesTouched!![pointerId] + if (edgesTouched and mTrackingEdges != 0) { + mCallback.onEdgeTouched(edgesTouched and mTrackingEdges, pointerId) + } + } + + MotionEventCompat.ACTION_POINTER_DOWN -> { + val pointerId = ev.getPointerId(actionIndex) + val x = ev.getX(actionIndex) + val y = ev.getY(actionIndex) + + saveInitialMotion(x, y, pointerId) + + // A ViewDragHelper can only manipulate one view at a time. + if (viewDragState == STATE_IDLE) { + val edgesTouched = mInitialEdgesTouched!![pointerId] + if (edgesTouched and mTrackingEdges != 0) { + mCallback.onEdgeTouched(edgesTouched and mTrackingEdges, pointerId) + } + } else if (viewDragState == STATE_SETTLING) { + // Catch a settling view if possible. + val toCapture = findTopChildUnder(x.toInt(), y.toInt()) + if (toCapture === capturedView) { + tryCaptureViewForDrag(toCapture, pointerId) + } + } + } + + MotionEvent.ACTION_MOVE -> { + + if (mInitialMotionX == null || mInitialMotionY == null) { + return false + } + + // First to cross a touch slop over a draggable view wins. Also report edge drags. + val pointerCount = ev.pointerCount + for (i in 0 until pointerCount) { + val pointerId = ev.getPointerId(i) + + // If pointer is invalid then skip the ACTION_MOVE. + if (!isValidPointerForActionMove(pointerId)) continue + + val x = ev.getX(i) + val y = ev.getY(i) + val dx = x - mInitialMotionX!![pointerId] + val dy = y - mInitialMotionY!![pointerId] + + val toCapture = findTopChildUnder(x.toInt(), y.toInt()) + val pastSlop = toCapture != null && checkTouchSlop(toCapture, dx, dy) + if (pastSlop) { + // check the callback's + // getView[Horizontal|Vertical]DragRange methods to know + // if you can move at all along an axis, then see if it + // would clamp to the same value. If you can't move at + // all in every dimension with a nonzero range, bail. + val oldLeft = toCapture!!.x.toInt() + val targetLeft = oldLeft + dx.toInt() + val newLeft = mCallback.clampViewPositionHorizontal(toCapture, + targetLeft, dx.toInt()) + val oldTop = toCapture.top + val targetTop = oldTop + dy.toInt() + val newTop = mCallback.clampViewPositionVertical(toCapture, targetTop, + dy.toInt()) + val horizontalDragRange = mCallback.getViewHorizontalDragRange( + toCapture) + val verticalDragRange = mCallback.getViewVerticalDragRange(toCapture) + if ((horizontalDragRange == 0 || horizontalDragRange > 0 && newLeft == oldLeft) && (verticalDragRange == 0 || verticalDragRange > 0 && newTop == oldTop)) { + break + } + } + reportNewEdgeDrags(dx, dy, pointerId) + if (viewDragState == STATE_DRAGGING) { + // Callback might have started an edge drag + break + } + + if (pastSlop && tryCaptureViewForDrag(toCapture, pointerId)) { + break + } + } + saveLastMotion(ev) + } + + MotionEventCompat.ACTION_POINTER_UP -> { + val pointerId = ev.getPointerId(actionIndex) + clearMotionHistory(pointerId) + } + + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + cancel() + } + } + + return viewDragState == STATE_DRAGGING + } + + /** + * Process a touch event received by the parent view. This method will dispatch callback events + * as needed before returning. The parent view's onTouchEvent implementation should call this. + * + * @param ev The touch event received by the parent view + */ + fun processTouchEvent(ev: MotionEvent) { + val action = MotionEventCompat.getActionMasked(ev) + val actionIndex = MotionEventCompat.getActionIndex(ev) + + if (action == MotionEvent.ACTION_DOWN) { + // Reset things for a new event stream, just in case we didn't get + // the whole previous stream. + cancel() + } + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain() + } + mVelocityTracker!!.addMovement(ev) + + when (action) { + MotionEvent.ACTION_DOWN -> { + val x = ev.x + val y = ev.y + val pointerId = ev.getPointerId(0) + val toCapture = findTopChildUnder(x.toInt(), y.toInt()) + + saveInitialMotion(x, y, pointerId) + + // Since the parent is already directly processing this touch event, + // there is no reason to delay for a slop before dragging. + // Start immediately if possible. + tryCaptureViewForDrag(toCapture, pointerId) + + val edgesTouched = mInitialEdgesTouched!![pointerId] + if (edgesTouched and mTrackingEdges != 0) { + mCallback.onEdgeTouched(edgesTouched and mTrackingEdges, pointerId) + } + } + + MotionEventCompat.ACTION_POINTER_DOWN -> { + val pointerId = ev.getPointerId(actionIndex) + val x = ev.getX(actionIndex) + val y = ev.getY(actionIndex) + + saveInitialMotion(x, y, pointerId) + + // A ViewDragHelper can only manipulate one view at a time. + if (viewDragState == STATE_IDLE) { + // If we're idle we can do anything! Treat it like a normal down event. + + val toCapture = findTopChildUnder(x.toInt(), y.toInt()) + tryCaptureViewForDrag(toCapture, pointerId) + + val edgesTouched = mInitialEdgesTouched!![pointerId] + if (edgesTouched and mTrackingEdges != 0) { + mCallback.onEdgeTouched(edgesTouched and mTrackingEdges, pointerId) + } + } else if (isCapturedViewUnder(x.toInt(), y.toInt())) { + // We're still tracking a captured view. If the same view is under this + // point, we'll swap to controlling it with this pointer instead. + // (This will still work if we're "catching" a settling view.) + + tryCaptureViewForDrag(capturedView, pointerId) + } + } + + MotionEvent.ACTION_MOVE -> { + if (viewDragState == STATE_DRAGGING) { + // If pointer is invalid then skip the ACTION_MOVE. + if (!isValidPointerForActionMove(activePointerId)) { + return + } + + val index = ev.findPointerIndex(activePointerId) + val x = ev.getX(index) + val y = ev.getY(index) + val idx = (x - mLastMotionX!![activePointerId]).toInt() + val idy = (y - mLastMotionY!![activePointerId]).toInt() + + dragTo((capturedView!!.x + idx).toInt(), (capturedView!!.y + idy).toInt(), idx, idy) + + saveLastMotion(ev) + } else { + // Check to see if any pointer is now over a draggable view. + val pointerCount = ev.pointerCount + for (i in 0 until pointerCount) { + val pointerId = ev.getPointerId(i) + + // If pointer is invalid then skip the ACTION_MOVE. + if (!isValidPointerForActionMove(pointerId)) continue + + val x = ev.getX(i) + val y = ev.getY(i) + val dx = x - mInitialMotionX!![pointerId] + val dy = y - mInitialMotionY!![pointerId] + + reportNewEdgeDrags(dx, dy, pointerId) + if (viewDragState == STATE_DRAGGING) { + // Callback might have started an edge drag. + break + } + + val toCapture = findTopChildUnder(x.toInt(), y.toInt()) + if (checkTouchSlop(toCapture, dx, dy) && tryCaptureViewForDrag(toCapture, pointerId)) { + break + } + } + saveLastMotion(ev) + } + } + + MotionEventCompat.ACTION_POINTER_UP -> { + val pointerId = ev.getPointerId(actionIndex) + if (viewDragState == STATE_DRAGGING && pointerId == activePointerId) { + // Try to find another pointer that's still holding on to the captured view. + var newActivePointer = INVALID_POINTER + val pointerCount = ev.pointerCount + for (i in 0 until pointerCount) { + val id = ev.getPointerId(i) + if (id == activePointerId) { + // This one's going away, skip. + continue + } + + val x = ev.getX(i) + val y = ev.getY(i) + if (findTopChildUnder(x.toInt(), y.toInt()) === capturedView && tryCaptureViewForDrag(capturedView, id)) { + newActivePointer = activePointerId + break + } + } + + if (newActivePointer == INVALID_POINTER) { + // We didn't find another pointer still touching the view, release it. + releaseViewForPointerUp() + } + } + clearMotionHistory(pointerId) + } + + MotionEvent.ACTION_UP -> { + if (viewDragState == STATE_DRAGGING) { + releaseViewForPointerUp() + } + cancel() + } + + MotionEvent.ACTION_CANCEL -> { + if (viewDragState == STATE_DRAGGING) { + dispatchViewReleased(0f, 0f) + } + cancel() + } + } + } + + private fun reportNewEdgeDrags(dx: Float, dy: Float, pointerId: Int) { + var dragsStarted = 0 + if (checkNewEdgeDrag(dx, dy, pointerId, EDGE_LEFT)) { + dragsStarted = dragsStarted or EDGE_LEFT + } + if (checkNewEdgeDrag(dy, dx, pointerId, EDGE_TOP)) { + dragsStarted = dragsStarted or EDGE_TOP + } + if (checkNewEdgeDrag(dx, dy, pointerId, EDGE_RIGHT)) { + dragsStarted = dragsStarted or EDGE_RIGHT + } + if (checkNewEdgeDrag(dy, dx, pointerId, EDGE_BOTTOM)) { + dragsStarted = dragsStarted or EDGE_BOTTOM + } + + if (dragsStarted != 0) { + mEdgeDragsInProgress!![pointerId] = mEdgeDragsInProgress!![pointerId] or dragsStarted + mCallback.onEdgeDragStarted(dragsStarted, pointerId) + } + } + + private fun checkNewEdgeDrag(delta: Float, odelta: Float, pointerId: Int, edge: Int): Boolean { + val absDelta = Math.abs(delta) + val absODelta = Math.abs(odelta) + + if (mInitialEdgesTouched!![pointerId] and edge != edge || mTrackingEdges and edge == 0 + || mEdgeDragsLocked!![pointerId] and edge == edge + || mEdgeDragsInProgress!![pointerId] and edge == edge + || absDelta <= touchSlop && absODelta <= touchSlop) { + return false + } + if (absDelta < absODelta * 0.5f && mCallback.onEdgeLock(edge)) { + mEdgeDragsLocked!![pointerId] = mEdgeDragsLocked!![pointerId] or edge + return false + } + return mEdgeDragsInProgress!![pointerId] and edge == 0 && absDelta > touchSlop + } + + /** + * Check if we've crossed a reasonable touch slop for the given child view. + * If the child cannot be dragged along the horizontal or vertical axis, motion + * along that axis will not count toward the slop check. + * + * @param child Child to check + * @param dx Motion since initial position along X axis + * @param dy Motion since initial position along Y axis + * @return true if the touch slop has been crossed + */ + private fun checkTouchSlop(child: View?, dx: Float, dy: Float): Boolean { + if (child == null) { + return false + } + val checkHorizontal = mCallback.getViewHorizontalDragRange(child) > 0 + val checkVertical = mCallback.getViewVerticalDragRange(child) > 0 + + if (checkHorizontal && checkVertical) { + return dx * dx + dy * dy > touchSlop * touchSlop + } else if (checkHorizontal) { + return Math.abs(dx) > touchSlop + } else if (checkVertical) { + return Math.abs(dy) > touchSlop + } + return false + } + + /** + * Check if any pointer tracked in the current gesture has crossed + * the required slop threshold. + * + * + * This depends on internal state populated by + * [.shouldInterceptTouchEvent] or + * [.processTouchEvent]. You should only rely on + * the results of this method after all currently available touch data + * has been provided to one of these two methods. + * + * @param directions Combination of direction flags, see [.DIRECTION_HORIZONTAL], + * [.DIRECTION_VERTICAL], [.DIRECTION_ALL] + * @return true if the slop threshold has been crossed, false otherwise + */ + fun checkTouchSlop(directions: Int): Boolean { + val count = mInitialMotionX!!.size + for (i in 0 until count) { + if (checkTouchSlop(directions, i)) { + return true + } + } + return false + } + + /** + * Check if the specified pointer tracked in the current gesture has crossed + * the required slop threshold. + * + * + * This depends on internal state populated by + * [.shouldInterceptTouchEvent] or + * [.processTouchEvent]. You should only rely on + * the results of this method after all currently available touch data + * has been provided to one of these two methods. + * + * @param directions Combination of direction flags, see [.DIRECTION_HORIZONTAL], + * [.DIRECTION_VERTICAL], [.DIRECTION_ALL] + * @param pointerId ID of the pointer to slop check as specified by MotionEvent + * @return true if the slop threshold has been crossed, false otherwise + */ + fun checkTouchSlop(directions: Int, pointerId: Int): Boolean { + if (!isPointerDown(pointerId)) { + return false + } + + val checkHorizontal = directions and DIRECTION_HORIZONTAL == DIRECTION_HORIZONTAL + val checkVertical = directions and DIRECTION_VERTICAL == DIRECTION_VERTICAL + + val dx = mLastMotionX!![pointerId] - mInitialMotionX!![pointerId] + val dy = mLastMotionY!![pointerId] - mInitialMotionY!![pointerId] + + if (checkHorizontal && checkVertical) { + return dx * dx + dy * dy > touchSlop * touchSlop + } else if (checkHorizontal) { + return Math.abs(dx) > touchSlop + } else if (checkVertical) { + return Math.abs(dy) > touchSlop + } + return false + } + + /** + * Check if any of the edges specified were initially touched in the currently active gesture. + * If there is no currently active gesture this method will return false. + * + * @param edges Edges to check for an initial edge touch. See [.EDGE_LEFT], + * [.EDGE_TOP], [.EDGE_RIGHT], [.EDGE_BOTTOM] and + * [.EDGE_ALL] + * @return true if any of the edges specified were initially touched in the current gesture + */ + fun isEdgeTouched(edges: Int): Boolean { + val count = mInitialEdgesTouched!!.size + for (i in 0 until count) { + if (isEdgeTouched(edges, i)) { + return true + } + } + return false + } + + /** + * Check if any of the edges specified were initially touched by the pointer with + * the specified ID. If there is no currently active gesture or if there is no pointer with + * the given ID currently down this method will return false. + * + * @param edges Edges to check for an initial edge touch. See [.EDGE_LEFT], + * [.EDGE_TOP], [.EDGE_RIGHT], [.EDGE_BOTTOM] and + * [.EDGE_ALL] + * @return true if any of the edges specified were initially touched in the current gesture + */ + fun isEdgeTouched(edges: Int, pointerId: Int): Boolean { + return isPointerDown(pointerId) && mInitialEdgesTouched!![pointerId] and edges != 0 + } + + private fun releaseViewForPointerUp() { + mVelocityTracker!!.computeCurrentVelocity(1000, mMaxVelocity) + val xvel = clampMag( + VelocityTrackerCompat.getXVelocity(mVelocityTracker!!, activePointerId), + minVelocity, mMaxVelocity) + val yvel = clampMag( + VelocityTrackerCompat.getYVelocity(mVelocityTracker!!, activePointerId), + minVelocity, mMaxVelocity) + dispatchViewReleased(xvel, yvel) + } + + private fun dragTo(left: Int, top: Int, dx: Int, dy: Int) { + var clampedX = left + var clampedY = top + val oldLeft = capturedView!!.x.toInt() + val oldTop = capturedView!!.y.toInt() + if (dx != 0) { + clampedX = mCallback.clampViewPositionHorizontal(capturedView!!, left, dx) + ViewCompat.offsetLeftAndRight(capturedView!!, clampedX - oldLeft) + } + if (dy != 0) { + clampedY = mCallback.clampViewPositionVertical(capturedView!!, top, dy) + ViewCompat.offsetTopAndBottom(capturedView!!, clampedY - oldTop) + } + + if (dx != 0 || dy != 0) { + val clampedDx = clampedX - oldLeft + val clampedDy = clampedY - oldTop + mCallback.onViewPositionChanged(capturedView!!, clampedX, clampedY, + clampedDx, clampedDy) + } + } + + /** + * Determine if the currently captured view is under the given point in the + * parent view's coordinate system. If there is no captured view this method + * will return false. + * + * @param x X position to test in the parent's coordinate system + * @param y Y position to test in the parent's coordinate system + * @return true if the captured view is under the given point, false otherwise + */ + fun isCapturedViewUnder(x: Int, y: Int): Boolean { + return isViewUnder(capturedView, x, y) + } + + /** + * Determine if the supplied view is under the given point in the + * parent view's coordinate system. + * + * @param view Child view of the parent to hit test + * @param x X position to test in the parent's coordinate system + * @param y Y position to test in the parent's coordinate system + * @return true if the supplied view is under the given point, false otherwise + */ + fun isViewUnder(view: View?, x: Int, y: Int): Boolean { + return if (view == null) { + false + } else x >= view.x + && x < view.x + view.width + && y >= view.y + && y < view.y + view.height + } + + /** + * Find the topmost child under the given point within the parent view's coordinate system. + * The child order is determined using [ViewDragHelper.Callback.getOrderedChildIndex]. + * + * @param x X position to test in the parent's coordinate system + * @param y Y position to test in the parent's coordinate system + * @return The topmost child view under (x, y) or null if none found. + */ + fun findTopChildUnder(x: Int, y: Int): View? { + + mParentView?.let { + val childCount = it.childCount + for (i in childCount - 1 downTo 0) { + val child = it.getChildAt(mCallback.getOrderedChildIndex(i)) + if (x >= child.x && x < child.x + child.width + && y >= child.y && y < child.y + child.height) { + return child + } + } + } + return null + } + + private fun getEdgesTouched(x: Int, y: Int): Int { + var result = 0 + + mParentView?.let { + if (x < it.x + edgeSize) result = result or EDGE_LEFT + if (y < it.y + edgeSize) result = result or EDGE_TOP + if (x > it.x + it.width - edgeSize) result = result or EDGE_RIGHT + if (y > it.y + it.height - edgeSize) result = result or EDGE_BOTTOM + } + + return result + } + + private fun isValidPointerForActionMove(pointerId: Int): Boolean { + if (!isPointerDown(pointerId)) { + Log.e(TAG, "Ignoring pointerId=" + pointerId + " because ACTION_DOWN was not received " + + "for this pointer before ACTION_MOVE. It likely happened because " + + " ViewDragHelper did not receive all the events in the event stream.") + return false + } + return true + } + + companion object { + + private val TAG = "ViewDragHelper" + + /** + * A null/invalid pointer ID. + */ + val INVALID_POINTER = -1 + + /** + * A view is not currently being dragged or animating as a result of a fling/snap. + */ + val STATE_IDLE = 0 + + /** + * A view is currently being dragged. The position is currently changing as a result + * of user input or simulated user input. + */ + val STATE_DRAGGING = 1 + + /** + * A view is currently settling into place as a result of a fling or + * predefined non-interactive motion. + */ + val STATE_SETTLING = 2 + + /** + * Edge flag indicating that the left edge should be affected. + */ + val EDGE_LEFT = 1 shl 0 + + /** + * Edge flag indicating that the right edge should be affected. + */ + val EDGE_RIGHT = 1 shl 1 + + /** + * Edge flag indicating that the top edge should be affected. + */ + val EDGE_TOP = 1 shl 2 + + /** + * Edge flag indicating that the bottom edge should be affected. + */ + val EDGE_BOTTOM = 1 shl 3 + + /** + * Edge flag set indicating all edges should be affected. + */ + val EDGE_ALL = EDGE_LEFT or EDGE_TOP or EDGE_RIGHT or EDGE_BOTTOM + + /** + * Indicates that a check should occur along the horizontal axis + */ + val DIRECTION_HORIZONTAL = 1 shl 0 + + /** + * Indicates that a check should occur along the vertical axis + */ + val DIRECTION_VERTICAL = 1 shl 1 + + /** + * Indicates that a check should occur along all axes + */ + val DIRECTION_ALL = DIRECTION_HORIZONTAL or DIRECTION_VERTICAL + + private val EDGE_SIZE = 20 // dp + + private val BASE_SETTLE_DURATION = 256 // ms + private val MAX_SETTLE_DURATION = 600 // ms + + + /** + * Interpolator defining the animation curve for mScroller + */ + private val sInterpolator = Interpolator { t -> + var t = t + t -= 1.0f + t * t * t * t * t + 1.0f + } + + /** + * Factory method to create a new ViewDragHelper. + * + * @param forParent Parent view to monitor + * @param cb Callback to provide information and receive events + * @return a new ViewDragHelper instance + */ + fun create(forParent: ViewGroup, cb: ViewDragHelper.Callback): KDragViewHelper { + return KDragViewHelper(forParent.context, forParent, cb) + } + + /** + * Factory method to create a new ViewDragHelper. + * + * @param forParent Parent view to monitor + * @param sensitivity Multiplier for how sensitive the helper should be about detecting + * the start of a drag. Larger values are more sensitive. 1.0f is normal. + * @param cb Callback to provide information and receive events + * @return a new ViewDragHelper instance + */ + fun create(forParent: ViewGroup, sensitivity: Float, cb: ViewDragHelper.Callback): KDragViewHelper { + val helper = create(forParent, cb) + helper.touchSlop = (helper.touchSlop * (1 / sensitivity)).toInt() + return helper + } + } + +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.java deleted file mode 100644 index a7a46ed..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.java +++ /dev/null @@ -1,49 +0,0 @@ -package kaufland.com.swipelibrary; - -import android.graphics.PointF; -import android.view.View; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * Created by sbra0902 on 21.06.17. - */ -public class LayoutCache { - - - Map mLayoutCache = new HashMap<>(); - - - public void restoreOnLayout(){ - - for (View child : mLayoutCache.keySet()){ - - PointF restorePoint = mLayoutCache.get(child); - - if(restorePoint != null){ - child.setX(restorePoint.x); - child.setY(restorePoint.y); - } - - } - - } - - - - public void captureChildrenBound(Collection views){ - - for (View child : views) { - PointF point = mLayoutCache.get(child); - if(point==null){ - point = new PointF(); - mLayoutCache.put(child, point); - } - - point.x = child.getX(); - point.y = child.getY(); - } - } -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.kt new file mode 100644 index 0000000..d5d9612 --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.kt @@ -0,0 +1,45 @@ +package kaufland.com.swipelibrary + +import android.graphics.PointF +import android.view.View +import java.util.HashMap + +/** + * Created by sbra0902 on 21.06.17. + */ +class LayoutCache { + + + internal var mLayoutCache: MutableMap = HashMap() + + + fun restoreOnLayout() { + + for (child in mLayoutCache.keys) { + + val restorePoint = mLayoutCache[child] + + if (restorePoint != null) { + child.x = restorePoint.x + child.y = restorePoint.y + } + + } + + } + + + fun captureChildrenBound(views: Collection) { + + for (child in views) { + var point = mLayoutCache[child] + if (point == null) { + point = PointF() + mLayoutCache[child] = point + } + + point.x = child.x + point.y = child.y + } + } +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SimpleSwipeListener.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SimpleSwipeListener.java deleted file mode 100644 index d62a01c..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SimpleSwipeListener.java +++ /dev/null @@ -1,19 +0,0 @@ -package kaufland.com.swipelibrary; - -public class SimpleSwipeListener implements SwipeLayout.SwipeListener { - - @Override - public void onSwipeOpened(SwipeState.DragViewState openedDragView, boolean isFullSwipe) { - - } - - @Override - public void onSwipeClosed(SwipeState.DragViewState dragViewState) { - - } - - @Override - public void onBounce(SwipeState.DragViewState dragViewState) { - - } -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SimpleSwipeListener.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SimpleSwipeListener.kt new file mode 100644 index 0000000..33a49d7 --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SimpleSwipeListener.kt @@ -0,0 +1,16 @@ +package kaufland.com.swipelibrary + +class SimpleSwipeListener : SwipeLayout.SwipeListener { + + override fun onSwipeOpened(openedDragView: SwipeState.DragViewState, isFullSwipe: Boolean) { + + } + + override fun onSwipeClosed(dragViewState: SwipeState.DragViewState) { + + } + + override fun onBounce(dragViewState: SwipeState.DragViewState) { + + } +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.java deleted file mode 100644 index af62f67..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.java +++ /dev/null @@ -1,32 +0,0 @@ -package kaufland.com.swipelibrary; - -import android.content.Context; -import android.os.Build; -import android.util.AttributeSet; -import android.widget.FrameLayout; - -import androidx.annotation.RequiresApi; - -/** - * Created by sbra0902 on 06.03.17. - */ - -public class SurfaceView extends FrameLayout { - - public SurfaceView(Context context) { - super(context); - } - - public SurfaceView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.kt new file mode 100644 index 0000000..b7f4b96 --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SurfaceView.kt @@ -0,0 +1,25 @@ +package kaufland.com.swipelibrary + +import android.content.Context +import android.os.Build +import android.util.AttributeSet +import android.widget.FrameLayout + +import androidx.annotation.RequiresApi + +/** + * Created by sbra0902 on 06.03.17. + */ + +class SurfaceView : FrameLayout { + + constructor(context: Context) : super(context) {} + + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {} + + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {} + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { + } +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.java deleted file mode 100644 index cbdb25a..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.java +++ /dev/null @@ -1,71 +0,0 @@ -package kaufland.com.swipelibrary; - -import android.graphics.Rect; - -/** - * Created by sbra0902 on 29.03.17. - */ - -public class SwipeDirectionDetector { - - private int xDown; - - private int xUp; - - private int yDown; - - private int yUp; - - public static final int SWIPE_DIRECTION_LEFT = 1; - - public static final int SWIPE_DIRECTION_RIGHT = 2; - - private Rect downRect; - private Rect upRect; - - - public void onActionDown(float x, float y, final SwipeLayout swipeLayout) { - xDown = (int) x; - yDown = (int) y; - - downRect = new Rect(); - swipeLayout.getGlobalVisibleRect(downRect); - } - - public void onActionUp(float x, float y, final SwipeLayout swipeLayout) { - - onAction(x, y); - - upRect = new Rect(); - swipeLayout.getGlobalVisibleRect(upRect); - } - - public void onAction(float x, float y){ - xUp = (int) x; - yUp = (int) y; - } - - public int getDifX() { - return xUp - xDown; - } - - public int getDifY() { - return yDown - yUp; - } - - public int getXDown() { - return xDown; - } - - public int getYDown() { - return yDown; - } - - public int getSwipeDirection(){ - return getDifX() > 0 ? SWIPE_DIRECTION_RIGHT : SWIPE_DIRECTION_LEFT; - } - - public boolean isHorizontalScrollChangedWhileDragging() { - return downRect == null || upRect == null || downRect.top != upRect.top; - } -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.kt new file mode 100644 index 0000000..f24be21 --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeDirectionDetector.kt @@ -0,0 +1,64 @@ +package kaufland.com.swipelibrary + +import android.graphics.Rect + +/** + * Created by sbra0902 on 29.03.17. + */ + +class SwipeDirectionDetector { + + var xDown: Int = 0 + private set + + private var xUp: Int = 0 + + var yDown: Int = 0 + private set + + private var yUp: Int = 0 + + private var downRect: Rect? = null + private var upRect: Rect? = null + + val difX: Int + get() = xUp - xDown + + val difY: Int + get() = yDown - yUp + + val swipeDirection: Int + get() = if (difX > 0) SWIPE_DIRECTION_RIGHT else SWIPE_DIRECTION_LEFT + + val isHorizontalScrollChangedWhileDragging: Boolean + get() = downRect == null || upRect == null || downRect!!.top != upRect!!.top + + + fun onActionDown(x: Float, y: Float, swipeLayout: SwipeLayout) { + xDown = x.toInt() + yDown = y.toInt() + + downRect = Rect() + swipeLayout.getGlobalVisibleRect(downRect) + } + + fun onActionUp(x: Float, y: Float, swipeLayout: SwipeLayout) { + + onAction(x, y) + + upRect = Rect() + swipeLayout.getGlobalVisibleRect(upRect) + } + + fun onAction(x: Float, y: Float) { + xUp = x.toInt() + yUp = y.toInt() + } + + companion object { + + val SWIPE_DIRECTION_LEFT = 1 + + val SWIPE_DIRECTION_RIGHT = 2 + } +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.java deleted file mode 100644 index 79ea8ca..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.java +++ /dev/null @@ -1,431 +0,0 @@ -package kaufland.com.swipelibrary; - -import android.content.Context; -import android.graphics.Canvas; - -import androidx.core.view.MotionEventCompat; -import androidx.core.view.ViewCompat; -import androidx.customview.widget.ViewDragHelper; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.widget.FrameLayout; - - - -import java.security.InvalidParameterException; - -import static kaufland.com.swipelibrary.SwipeState.DragViewState.CLOSED; -import static kaufland.com.swipelibrary.SwipeState.DragViewState.LEFT_OPEN; -import static kaufland.com.swipelibrary.SwipeState.DragViewState.RIGHT_OPEN; -import static kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.HORIZONTAL; -import static kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.VERTICAL; - - -public class SwipeLayout extends FrameLayout { - - private static final int SWIPE_CLOSING_POINT = 0; - - public static final int LEFT_DRAG_VIEW = 1; - public static final int RIGHT_DRAG_VIEW = 2; - public static final int TOP_DRAG_VIEW = 3; - public static final int BOTTOM_DRAG_VIEW = 4; - public static final int SURFACE_VIEW = 5; - - private static final String TAG = SwipeLayout.class.getSimpleName(); - - protected SwipeState mSwipeState = new SwipeState(); - - protected SwipeDirectionDetector mSwipeDirectionDetector = new SwipeDirectionDetector(); - - protected DraggingProxy mDraggingProxy = new DraggingProxy(); - - private KDragViewHelper mDragHelper; - - private SwipeListener mSwipeListener; - - private boolean mSwipeEnabled = true; - - private float mDragHelperTouchSlop; - - public interface SwipeListener { - void onSwipeOpened(SwipeState.DragViewState openedDragView, boolean isFullSwipe); - - void onSwipeClosed(SwipeState.DragViewState dragViewState); - - void onBounce(SwipeState.DragViewState dragViewState); - } - - public SwipeLayout(Context context) { - super(context); - } - - public SwipeLayout(Context context, AttributeSet attrs) { - super(context, attrs); - initSwipe(); - } - - public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initSwipe(); - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - - - if (!mSwipeEnabled) { - return false; - } - - final int action = ev.getAction(); - - switch (action) { - case MotionEvent.ACTION_DOWN: - - mDragHelper.abort(); - mSwipeDirectionDetector.onActionDown(ev.getX(), ev.getY(), this); - mDragHelper.processTouchEvent(ev); - break; - - case MotionEvent.ACTION_MOVE: - mSwipeDirectionDetector.onAction(ev.getX(), ev.getY()); - - - boolean isClick = mDragHelperTouchSlop > Math.abs(mSwipeDirectionDetector.getDifX()); - - if (!isClick) { - getParent().requestDisallowInterceptTouchEvent(true); - try { - mDragHelper.processTouchEvent(ev); - } catch (IllegalArgumentException e) { - // https://code.google.com/p/android/issues/detail?id=64553 - mSwipeDirectionDetector.onAction(mSwipeDirectionDetector.getXDown(), mSwipeDirectionDetector.getYDown()); - ev.setAction(MotionEvent.ACTION_UP); - mDragHelper.processTouchEvent(ev); - } - } - - break; - - case MotionEvent.ACTION_UP: - - mSwipeDirectionDetector.onActionUp(ev.getX(), ev.getY(), this); - - - if (ev.getX() < 0 || ev.getY() < 0 || ev.getX() > getMeasuredWidth() || ev.getY() > getMeasuredHeight()) { - - - ev.setAction(MotionEvent.ACTION_UP); - mDragHelper.processTouchEvent(ev); - return true; - } - - - mDragHelper.processTouchEvent(ev); - - - break; - - case MotionEvent.ACTION_CANCEL: - - mDragHelper.processTouchEvent(ev); - - break; - - default: - mDragHelper.processTouchEvent(ev); - } - - return true; - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - - - if (!mSwipeEnabled) { - return false; - } - - final int action = MotionEventCompat.getActionMasked(ev); - - switch (action) { - case MotionEvent.ACTION_DOWN: - mSwipeDirectionDetector.onActionDown(ev.getX(), ev.getY(), this); - mDragHelper.abort(); - mDragHelper.processTouchEvent(ev); - break; - - case MotionEvent.ACTION_MOVE: - mSwipeDirectionDetector.onAction(ev.getX(), ev.getY()); - - boolean isClick = mDragHelperTouchSlop > Math.abs(mSwipeDirectionDetector.getDifX()); - if (!isClick) { - try { - mDragHelper.processTouchEvent(ev); - } catch (IllegalArgumentException e) { - // https://code.google.com/p/android/issues/detail?id=64553 - mSwipeDirectionDetector.onAction(mSwipeDirectionDetector.getXDown(), mSwipeDirectionDetector.getYDown()); - ev.setAction(MotionEvent.ACTION_UP); - mDragHelper.processTouchEvent(ev); - } - } - - - if (!isClick) { - ViewParent parent = getParent(); - if (parent != null) { - parent.requestDisallowInterceptTouchEvent(true); - } - return true; - } - - break; - - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - - mDragHelper.processTouchEvent(ev); - break; - } - - return false; - } - - - public void smoothSlideTo(float slideOffset) { - - int leftOffset = mDraggingProxy.getDragDirection() == HORIZONTAL ? (int) slideOffset : 0; - int topOffset = mDraggingProxy.getDragDirection() == VERTICAL ? (int) slideOffset : 0; - - if (mDragHelper.smoothSlideViewTo(mDraggingProxy.getSurfaceView(), leftOffset, topOffset)) { - ViewCompat.postInvalidateOnAnimation(this); - } - } - - @Override - public void computeScroll() { - super.computeScroll(); - - - if (mDragHelper.continueSettling(true)) { - ViewCompat.postInvalidateOnAnimation(this); - } - - } - - @Override - protected void dispatchDraw(Canvas canvas) { - - super.dispatchDraw(canvas); - - if (!mDraggingProxy.isInitilized()) { - mDraggingProxy.init(this); - } - - if (mRestoreOnDraw) { - post(new Runnable() { - @Override - public void run() { - mDraggingProxy.restoreState(mSwipeState.getState()); - mRestoreOnDraw = false; - } - }); - - } - - - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - mDraggingProxy.restoreChildrenBound(); - } - - private class SwipeDragViewHelper extends ViewDragHelper.Callback { - - private ViewGroup parent; - - private int xBeforeDrag; - - SwipeDragViewHelper(ViewGroup parent) { - this.parent = parent; - } - - @Override - public boolean tryCaptureView(View child, int pointerId) { - - xBeforeDrag = (int) child.getX(); - return mDraggingProxy.isCapturedViewDraggable(child); - } - - @Override - public void onViewDragStateChanged(int state) { - if(state == 0){ - mDraggingProxy.captureChildrenBound(); - } - } - - @Override - public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { - - if (mDraggingProxy.getDragDirection() == SwipeViewLayouter.DragDirection.HORIZONTAL) { - - mDraggingProxy.moveView(changedView, left); - - } else if (mDraggingProxy.getDragDirection() == SwipeViewLayouter.DragDirection.VERTICAL) { - throw new InvalidParameterException("VerticalSwipeNotImplemented"); - } - } - - @Override - public void onViewReleased(View releasedChild, final float xvel, float yvel) { - - if (mDraggingProxy.getDragDirection() == SwipeViewLayouter.DragDirection.VERTICAL) { - throw new InvalidParameterException("VerticalSwipeNotImplemented"); - } else if (mDraggingProxy.getDragDirection() == SwipeViewLayouter.DragDirection.HORIZONTAL) { - - SwipeResult swipeResult = new SwipeResult(xBeforeDrag); - boolean isClick = mDragHelperTouchSlop > Math.abs(mSwipeDirectionDetector.getDifX()); - - if (!mSwipeDirectionDetector.isHorizontalScrollChangedWhileDragging() && !isClick) { - swipeResult = mDraggingProxy.determineSwipeHorizontalState(xvel, mSwipeDirectionDetector, mSwipeState, mSwipeListener, releasedChild); - } - - if (mDragHelper.smoothSlideViewTo(releasedChild, swipeResult.getSettleX(), 0)) { - ViewCompat.postInvalidateOnAnimation(parent); - - } - - mDraggingProxy.requestLayout(); - - if (swipeResult.getNotifyListener() != null && mSwipeListener != null) { - swipeResult.getNotifyListener().run(); - } - } - } - - @Override - public int clampViewPositionVertical(View child, int top, int dy) { - if (mSwipeState.getState() == LEFT_OPEN || - mSwipeState.getState() == RIGHT_OPEN || - mDraggingProxy.getDragDirection() == SwipeViewLayouter.DragDirection.HORIZONTAL) { - return 0; - } - - return 0; - } - - @Override - public int clampViewPositionHorizontal(View child, int left, int dx) { - if (mSwipeState.getState() == SwipeState.DragViewState.TOP_OPEN || - mSwipeState.getState() == SwipeState.DragViewState.BOTTOM_OPEN || - !mDraggingProxy.canSwipe(mSwipeDirectionDetector, mSwipeState.getState()) || - mDraggingProxy.getDragDirection() == SwipeViewLayouter.DragDirection.VERTICAL) { - return 0; - } - - return mDraggingProxy.clampViewPositionHorizontal(child, left); - } - - @Override - public int getViewHorizontalDragRange(View child) { - return getWidth(); - } - - @Override - public int getViewVerticalDragRange(View child) { - return 0; - } - - } - - - private boolean mRestoreOnDraw; - - public void markForRestoreOnDraw(SwipeState.DragViewState swipeState) { - mSwipeState.setState(swipeState); - mRestoreOnDraw = true; - if (mDragHelper.getViewDragState() != KDragViewHelper.STATE_IDLE) { - mDragHelper.abort(); - } - } - - public void closeSwipeNoAnimation() { - mSwipeState.setState(CLOSED); - mDraggingProxy.restoreState(mSwipeState.getState()); - } - - public void openSwipe(final int position, boolean notifyCallback) { - - int mSurfaceOpenOffsetByDragView = mDraggingProxy.getSurfaceOpenOffsetByDragView(position); - - switch (position) { - case LEFT_DRAG_VIEW: - mSwipeState.setState(LEFT_OPEN); - smoothSlideTo(mSurfaceOpenOffsetByDragView); - break; - - case RIGHT_DRAG_VIEW: - mSwipeState.setState(RIGHT_OPEN); - smoothSlideTo(mSurfaceOpenOffsetByDragView); - break; - - default: - return; - } - - - if (mSwipeListener != null && notifyCallback) { - notifySwipeOpened(); - } - } - - public void openSwipe(final int position) { - openSwipe(position, true); - } - - public void closeSwipe() { - switch (mSwipeState.getState()) { - case LEFT_OPEN: - case RIGHT_OPEN: - case TOP_OPEN: - case BOTTOM_OPEN: - smoothSlideTo(SWIPE_CLOSING_POINT); - mSwipeState.setState(CLOSED); - break; - } - } - - public void setSwipeEnabled(boolean enabled) { - mSwipeEnabled = enabled; - } - - public boolean getSwipeEnabled() { - return mSwipeEnabled; - } - - public SwipeState getSwipeState() { - return mSwipeState; - } - - public void setSwipeListener(SwipeListener listener) { - mSwipeListener = listener; - } - - private void notifySwipeOpened() { - mSwipeListener.onSwipeOpened(mSwipeState.getState(), true); - - } - - private void initSwipe() { - - mDragHelper = KDragViewHelper.create(this, 1.0f, new SwipeDragViewHelper(this)); - mDragHelperTouchSlop = mDragHelper.getTouchSlop() * 2; - } - -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.kt new file mode 100644 index 0000000..6b48a92 --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.kt @@ -0,0 +1,378 @@ +package kaufland.com.swipelibrary + +import android.content.Context +import android.graphics.Canvas + +import androidx.core.view.MotionEventCompat +import androidx.core.view.ViewCompat +import androidx.customview.widget.ViewDragHelper +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup +import android.view.ViewParent +import android.widget.FrameLayout + + +import java.security.InvalidParameterException + +import kaufland.com.swipelibrary.SwipeState.DragViewState.CLOSED +import kaufland.com.swipelibrary.SwipeState.DragViewState.LEFT_OPEN +import kaufland.com.swipelibrary.SwipeState.DragViewState.RIGHT_OPEN +import kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.HORIZONTAL +import kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.VERTICAL + + +class SwipeLayout : FrameLayout { + + var swipeState = SwipeState() + protected set + + protected var mSwipeDirectionDetector = SwipeDirectionDetector() + + protected var mDraggingProxy = DraggingProxy() + + private var mDragHelper: KDragViewHelper? = null + + private var mSwipeListener: SwipeListener? = null + + var swipeEnabled = true + + private var mDragHelperTouchSlop: Float = 0.toFloat() + + + private var mRestoreOnDraw: Boolean = false + + interface SwipeListener { + fun onSwipeOpened(openedDragView: SwipeState.DragViewState, isFullSwipe: Boolean) + + fun onSwipeClosed(dragViewState: SwipeState.DragViewState) + + fun onBounce(dragViewState: SwipeState.DragViewState) + } + + constructor(context: Context) : super(context) {} + + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { + initSwipe() + } + + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + initSwipe() + } + + override fun onTouchEvent(ev: MotionEvent): Boolean { + + + if (!swipeEnabled) { + return false + } + + val action = ev.action + + when (action) { + MotionEvent.ACTION_DOWN -> { + + mDragHelper!!.abort() + mSwipeDirectionDetector.onActionDown(ev.x, ev.y, this) + mDragHelper!!.processTouchEvent(ev) + } + + MotionEvent.ACTION_MOVE -> { + mSwipeDirectionDetector.onAction(ev.x, ev.y) + + + val isClick = mDragHelperTouchSlop > Math.abs(mSwipeDirectionDetector.difX) + + if (!isClick) { + parent.requestDisallowInterceptTouchEvent(true) + try { + mDragHelper!!.processTouchEvent(ev) + } catch (e: IllegalArgumentException) { + // https://code.google.com/p/android/issues/detail?id=64553 + mSwipeDirectionDetector.onAction(mSwipeDirectionDetector.xDown.toFloat(), mSwipeDirectionDetector.yDown.toFloat()) + ev.action = MotionEvent.ACTION_UP + mDragHelper!!.processTouchEvent(ev) + } + + } + } + + MotionEvent.ACTION_UP -> { + + mSwipeDirectionDetector.onActionUp(ev.x, ev.y, this) + + + if (ev.x < 0 || ev.y < 0 || ev.x > measuredWidth || ev.y > measuredHeight) { + + + ev.action = MotionEvent.ACTION_UP + mDragHelper!!.processTouchEvent(ev) + return true + } + + + mDragHelper!!.processTouchEvent(ev) + } + + MotionEvent.ACTION_CANCEL -> + + mDragHelper!!.processTouchEvent(ev) + + else -> mDragHelper!!.processTouchEvent(ev) + } + + return true + } + + override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { + + + if (!swipeEnabled) { + return false + } + + val action = MotionEventCompat.getActionMasked(ev) + + when (action) { + MotionEvent.ACTION_DOWN -> { + mSwipeDirectionDetector.onActionDown(ev.x, ev.y, this) + mDragHelper!!.abort() + mDragHelper!!.processTouchEvent(ev) + } + + MotionEvent.ACTION_MOVE -> { + mSwipeDirectionDetector.onAction(ev.x, ev.y) + + val isClick = mDragHelperTouchSlop > Math.abs(mSwipeDirectionDetector.difX) + if (!isClick) { + try { + mDragHelper!!.processTouchEvent(ev) + } catch (e: IllegalArgumentException) { + // https://code.google.com/p/android/issues/detail?id=64553 + mSwipeDirectionDetector.onAction(mSwipeDirectionDetector.xDown.toFloat(), mSwipeDirectionDetector.yDown.toFloat()) + ev.action = MotionEvent.ACTION_UP + mDragHelper!!.processTouchEvent(ev) + } + + } + + + if (!isClick) { + val parent = parent + parent?.requestDisallowInterceptTouchEvent(true) + return true + } + } + + MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> + + mDragHelper!!.processTouchEvent(ev) + } + + return false + } + + + fun smoothSlideTo(slideOffset: Float) { + + val leftOffset = if (mDraggingProxy.dragDirection == HORIZONTAL) slideOffset.toInt() else 0 + val topOffset = if (mDraggingProxy.dragDirection == VERTICAL) slideOffset.toInt() else 0 + + if (mDragHelper!!.smoothSlideViewTo(mDraggingProxy.surfaceView, leftOffset, topOffset)) { + ViewCompat.postInvalidateOnAnimation(this) + } + } + + override fun computeScroll() { + super.computeScroll() + + + if (mDragHelper!!.continueSettling(true)) { + ViewCompat.postInvalidateOnAnimation(this) + } + + } + + override fun dispatchDraw(canvas: Canvas) { + + super.dispatchDraw(canvas) + + if (!mDraggingProxy.isInitilized) { + mDraggingProxy.init(this) + } + + if (mRestoreOnDraw) { + post { + mDraggingProxy.restoreState(swipeState.state) + mRestoreOnDraw = false + } + + } + + + } + + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + super.onLayout(changed, left, top, right, bottom) + mDraggingProxy.restoreChildrenBound() + } + + private inner class SwipeDragViewHelper internal constructor(private val parent: ViewGroup) : ViewDragHelper.Callback() { + + private var xBeforeDrag: Int = 0 + + override fun tryCaptureView(child: View, pointerId: Int): Boolean { + + xBeforeDrag = child.x.toInt() + return mDraggingProxy.isCapturedViewDraggable(child) + } + + override fun onViewDragStateChanged(state: Int) { + if (state == 0) { + mDraggingProxy.captureChildrenBound() + } + } + + override fun onViewPositionChanged(changedView: View, left: Int, top: Int, dx: Int, dy: Int) { + + if (mDraggingProxy.dragDirection == SwipeViewLayouter.DragDirection.HORIZONTAL) { + + mDraggingProxy.moveView(changedView, left) + + } else if (mDraggingProxy.dragDirection == SwipeViewLayouter.DragDirection.VERTICAL) { + throw InvalidParameterException("VerticalSwipeNotImplemented") + } + } + + override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) { + + if (mDraggingProxy.dragDirection == SwipeViewLayouter.DragDirection.VERTICAL) { + throw InvalidParameterException("VerticalSwipeNotImplemented") + } else if (mDraggingProxy.dragDirection == SwipeViewLayouter.DragDirection.HORIZONTAL) { + + var swipeResult = SwipeResult(xBeforeDrag) + val isClick = mDragHelperTouchSlop > Math.abs(mSwipeDirectionDetector.difX) + + if (!mSwipeDirectionDetector.isHorizontalScrollChangedWhileDragging && !isClick) { + swipeResult = mDraggingProxy.determineSwipeHorizontalState(xvel, mSwipeDirectionDetector, swipeState, mSwipeListener, releasedChild) + } + + if (mDragHelper!!.smoothSlideViewTo(releasedChild, swipeResult.settleX, 0)) { + ViewCompat.postInvalidateOnAnimation(parent) + + } + + mDraggingProxy.requestLayout() + + if (swipeResult.notifyListener != null && mSwipeListener != null) { + swipeResult.notifyListener?.run() + } + } + } + + override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int { + return if (swipeState.state == LEFT_OPEN || + swipeState.state == RIGHT_OPEN || + mDraggingProxy.dragDirection == SwipeViewLayouter.DragDirection.HORIZONTAL) { + 0 + } else 0 + + } + + override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int { + return if (swipeState.state == SwipeState.DragViewState.TOP_OPEN || + swipeState.state == SwipeState.DragViewState.BOTTOM_OPEN || + !mDraggingProxy.canSwipe(mSwipeDirectionDetector, swipeState.state) || + mDraggingProxy.dragDirection == SwipeViewLayouter.DragDirection.VERTICAL) { + 0 + } else mDraggingProxy.clampViewPositionHorizontal(child, left) + + } + + override fun getViewHorizontalDragRange(child: View): Int { + return width + } + + override fun getViewVerticalDragRange(child: View): Int { + return 0 + } + + } + + fun markForRestoreOnDraw(swipeState: SwipeState.DragViewState) { + this.swipeState.state = swipeState + mRestoreOnDraw = true + if (mDragHelper!!.viewDragState != KDragViewHelper.STATE_IDLE) { + mDragHelper!!.abort() + } + } + + fun closeSwipeNoAnimation() { + swipeState.state = CLOSED + mDraggingProxy.restoreState(swipeState.state) + } + + @JvmOverloads + fun openSwipe(position: Int, notifyCallback: Boolean = true) { + + val mSurfaceOpenOffsetByDragView = mDraggingProxy.getSurfaceOpenOffsetByDragView(position) + + when (position) { + LEFT_DRAG_VIEW -> { + swipeState.state = LEFT_OPEN + smoothSlideTo(mSurfaceOpenOffsetByDragView.toFloat()) + } + + RIGHT_DRAG_VIEW -> { + swipeState.state = RIGHT_OPEN + smoothSlideTo(mSurfaceOpenOffsetByDragView.toFloat()) + } + + else -> return + } + + + if (mSwipeListener != null && notifyCallback) { + notifySwipeOpened() + } + } + + fun closeSwipe() { + when (swipeState.state) { + LEFT_OPEN, RIGHT_OPEN, SwipeState.DragViewState.TOP_OPEN, SwipeState.DragViewState.BOTTOM_OPEN -> { + smoothSlideTo(SWIPE_CLOSING_POINT.toFloat()) + swipeState.state = CLOSED + } + } + } + + fun setSwipeListener(listener: SwipeListener) { + mSwipeListener = listener + } + + private fun notifySwipeOpened() { + mSwipeListener!!.onSwipeOpened(swipeState.state, true) + + } + + private fun initSwipe() { + + mDragHelper = KDragViewHelper.create(this, 1.0f, SwipeDragViewHelper(this)) + mDragHelperTouchSlop = (mDragHelper!!.touchSlop * 2).toFloat() + } + + companion object { + + private val SWIPE_CLOSING_POINT = 0 + + val LEFT_DRAG_VIEW = 1 + val RIGHT_DRAG_VIEW = 2 + val TOP_DRAG_VIEW = 3 + val BOTTOM_DRAG_VIEW = 4 + val SURFACE_VIEW = 5 + + private val TAG = SwipeLayout::class.java.getSimpleName() + } + +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeResult.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeResult.java deleted file mode 100644 index d6c264f..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeResult.java +++ /dev/null @@ -1,29 +0,0 @@ -package kaufland.com.swipelibrary; - -/** - * Created by sbra0902 on 17.03.17. - */ - -public class SwipeResult { - - private int settleX; - - private Runnable notifyListener; - - public SwipeResult(int settleX, Runnable notifyListener) { - this.settleX = settleX; - this.notifyListener = notifyListener; - } - - public SwipeResult(int settleX) { - this.settleX = settleX; - } - - public int getSettleX() { - return settleX; - } - - public Runnable getNotifyListener() { - return notifyListener; - } -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeResult.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeResult.kt new file mode 100644 index 0000000..05322c3 --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeResult.kt @@ -0,0 +1,23 @@ +package kaufland.com.swipelibrary + +/** + * Created by sbra0902 on 17.03.17. + */ + +class SwipeResult { + + var settleX: Int = 0 + private set + + var notifyListener: Runnable? + + constructor(settleX: Int, notifyListener: Runnable) { + this.settleX = settleX + this.notifyListener = notifyListener + } + + constructor(settleX: Int) { + this.settleX = settleX + this.notifyListener = null + } +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.java deleted file mode 100644 index 3e45beb..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.java +++ /dev/null @@ -1,32 +0,0 @@ -package kaufland.com.swipelibrary; - -public class SwipeState { - - private boolean isOpen; - private DragViewState mState = DragViewState.CLOSED; - private boolean isSettled; - private int settleState; - - - public enum DragViewState{ - LEFT_OPEN, RIGHT_OPEN, TOP_OPEN, BOTTOM_OPEN, CLOSED - } - - public boolean isOpen() { - return isOpen; - } - - public void setOpen(boolean open) { - isOpen = open; - } - - public DragViewState getState() { - return mState; - } - - public void setState(DragViewState mState) { - this.mState = mState; - } - - -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.kt new file mode 100644 index 0000000..dcb36df --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeState.kt @@ -0,0 +1,16 @@ +package kaufland.com.swipelibrary + +class SwipeState { + + var isOpen: Boolean = false + var state = DragViewState.CLOSED + private val isSettled: Boolean = false + private val settleState: Int = 0 + + + enum class DragViewState { + LEFT_OPEN, RIGHT_OPEN, TOP_OPEN, BOTTOM_OPEN, CLOSED + } + + +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.java deleted file mode 100644 index 560f260..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.java +++ /dev/null @@ -1,113 +0,0 @@ -package kaufland.com.swipelibrary; - -import android.view.View; -import android.view.ViewGroup; - -import java.security.InvalidParameterException; -import java.util.HashMap; -import java.util.Map; - -import kaufland.com.swipelibrary.dragengine.DraggingEngine; -import kaufland.com.swipelibrary.dragengine.LeftDragViewEngine; -import kaufland.com.swipelibrary.dragengine.RightDragViewEngine; -import kaufland.com.swipelibrary.dragengine.SurfaceViewEngine; - -import static kaufland.com.swipelibrary.SwipeLayout.LEFT_DRAG_VIEW; -import static kaufland.com.swipelibrary.SwipeLayout.RIGHT_DRAG_VIEW; -import static kaufland.com.swipelibrary.SwipeLayout.SURFACE_VIEW; -import static kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.HORIZONTAL; -import static kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.VERTICAL; - - -public class SwipeViewLayouter { - - private Map mViewEngines = new HashMap<>(); - - private Map mViews = new HashMap<>(); - - private DragDirection mDragDirection = DragDirection.NONE; - - public enum DragDirection { - HORIZONTAL, VERTICAL, NONE - } - - - public void init(ViewGroup parent) { - - mViewEngines.clear(); - - mViews.clear(); - - for (int i = 0; i < parent.getChildCount(); i++) { - - View child = parent.getChildAt(i); - - if (child instanceof DragView) { - mViews.put(((DragView) child).getViewPosition(), child); - mDragDirection = ((DragView) child).getViewPosition() <= 2 ? HORIZONTAL : VERTICAL; - } else if (child instanceof SurfaceView) { - mViews.put(SURFACE_VIEW, child); - } else { - throw new InvalidParameterException("Only DragView or SurfaceView are supported members of SwipeLayout"); - } - } - - - - for (Integer key : mViews.keySet()) { - - switch (key){ - case LEFT_DRAG_VIEW: - mViewEngines.put(LEFT_DRAG_VIEW, new LeftDragViewEngine(this)); - break; - case RIGHT_DRAG_VIEW: - mViewEngines.put(RIGHT_DRAG_VIEW, new RightDragViewEngine(this)); - break; - case SURFACE_VIEW: - mViewEngines.put(SURFACE_VIEW, new SurfaceViewEngine(this)); - break; - } - } - - if (!mViews.containsKey(SURFACE_VIEW)) { - throw new InvalidParameterException("SwipeLayout needs a SurfaceView"); - } - - if (mViews.size() <= 1) { - throw new InvalidParameterException("SwipeLayout needs at least 1 DragView"); - } - - - - - } - - public DragDirection getDragDirection() { - return mDragDirection; - } - - public DraggingEngine getDragViewEngineByPosition(int position) { - return mViewEngines.get(position); - } - - public Map getViewEngines() { - return mViewEngines; - } - - public Map getViews() { - return mViews; - } - - public SurfaceView getSurfaceView() { - return (SurfaceView) mViews.get(SURFACE_VIEW); - } - - public DragView getLeftDragView() { - return (DragView) mViews.get(LEFT_DRAG_VIEW); - } - - public DragView getRightDragView() { - return (DragView) mViews.get(RIGHT_DRAG_VIEW); - } - -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.kt new file mode 100644 index 0000000..df5e7a5 --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.kt @@ -0,0 +1,93 @@ +package kaufland.com.swipelibrary + +import android.view.View +import android.view.ViewGroup + +import java.security.InvalidParameterException +import java.util.HashMap + +import kaufland.com.swipelibrary.dragengine.DraggingEngine +import kaufland.com.swipelibrary.dragengine.LeftDragViewEngine +import kaufland.com.swipelibrary.dragengine.RightDragViewEngine +import kaufland.com.swipelibrary.dragengine.SurfaceViewEngine + +import kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.HORIZONTAL +import kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.VERTICAL + + +class SwipeViewLayouter { + + private val mViewEngines = HashMap>() + + private val mViews = HashMap() + + var dragDirection = DragDirection.NONE + private set + + val viewEngines: Map> + get() = mViewEngines + + val views: Map + get() = mViews + + val surfaceView: SurfaceView + get() = mViews[SwipeLayout.SURFACE_VIEW] as SurfaceView + + val leftDragView: DragView + get() = mViews[SwipeLayout.LEFT_DRAG_VIEW] as DragView + + val rightDragView: DragView + get() = mViews[SwipeLayout.RIGHT_DRAG_VIEW] as DragView + + enum class DragDirection { + HORIZONTAL, VERTICAL, NONE + } + + + fun init(parent: ViewGroup) { + + mViewEngines.clear() + + mViews.clear() + + for (i in 0 until parent.childCount) { + + val child = parent.getChildAt(i) + + if (child is DragView) { + mViews[child.viewPosition] = child + dragDirection = if (child.viewPosition <= 2) HORIZONTAL else VERTICAL + } else if (child is SurfaceView) { + mViews[SwipeLayout.SURFACE_VIEW] = child + } else { + throw InvalidParameterException("Only DragView or SurfaceView are supported members of SwipeLayout") + } + } + + + + for (key in mViews.keys) { + + when (key) { + SwipeLayout.LEFT_DRAG_VIEW -> mViewEngines[SwipeLayout.LEFT_DRAG_VIEW] = LeftDragViewEngine(this) + SwipeLayout.RIGHT_DRAG_VIEW -> mViewEngines[SwipeLayout.RIGHT_DRAG_VIEW] = RightDragViewEngine(this) + SwipeLayout.SURFACE_VIEW -> mViewEngines[SwipeLayout.SURFACE_VIEW] = SurfaceViewEngine(this) + } + } + + if (!mViews.containsKey(SwipeLayout.SURFACE_VIEW)) { + throw InvalidParameterException("SwipeLayout needs a SurfaceView") + } + + if (mViews.size <= 1) { + throw InvalidParameterException("SwipeLayout needs at least 1 DragView") + } + + + } + + fun DragViewEngineByPosition(position: Int): DraggingEngine<*>? { + return mViewEngines[position] + } + +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/DraggingEngine.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/DraggingEngine.java deleted file mode 100644 index 05996aa..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/DraggingEngine.java +++ /dev/null @@ -1,37 +0,0 @@ -package kaufland.com.swipelibrary.dragengine; - -import android.graphics.Rect; -import android.view.View; - -import kaufland.com.swipelibrary.DragView; -import kaufland.com.swipelibrary.SurfaceView; -import kaufland.com.swipelibrary.SwipeDirectionDetector; -import kaufland.com.swipelibrary.SwipeLayout; -import kaufland.com.swipelibrary.SwipeResult; -import kaufland.com.swipelibrary.SwipeState; -import kaufland.com.swipelibrary.SwipeViewLayouter; - -/** - * Created by sbra0902 on 29.03.17. - */ - -public interface DraggingEngine { - - void moveView(float offset, SurfaceView view, View changedView); - - void initializePosition(SwipeViewLayouter.DragDirection orientation); - - int clampViewPositionHorizontal(View child, int left); - - void restoreState(SwipeState.DragViewState state, SurfaceView view); - - T getDragView(); - - int getDragDistance(); - - int getIntermmediateDistance(); - - int getOpenOffset(); - - SwipeResult determineSwipeHorizontalState(float velocity, SwipeDirectionDetector swipeDirectionDetector, SwipeState swipeState, SwipeLayout.SwipeListener swipeListener, View releasedChild); -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/DraggingEngine.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/DraggingEngine.kt new file mode 100644 index 0000000..1af069b --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/DraggingEngine.kt @@ -0,0 +1,37 @@ +package kaufland.com.swipelibrary.dragengine + +import android.graphics.Rect +import android.view.View + +import kaufland.com.swipelibrary.DragView +import kaufland.com.swipelibrary.SurfaceView +import kaufland.com.swipelibrary.SwipeDirectionDetector +import kaufland.com.swipelibrary.SwipeLayout +import kaufland.com.swipelibrary.SwipeResult +import kaufland.com.swipelibrary.SwipeState +import kaufland.com.swipelibrary.SwipeViewLayouter + +/** + * Created by sbra0902 on 29.03.17. + */ + +interface DraggingEngine { + + val dragView: T? + + val dragDistance: Int + + val intermmediateDistance: Int + + fun openOffset(): Int + + fun moveView(offset: Float, view: SurfaceView, changedView: View) + + fun initializePosition(orientation: SwipeViewLayouter.DragDirection) + + fun clampViewPositionHorizontal(child: View, left: Int): Int + + fun restoreState(state: SwipeState.DragViewState, view: SurfaceView) + + fun determineSwipeHorizontalState(velocity: Float, swipeDirectionDetector: SwipeDirectionDetector, swipeState: SwipeState, swipeListener: SwipeLayout.SwipeListener?, releasedChild: View): SwipeResult? +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/LeftDragViewEngine.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/LeftDragViewEngine.java deleted file mode 100644 index d22a63a..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/LeftDragViewEngine.java +++ /dev/null @@ -1,135 +0,0 @@ -package kaufland.com.swipelibrary.dragengine; - -import android.graphics.Rect; -import android.view.View; - -import kaufland.com.swipelibrary.DragView; -import kaufland.com.swipelibrary.SurfaceView; -import kaufland.com.swipelibrary.SwipeDirectionDetector; -import kaufland.com.swipelibrary.SwipeLayout; -import kaufland.com.swipelibrary.SwipeResult; -import kaufland.com.swipelibrary.SwipeState; -import kaufland.com.swipelibrary.SwipeViewLayouter; - -import static kaufland.com.swipelibrary.SwipeDirectionDetector.SWIPE_DIRECTION_LEFT; -import static kaufland.com.swipelibrary.SwipeState.DragViewState.CLOSED; - -/** - * Created by sbra0902 on 29.03.17. - */ - -public class LeftDragViewEngine implements DraggingEngine { - - private SurfaceView mSurfaceView; - private DragView mDragView; - - private int mInitialXPos; - - private int mDragDistance; - - private int mIntermmediateDistance; - - private SwipeViewLayouter mLayouter; - - public LeftDragViewEngine(SwipeViewLayouter layouter) { - mLayouter = layouter; - } - - @Override - public void moveView(float offset, SurfaceView view, View changedView) { - if (!mDragView.equals(changedView)) { - mDragView.setX(view.getX() - mDragView.getWidth()); - } - } - - @Override - public void initializePosition(SwipeViewLayouter.DragDirection orientation) { - - mSurfaceView = mLayouter.getSurfaceView(); - mDragView = mLayouter.getLeftDragView(); - - mInitialXPos = (int) (mSurfaceView.getX() - mDragView.getWidth()); - mDragDistance = mDragView.getWidth(); - mIntermmediateDistance = mDragView.getSettlePointResourceId() != -1 ? mDragView.findViewById(mDragView.getSettlePointResourceId()).getRight() : mDragView.getWidth(); - - moveToInitial(); - } - - private void moveToInitial() { - mDragView.setX(mInitialXPos); - } - - @Override - public int clampViewPositionHorizontal(View child, int left) { - - if (mDragView != null && child.equals(mDragView)) { - - - if (left > 0 && !mDragView.isBouncePossible()) { - return 0; - } - - return left; - } - - return 0; - } - - @Override - public void restoreState(SwipeState.DragViewState state, SurfaceView view) { - switch (state) { - case LEFT_OPEN: - - mDragView.setX(0); - break; - case RIGHT_OPEN: - mDragView.setX((int) (mLayouter.getRightDragView().getX() - mSurfaceView.getWidth() - mDragView.getWidth())); - break; - case TOP_OPEN: - //TODO Implementation - break; - case BOTTOM_OPEN: - //TODO Implementation - break; - default: - mDragView.setX(-mDragDistance); - break; - } - } - - - @Override - public int getDragDistance() { - return mDragDistance; - } - - @Override - public int getIntermmediateDistance() { - return mIntermmediateDistance; - } - - @Override - public int getOpenOffset() { - return mDragDistance; - } - - @Override - public SwipeResult determineSwipeHorizontalState(float velocity, SwipeDirectionDetector swipeDirectionDetector, SwipeState swipeState, final SwipeLayout.SwipeListener swipeListener, View releasedChild) { - if (mDragView.equals(releasedChild) && swipeDirectionDetector.getSwipeDirection() == SWIPE_DIRECTION_LEFT && Math.abs(swipeDirectionDetector.getDifX()) > (getDragDistance() / 2)) { - swipeState.setState(SwipeState.DragViewState.CLOSED); - return new SwipeResult(-mDragView.getWidth(), new Runnable() { - @Override - public void run() { - swipeListener.onSwipeClosed(CLOSED); - } - }); - } - - return null; - } - - @Override - public DragView getDragView() { - return mDragView; - } -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/LeftDragViewEngine.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/LeftDragViewEngine.kt new file mode 100644 index 0000000..806d7da --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/LeftDragViewEngine.kt @@ -0,0 +1,96 @@ +package kaufland.com.swipelibrary.dragengine + +import android.graphics.Rect +import android.view.View + +import kaufland.com.swipelibrary.DragView +import kaufland.com.swipelibrary.SurfaceView +import kaufland.com.swipelibrary.SwipeDirectionDetector +import kaufland.com.swipelibrary.SwipeLayout +import kaufland.com.swipelibrary.SwipeResult +import kaufland.com.swipelibrary.SwipeState +import kaufland.com.swipelibrary.SwipeViewLayouter + +import kaufland.com.swipelibrary.SwipeState.DragViewState.CLOSED + +/** + * Created by sbra0902 on 29.03.17. + */ + +class LeftDragViewEngine(private val mLayouter: SwipeViewLayouter) : DraggingEngine { + + private var mSurfaceView: SurfaceView? = null + override var dragView: T? = null + private set + + private var mInitialXPos: Int = 0 + + override var dragDistance: Int = 0 + private set + + override var intermmediateDistance: Int = 0 + private set + + override fun moveView(offset: Float, view: SurfaceView, changedView: View) { + if (dragView != changedView) { + dragView!!.x = view.x - dragView!!.width + } + } + + override fun initializePosition(orientation: SwipeViewLayouter.DragDirection) { + + mSurfaceView = mLayouter.surfaceView + dragView = mLayouter.leftDragView as T + + mInitialXPos = (mSurfaceView!!.x - dragView!!.width).toInt() + dragDistance = dragView!!.width + intermmediateDistance = if (dragView!!.settlePointResourceId != -1) dragView!!.findViewById(dragView!!.settlePointResourceId).right else dragView!!.width + + moveToInitial() + } + + private fun moveToInitial() { + dragView!!.x = mInitialXPos.toFloat() + } + + override fun clampViewPositionHorizontal(child: View, left: Int): Int { + + return if (dragView != null && child == dragView) { + + + if (left > 0 && !dragView!!.isBouncePossible) { + 0 + } else left + + } else 0 + + } + + override fun restoreState(state: SwipeState.DragViewState, view: SurfaceView) { + when (state) { + SwipeState.DragViewState.LEFT_OPEN -> + + dragView!!.x = 0f + SwipeState.DragViewState.RIGHT_OPEN -> dragView!!.x = (mLayouter.rightDragView.x - mSurfaceView!!.width.toFloat() - dragView!!.width.toFloat()).toInt().toFloat() + SwipeState.DragViewState.TOP_OPEN -> { + } + SwipeState.DragViewState.BOTTOM_OPEN -> { + } + else -> dragView!!.x = (-dragDistance).toFloat() + }//TODO Implementation + //TODO Implementation + } + + override fun openOffset(): Int { + return dragDistance + } + + override fun determineSwipeHorizontalState(velocity: Float, swipeDirectionDetector: SwipeDirectionDetector, swipeState: SwipeState, swipeListener: SwipeLayout.SwipeListener?, releasedChild: View): SwipeResult? { + if (dragView == releasedChild && swipeDirectionDetector.swipeDirection == SwipeDirectionDetector.SWIPE_DIRECTION_LEFT && Math.abs(swipeDirectionDetector.difX) > dragDistance / 2) { + swipeState.state = SwipeState.DragViewState.CLOSED + return SwipeResult(-dragView!!.width, Runnable { swipeListener?.onSwipeClosed(CLOSED) }) + } + + return null + } +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/RightDragViewEngine.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/RightDragViewEngine.java deleted file mode 100644 index 2e54ae6..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/RightDragViewEngine.java +++ /dev/null @@ -1,137 +0,0 @@ -package kaufland.com.swipelibrary.dragengine; - -import android.graphics.Rect; -import android.view.View; - -import kaufland.com.swipelibrary.DragView; -import kaufland.com.swipelibrary.SurfaceView; -import kaufland.com.swipelibrary.SwipeDirectionDetector; -import kaufland.com.swipelibrary.SwipeLayout; -import kaufland.com.swipelibrary.SwipeResult; -import kaufland.com.swipelibrary.SwipeState; -import kaufland.com.swipelibrary.SwipeViewLayouter; - -import static kaufland.com.swipelibrary.SwipeDirectionDetector.SWIPE_DIRECTION_RIGHT; -import static kaufland.com.swipelibrary.SwipeState.DragViewState.CLOSED; -import static kaufland.com.swipelibrary.SwipeState.DragViewState.RIGHT_OPEN; - -/** - * Created by sbra0902 on 29.03.17. - */ - -public class RightDragViewEngine implements DraggingEngine { - - private final SwipeViewLayouter mLayouter; - private DragView mDragView; - - private SurfaceView mSurfaceView; - - private int mInitialXPos; - - private int mDragDistance; - - private int mIntermmediateDistance; - - public RightDragViewEngine(SwipeViewLayouter layouter) { - mLayouter = layouter; - } - - @Override - public void moveView(float offset, SurfaceView view, View changedView) { - - if (!mDragView.equals(changedView)) { - mDragView.setX(view.getX() + mSurfaceView.getWidth()); - } - } - - @Override - public void initializePosition(SwipeViewLayouter.DragDirection orientation) { - - mDragView = (DragView) mLayouter.getViews().get(SwipeLayout.RIGHT_DRAG_VIEW); - mSurfaceView = mLayouter.getSurfaceView(); - mDragDistance = mDragView.getWidth(); - mInitialXPos = (int) (mSurfaceView.getX() + mSurfaceView.getWidth()); - mIntermmediateDistance = mDragView.getSettlePointResourceId() != -1 ? mDragView.findViewById(mDragView.getSettlePointResourceId()).getRight() : mDragView.getWidth(); - - moveToInitial(); - } - - private void moveToInitial() { - mDragView.setX(mInitialXPos); - } - - @Override - public int clampViewPositionHorizontal(View child, int left) { - if (left < (mSurfaceView.getWidth() - getDragDistance()) && !mDragView.isBouncePossible()) { - return mSurfaceView.getWidth() - getDragDistance(); - } - - return left; - } - - @Override - public void restoreState(SwipeState.DragViewState state, SurfaceView view) { - switch (state) { - case LEFT_OPEN: - mDragView.setX(mLayouter.getLeftDragView().getWidth() + mSurfaceView.getWidth()); - break; - case RIGHT_OPEN: - mDragView.setX(0); - break; - case TOP_OPEN: - //TODO Implementation - break; - case BOTTOM_OPEN: - //TODO Implementation - break; - default: - - mDragView.setX(mSurfaceView.getWidth()); - break; - } - } - - - @Override - public int getDragDistance() { - return mDragDistance; - } - - @Override - public int getIntermmediateDistance() { - return mIntermmediateDistance; - } - - @Override - public SwipeResult determineSwipeHorizontalState(float velocity, SwipeDirectionDetector swipeDirectionDetector, SwipeState swipeState, final SwipeLayout.SwipeListener swipeListener, View releasedChild) { - if (releasedChild.equals(getDragView()) && swipeDirectionDetector.getSwipeDirection() == SWIPE_DIRECTION_RIGHT && Math.abs(swipeDirectionDetector.getDifX()) > (getDragDistance() / 2)) { - swipeState.setState(SwipeState.DragViewState.CLOSED); - return new SwipeResult(mSurfaceView.getWidth(), new Runnable() { - @Override - public void run() { - swipeListener.onSwipeClosed(CLOSED); - } - }); - }else if(releasedChild.equals(getDragView())){ - swipeState.setState(RIGHT_OPEN); - return new SwipeResult(mSurfaceView.getWidth() - getDragDistance(), new Runnable() { - @Override - public void run() { - swipeListener.onSwipeClosed(RIGHT_OPEN); - } - }); - } - - return null; - } - - @Override - public DragView getDragView() { - return mDragView; - } - - @Override - public int getOpenOffset() { - return -mDragDistance; - } -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/RightDragViewEngine.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/RightDragViewEngine.kt new file mode 100644 index 0000000..e0a2e66 --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/RightDragViewEngine.kt @@ -0,0 +1,95 @@ +package kaufland.com.swipelibrary.dragengine + +import android.graphics.Rect +import android.view.View + +import kaufland.com.swipelibrary.DragView +import kaufland.com.swipelibrary.SurfaceView +import kaufland.com.swipelibrary.SwipeDirectionDetector +import kaufland.com.swipelibrary.SwipeLayout +import kaufland.com.swipelibrary.SwipeResult +import kaufland.com.swipelibrary.SwipeState +import kaufland.com.swipelibrary.SwipeViewLayouter + +import kaufland.com.swipelibrary.SwipeState.DragViewState.CLOSED +import kaufland.com.swipelibrary.SwipeState.DragViewState.RIGHT_OPEN + +/** + * Created by sbra0902 on 29.03.17. + */ + +class RightDragViewEngine(private val mLayouter: SwipeViewLayouter) : DraggingEngine { + + override var dragView: T? = null + private set + + private var mSurfaceView: SurfaceView? = null + + private var mInitialXPos: Int = 0 + + override var dragDistance: Int = 0 + private set + + override var intermmediateDistance: Int = 0 + private set + + override fun openOffset(): Int { + return -dragDistance + } + + override fun moveView(offset: Float, view: SurfaceView, changedView: View) { + + if (dragView != changedView) { + dragView!!.x = view.x + mSurfaceView!!.width + } + } + + override fun initializePosition(orientation: SwipeViewLayouter.DragDirection) { + + dragView = mLayouter.views[SwipeLayout.RIGHT_DRAG_VIEW] as T? + mSurfaceView = mLayouter.surfaceView + dragDistance = dragView!!.width + mInitialXPos = (mSurfaceView!!.x + mSurfaceView!!.width).toInt() + intermmediateDistance = if (dragView!!.settlePointResourceId != -1) dragView!!.findViewById(dragView!!.settlePointResourceId).right else dragView!!.width + + moveToInitial() + } + + private fun moveToInitial() { + dragView!!.x = mInitialXPos.toFloat() + } + + override fun clampViewPositionHorizontal(child: View, left: Int): Int { + return if (left < mSurfaceView!!.width - dragDistance && !dragView!!.isBouncePossible) { + mSurfaceView!!.width - dragDistance + } else left + + } + + override fun restoreState(state: SwipeState.DragViewState, view: SurfaceView) { + when (state) { + SwipeState.DragViewState.LEFT_OPEN -> dragView!!.x = (mLayouter.leftDragView.width + mSurfaceView!!.width).toFloat() + RIGHT_OPEN -> dragView!!.x = 0f + SwipeState.DragViewState.TOP_OPEN -> { + } + SwipeState.DragViewState.BOTTOM_OPEN -> { + } + else -> + + dragView!!.x = mSurfaceView!!.width.toFloat() + }//TODO Implementation + //TODO Implementation + } + + override fun determineSwipeHorizontalState(velocity: Float, swipeDirectionDetector: SwipeDirectionDetector, swipeState: SwipeState, swipeListener: SwipeLayout.SwipeListener?, releasedChild: View): SwipeResult? { + if (releasedChild == dragView && swipeDirectionDetector.swipeDirection == SwipeDirectionDetector.SWIPE_DIRECTION_RIGHT && Math.abs(swipeDirectionDetector.difX) > dragDistance / 2) { + swipeState.state = SwipeState.DragViewState.CLOSED + return SwipeResult(mSurfaceView!!.width, Runnable { swipeListener?.onSwipeClosed(CLOSED) }) + } else if (releasedChild == dragView) { + swipeState.state = RIGHT_OPEN + return SwipeResult(mSurfaceView!!.width - dragDistance, Runnable { swipeListener?.onSwipeClosed(RIGHT_OPEN) }) + } + + return null + } +} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/SurfaceViewEngine.java b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/SurfaceViewEngine.java deleted file mode 100644 index 8d2c4b0..0000000 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/SurfaceViewEngine.java +++ /dev/null @@ -1,261 +0,0 @@ -package kaufland.com.swipelibrary.dragengine; - -import android.view.View; - -import kaufland.com.swipelibrary.DragView; -import kaufland.com.swipelibrary.SurfaceView; -import kaufland.com.swipelibrary.SwipeDirectionDetector; -import kaufland.com.swipelibrary.SwipeLayout; -import kaufland.com.swipelibrary.SwipeResult; -import kaufland.com.swipelibrary.SwipeState; -import kaufland.com.swipelibrary.SwipeViewLayouter; - -import static kaufland.com.swipelibrary.SwipeDirectionDetector.SWIPE_DIRECTION_LEFT; -import static kaufland.com.swipelibrary.SwipeDirectionDetector.SWIPE_DIRECTION_RIGHT; -import static kaufland.com.swipelibrary.SwipeState.DragViewState.CLOSED; -import static kaufland.com.swipelibrary.SwipeState.DragViewState.LEFT_OPEN; -import static kaufland.com.swipelibrary.SwipeState.DragViewState.RIGHT_OPEN; - -/** - * Created by sbra0902 on 29.03.17. - */ - -public class SurfaceViewEngine implements DraggingEngine { - - public static final double AUTO_OPEN_SPEED_TRESHOLD = 800.0; - public static final double LEFT_FULL_AUTO_OPEN_TRESHOLD = AUTO_OPEN_SPEED_TRESHOLD * 2; - public static final double RIGHT_FULL_AUTO_OPEN_TRESHOLD = -LEFT_FULL_AUTO_OPEN_TRESHOLD; - - private SwipeViewLayouter mLayouter; - - private SurfaceView mSurfaceView; - - private DraggingEngine mLeftDragViewEngine; - - private DraggingEngine mRightDragViewEngine; - - public SurfaceViewEngine(SwipeViewLayouter layouter) { - mLayouter = layouter; - } - - @Override - public void moveView(float offset, SurfaceView view, View changedView) { - - if (changedView.equals(mSurfaceView)) { - return; - } - - if (mLeftDragViewEngine != null && changedView.equals(mLeftDragViewEngine.getDragView())) { - mSurfaceView.setX(mLeftDragViewEngine.getDragView().getX() + mLeftDragViewEngine.getDragView().getWidth()); - } - - if (mRightDragViewEngine != null && changedView.equals(mRightDragViewEngine.getDragView())) { - mSurfaceView.setX(mRightDragViewEngine.getDragView().getX() - mSurfaceView.getWidth()); - } - } - - private boolean isMinimumDifReached(int distanceToNextState, SwipeDirectionDetector detector) { - return Math.abs(distanceToNextState / 2) <= Math.abs(detector.getDifX()) && Math.abs(detector.getDifX()) > Math.abs(detector.getDifY()) && !detector.isHorizontalScrollChangedWhileDragging(); - } - - @Override - public SwipeResult determineSwipeHorizontalState(float velocity, SwipeDirectionDetector swipeDirectionDetector, SwipeState swipeState, final SwipeLayout.SwipeListener mSwipeListener, View releasedChild) { - - if (!mSurfaceView.equals(releasedChild)) { - return null; - } - - int swipeDirection = swipeDirectionDetector.getSwipeDirection(); - - if (swipeState.getState() == SwipeState.DragViewState.CLOSED) { - if (swipeDirection == SWIPE_DIRECTION_RIGHT) { - if (mLeftDragViewEngine == null || !getDragViewForEngine(mLeftDragViewEngine).isDraggable() || !isMinimumDifReached(mLeftDragViewEngine.getIntermmediateDistance(), swipeDirectionDetector)) { - return new SwipeResult(0); - } - - swipeState.setState(SwipeState.DragViewState.LEFT_OPEN); - if (velocity > LEFT_FULL_AUTO_OPEN_TRESHOLD || Math.abs(swipeDirectionDetector.getDifX()) > (mLeftDragViewEngine.getDragDistance() / 2)) { - return new SwipeResult(mLeftDragViewEngine.getDragDistance(), new Runnable() { - @Override - public void run() { - mSwipeListener.onSwipeOpened(LEFT_OPEN, true); - } - }); - } else { - return new SwipeResult(mLeftDragViewEngine.getIntermmediateDistance(), new Runnable() { - @Override - public void run() { - mSwipeListener.onSwipeOpened(LEFT_OPEN, mLeftDragViewEngine.getIntermmediateDistance() == mLeftDragViewEngine.getDragDistance()); - } - }); - } - - } else if (swipeDirection == SWIPE_DIRECTION_LEFT) { - if (mRightDragViewEngine == null || !getDragViewForEngine(mRightDragViewEngine).isDraggable() || !isMinimumDifReached(mRightDragViewEngine.getIntermmediateDistance(), swipeDirectionDetector)) { - return new SwipeResult(0); - } - - swipeState.setState(RIGHT_OPEN); - - if (velocity < RIGHT_FULL_AUTO_OPEN_TRESHOLD || Math.abs(swipeDirectionDetector.getDifX()) > (mRightDragViewEngine.getDragDistance() / 2)) { - return new SwipeResult(-mRightDragViewEngine.getDragDistance(), new Runnable() { - @Override - public void run() { - mSwipeListener.onSwipeOpened(RIGHT_OPEN, true); - } - }); - } else { - return new SwipeResult(-mRightDragViewEngine.getIntermmediateDistance(), new Runnable() { - @Override - public void run() { - mSwipeListener.onSwipeOpened(RIGHT_OPEN, mRightDragViewEngine.getIntermmediateDistance() == mRightDragViewEngine.getDragDistance()); - } - }); - } - } - } else if (swipeState.getState() == SwipeState.DragViewState.LEFT_OPEN) { - if (swipeDirection == SWIPE_DIRECTION_RIGHT) { - swipeState.setState(LEFT_OPEN); - - return new SwipeResult(mLeftDragViewEngine.getIntermmediateDistance(), new Runnable() { - @Override - public void run() { - mSwipeListener.onBounce(LEFT_OPEN); - } - }); - - } else if (swipeDirection == SWIPE_DIRECTION_LEFT) { - - swipeState.setState(CLOSED); - return new SwipeResult(0, new Runnable() { - @Override - public void run() { - mSwipeListener.onSwipeClosed(CLOSED); - } - }); - } - } else if (swipeState.getState() == RIGHT_OPEN) { - if (swipeDirection == SWIPE_DIRECTION_RIGHT) { - - swipeState.setState(SwipeState.DragViewState.CLOSED); - return new SwipeResult(0, new Runnable() { - @Override - public void run() { - mSwipeListener.onSwipeClosed(CLOSED); - } - }); - - } else if (swipeDirection == SWIPE_DIRECTION_LEFT) { - swipeState.setState(RIGHT_OPEN); - if (velocity < RIGHT_FULL_AUTO_OPEN_TRESHOLD || Math.abs(swipeDirectionDetector.getDifX()) > (mRightDragViewEngine.getDragDistance() / 2)) { - return new SwipeResult(-mRightDragViewEngine.getDragDistance(), new Runnable() { - @Override - public void run() { - mSwipeListener.onSwipeOpened(RIGHT_OPEN, true); - } - }); - } else { - return new SwipeResult(-mRightDragViewEngine.getIntermmediateDistance(), new Runnable() { - @Override - public void run() { - mSwipeListener.onSwipeOpened(RIGHT_OPEN, mRightDragViewEngine.getIntermmediateDistance() == mRightDragViewEngine.getDragDistance()); - } - }); - } - } - - } - - return new SwipeResult(0); - } - - @Override - public void initializePosition(SwipeViewLayouter.DragDirection orientation) { - - mSurfaceView = mLayouter.getSurfaceView(); - - mLeftDragViewEngine = mLayouter.getDragViewEngineByPosition(SwipeLayout.LEFT_DRAG_VIEW); - mRightDragViewEngine = mLayouter.getDragViewEngineByPosition(SwipeLayout.RIGHT_DRAG_VIEW); - } - - @Override - public int clampViewPositionHorizontal(View child, int left) { - - if (mRightDragViewEngine == null) { - if (left <= 0) { - return 0; - } - } else { - boolean isOutsideRightRangeAndBounceNotPossible = left < -mRightDragViewEngine.getDragDistance() && !getDragViewForEngine(mRightDragViewEngine).isBouncePossible(); - if (isOutsideRightRangeAndBounceNotPossible) { - return -mRightDragViewEngine.getDragDistance(); - } - } - - - if (mLeftDragViewEngine == null) { - if (left <= -mRightDragViewEngine.getDragDistance()) { - return -mRightDragViewEngine.getDragDistance(); - } - } else { - boolean isOutsideLeftRangeAndBounceNotPossible = left > mLeftDragViewEngine.getDragDistance() && !getDragViewForEngine(mLeftDragViewEngine).isBouncePossible(); - - - if (isOutsideLeftRangeAndBounceNotPossible) { - return mLeftDragViewEngine.getDragDistance(); - } - } - - - return left; - } - - - @Override - public void restoreState(SwipeState.DragViewState state, SurfaceView view) { - - switch (state) { - case LEFT_OPEN: - mSurfaceView.setX(mLeftDragViewEngine.getDragDistance()); - break; - case RIGHT_OPEN: - mSurfaceView.setX(-mRightDragViewEngine.getDragDistance()); - break; - case TOP_OPEN: - //TODO Implementation - break; - case BOTTOM_OPEN: - //TODO Implementation - break; - default: - mSurfaceView.setX(0); - break; - } - } - - private DragView getDragViewForEngine(DraggingEngine engine) { - return engine != null ? (DragView) engine.getDragView() : null; - } - - - @Override - public int getDragDistance() { - return 0; - } - - @Override - public int getIntermmediateDistance() { - return 0; - } - - @Override - public int getOpenOffset() { - return 0; - } - - - @Override - public SurfaceView getDragView() { - return mSurfaceView; - } -} diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/SurfaceViewEngine.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/SurfaceViewEngine.kt new file mode 100644 index 0000000..3297864 --- /dev/null +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/dragengine/SurfaceViewEngine.kt @@ -0,0 +1,193 @@ +package kaufland.com.swipelibrary.dragengine + +import android.view.View + +import kaufland.com.swipelibrary.DragView +import kaufland.com.swipelibrary.SurfaceView +import kaufland.com.swipelibrary.SwipeDirectionDetector +import kaufland.com.swipelibrary.SwipeDirectionDetector.Companion.SWIPE_DIRECTION_LEFT +import kaufland.com.swipelibrary.SwipeDirectionDetector.Companion.SWIPE_DIRECTION_RIGHT +import kaufland.com.swipelibrary.SwipeLayout +import kaufland.com.swipelibrary.SwipeResult +import kaufland.com.swipelibrary.SwipeState +import kaufland.com.swipelibrary.SwipeViewLayouter + + +import kaufland.com.swipelibrary.SwipeState.DragViewState.CLOSED +import kaufland.com.swipelibrary.SwipeState.DragViewState.LEFT_OPEN +import kaufland.com.swipelibrary.SwipeState.DragViewState.RIGHT_OPEN + +/** + * Created by sbra0902 on 29.03.17. + */ + +class SurfaceViewEngine(private val mLayouter: SwipeViewLayouter) : DraggingEngine { + + override var dragView: SurfaceView? = null + private set + + private var mLeftDragViewEngine: DraggingEngine<*>? = null + + private var mRightDragViewEngine: DraggingEngine<*>? = null + + + override val dragDistance: Int + get() = 0 + + override val intermmediateDistance: Int + get() = 0 + + override fun openOffset(): Int { + return 0 + } + + override fun moveView(offset: Float, view: SurfaceView, changedView: View) { + + if (changedView == dragView) { + return + } + + //TODO WTF? + if (mLeftDragViewEngine != null && changedView == mLeftDragViewEngine!!.dragView) { + dragView!!.x = mLeftDragViewEngine!!.dragView?.x?.plus(mLeftDragViewEngine!!.dragView!!.width) ?: 0f + } + + if (mRightDragViewEngine != null && changedView == mRightDragViewEngine!!.dragView) { + dragView!!.x = mRightDragViewEngine!!.dragView?.x?.minus(dragView!!.width) ?: 0f + } + } + + private fun isMinimumDifReached(distanceToNextState: Int, detector: SwipeDirectionDetector): Boolean { + return Math.abs(distanceToNextState / 2) <= Math.abs(detector.difX) && Math.abs(detector.difX) > Math.abs(detector.difY) && !detector.isHorizontalScrollChangedWhileDragging + } + + override fun determineSwipeHorizontalState(velocity: Float, swipeDirectionDetector: SwipeDirectionDetector, swipeState: SwipeState, mSwipeListener: SwipeLayout.SwipeListener?, releasedChild: View): SwipeResult? { + + if (dragView != releasedChild) { + return null + } + + val swipeDirection = swipeDirectionDetector.swipeDirection + + if (swipeState.state == SwipeState.DragViewState.CLOSED) { + if (swipeDirection == SwipeDirectionDetector.SWIPE_DIRECTION_RIGHT) { + if (mLeftDragViewEngine == null || !getDragViewForEngine(mLeftDragViewEngine)!!.isDraggable || !isMinimumDifReached(mLeftDragViewEngine!!.intermmediateDistance, swipeDirectionDetector)) { + return SwipeResult(0) + } + + swipeState.state = SwipeState.DragViewState.LEFT_OPEN + return if (velocity > LEFT_FULL_AUTO_OPEN_TRESHOLD || Math.abs(swipeDirectionDetector.difX) > mLeftDragViewEngine!!.dragDistance / 2) { + SwipeResult(mLeftDragViewEngine!!.dragDistance, Runnable { mSwipeListener?.onSwipeOpened(LEFT_OPEN, true) }) + } else { + SwipeResult(mLeftDragViewEngine!!.intermmediateDistance, Runnable { mSwipeListener?.onSwipeOpened(LEFT_OPEN, mLeftDragViewEngine!!.intermmediateDistance == mLeftDragViewEngine!!.dragDistance) }) + } + + } else if (swipeDirection == SwipeDirectionDetector.SWIPE_DIRECTION_LEFT) { + if (mRightDragViewEngine == null || !getDragViewForEngine(mRightDragViewEngine)!!.isDraggable || !isMinimumDifReached(mRightDragViewEngine!!.intermmediateDistance, swipeDirectionDetector)) { + return SwipeResult(0) + } + + swipeState.state = RIGHT_OPEN + + return if (velocity < RIGHT_FULL_AUTO_OPEN_TRESHOLD || Math.abs(swipeDirectionDetector.difX) > mRightDragViewEngine!!.dragDistance / 2) { + SwipeResult(-mRightDragViewEngine!!.dragDistance, Runnable { mSwipeListener?.onSwipeOpened(RIGHT_OPEN, true) }) + } else { + SwipeResult(-mRightDragViewEngine!!.intermmediateDistance, Runnable { mSwipeListener?.onSwipeOpened(RIGHT_OPEN, mRightDragViewEngine!!.intermmediateDistance == mRightDragViewEngine!!.dragDistance) }) + } + } + } else if (swipeState.state == SwipeState.DragViewState.LEFT_OPEN) { + if (swipeDirection == SWIPE_DIRECTION_RIGHT) { + swipeState.state = LEFT_OPEN + + return SwipeResult(mLeftDragViewEngine!!.intermmediateDistance, Runnable { mSwipeListener?.onBounce(LEFT_OPEN) }) + + } else if (swipeDirection == SWIPE_DIRECTION_LEFT) { + + swipeState.state = CLOSED + return SwipeResult(0, Runnable { mSwipeListener?.onSwipeClosed(CLOSED) }) + } + } else if (swipeState.state == RIGHT_OPEN) { + if (swipeDirection == SWIPE_DIRECTION_RIGHT) { + + swipeState.state = SwipeState.DragViewState.CLOSED + return SwipeResult(0, Runnable { mSwipeListener?.onSwipeClosed(CLOSED) }) + + } else if (swipeDirection == SWIPE_DIRECTION_LEFT) { + swipeState.state = RIGHT_OPEN + return if (velocity < RIGHT_FULL_AUTO_OPEN_TRESHOLD || Math.abs(swipeDirectionDetector.difX) > mRightDragViewEngine!!.dragDistance / 2) { + SwipeResult(-mRightDragViewEngine!!.dragDistance, Runnable { mSwipeListener?.onSwipeOpened(RIGHT_OPEN, true) }) + } else { + SwipeResult(-mRightDragViewEngine!!.intermmediateDistance, Runnable { mSwipeListener?.onSwipeOpened(RIGHT_OPEN, mRightDragViewEngine!!.intermmediateDistance == mRightDragViewEngine!!.dragDistance) }) + } + } + + } + + return SwipeResult(0) + } + + override fun initializePosition(orientation: SwipeViewLayouter.DragDirection) { + + dragView = mLayouter.surfaceView + + mLeftDragViewEngine = mLayouter.DragViewEngineByPosition(SwipeLayout.LEFT_DRAG_VIEW) + mRightDragViewEngine = mLayouter.DragViewEngineByPosition(SwipeLayout.RIGHT_DRAG_VIEW) + } + + override fun clampViewPositionHorizontal(child: View, left: Int): Int { + + if (mRightDragViewEngine == null) { + if (left <= 0) { + return 0 + } + } else { + val isOutsideRightRangeAndBounceNotPossible = left < -mRightDragViewEngine!!.dragDistance && !getDragViewForEngine(mRightDragViewEngine)!!.isBouncePossible + if (isOutsideRightRangeAndBounceNotPossible) { + return -mRightDragViewEngine!!.dragDistance + } + } + + + if (mLeftDragViewEngine == null) { + if (left <= -mRightDragViewEngine!!.dragDistance) { + return -mRightDragViewEngine!!.dragDistance + } + } else { + val isOutsideLeftRangeAndBounceNotPossible = left > mLeftDragViewEngine!!.dragDistance && !getDragViewForEngine(mLeftDragViewEngine)!!.isBouncePossible + + + if (isOutsideLeftRangeAndBounceNotPossible) { + return mLeftDragViewEngine!!.dragDistance + } + } + + + return left + } + + + override fun restoreState(state: SwipeState.DragViewState, view: SurfaceView) { + + when (state) { + LEFT_OPEN -> dragView!!.x = mLeftDragViewEngine!!.dragDistance.toFloat() + RIGHT_OPEN -> dragView!!.x = (-mRightDragViewEngine!!.dragDistance).toFloat() + SwipeState.DragViewState.TOP_OPEN -> { + } + SwipeState.DragViewState.BOTTOM_OPEN -> { + } + else -> dragView!!.x = 0f + }//TODO Implementation + //TODO Implementation + } + + private fun getDragViewForEngine(engine: DraggingEngine<*>?): DragView? { + return if (engine != null) engine.dragView as DragView else null + } + + companion object { + + val AUTO_OPEN_SPEED_TRESHOLD = 800.0 + val LEFT_FULL_AUTO_OPEN_TRESHOLD = AUTO_OPEN_SPEED_TRESHOLD * 2 + val RIGHT_FULL_AUTO_OPEN_TRESHOLD = -LEFT_FULL_AUTO_OPEN_TRESHOLD + } +} diff --git a/swipelibrary/src/test/java/kaufland/com/swipelibrary/ExampleUnitTest.java b/swipelibrary/src/test/java/kaufland/com/swipelibrary/ExampleUnitTest.java deleted file mode 100644 index 038d1a0..0000000 --- a/swipelibrary/src/test/java/kaufland/com/swipelibrary/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package kaufland.com.swipelibrary; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/swipelibrary/src/test/java/kaufland/com/swipelibrary/ExampleUnitTest.kt b/swipelibrary/src/test/java/kaufland/com/swipelibrary/ExampleUnitTest.kt new file mode 100644 index 0000000..ba3c674 --- /dev/null +++ b/swipelibrary/src/test/java/kaufland/com/swipelibrary/ExampleUnitTest.kt @@ -0,0 +1,18 @@ +package kaufland.com.swipelibrary + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see [Testing documentation](http://d.android.com/tools/testing) + */ +class ExampleUnitTest { + @Test + @Throws(Exception::class) + fun addition_isCorrect() { + assertEquals(4, (2 + 2).toLong()) + } +} \ No newline at end of file From 6e6d177a1f5e2ef46203d1be7459e02628bf430d Mon Sep 17 00:00:00 2001 From: Sven Braune Date: Wed, 22 May 2019 11:11:21 +0200 Subject: [PATCH 3/4] # migrated to Kotlin --- .../java/kaufland/com/swipelibrary/SwipeLayout.kt | 6 +++--- .../kaufland/com/swipelibrary/SwipeViewLayouter.kt | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.kt index 6b48a92..46b7ccf 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.kt +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeLayout.kt @@ -26,11 +26,11 @@ import kaufland.com.swipelibrary.SwipeViewLayouter.DragDirection.VERTICAL class SwipeLayout : FrameLayout { var swipeState = SwipeState() - protected set + private set - protected var mSwipeDirectionDetector = SwipeDirectionDetector() + private var mSwipeDirectionDetector = SwipeDirectionDetector() - protected var mDraggingProxy = DraggingProxy() + private var mDraggingProxy = DraggingProxy() private var mDragHelper: KDragViewHelper? = null diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.kt index df5e7a5..60ff160 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.kt +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/SwipeViewLayouter.kt @@ -54,13 +54,13 @@ class SwipeViewLayouter { val child = parent.getChildAt(i) - if (child is DragView) { - mViews[child.viewPosition] = child - dragDirection = if (child.viewPosition <= 2) HORIZONTAL else VERTICAL - } else if (child is SurfaceView) { - mViews[SwipeLayout.SURFACE_VIEW] = child - } else { - throw InvalidParameterException("Only DragView or SurfaceView are supported members of SwipeLayout") + when (child) { + is DragView -> { + mViews[child.viewPosition] = child + dragDirection = if (child.viewPosition <= 2) HORIZONTAL else VERTICAL + } + is SurfaceView -> mViews[SwipeLayout.SURFACE_VIEW] = child + else -> throw InvalidParameterException("Only DragView or SurfaceView are supported members of SwipeLayout") } } From 410ef263fd7bdf412acb9990e3c24c83af9aeed5 Mon Sep 17 00:00:00 2001 From: Sven Braune Date: Wed, 22 May 2019 11:51:11 +0200 Subject: [PATCH 4/4] # migrated to Kotlin --- .../src/main/java/kaufland/com/swipelibrary/LayoutCache.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.kt b/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.kt index d5d9612..6bc086f 100644 --- a/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.kt +++ b/swipelibrary/src/main/java/kaufland/com/swipelibrary/LayoutCache.kt @@ -10,7 +10,7 @@ import java.util.HashMap class LayoutCache { - internal var mLayoutCache: MutableMap = HashMap() + private var mLayoutCache: MutableMap = HashMap() fun restoreOnLayout() {