diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..e01273c
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
diff --git a/default.properties b/default.properties
new file mode 100644
index 0000000..ecd5d12
--- /dev/null
+++ b/default.properties
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2013 47 Degrees, LLC
+# http://47deg.com
+# hello@47deg.com
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# File used by Eclipse to determine the target system
+# Project target.
+target=android-16
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..5462a88
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,188 @@
+
+
+
+
+ 4.0.0
+ com.fortysevendeg.android
+ swipelistview
+ 1.0-SNAPSHOT
+ apklib
+ android-swipelistview-lib
+ An Android List View implementation with support for drawable cells and many other swipe related features
+ https://github.com/47deg/${project.name-github}
+ 2013
+
+
+ 4.1.1.4
+ android-swipelistview
+ master
+ /Applications/android-sdk-macosx
+
+
+
+ https://github.com/47deg/${project.name-github}/tree/${scm.branch}
+ scm:git:git://github.com/47deg/${project.name-github}.git
+ scm:git:ssh://git@github.com/47deg/${project.name-github}.git
+ HEAD
+
+
+
+ Github Issue Tracking
+ https://github.com/47deg/${project.name-github}/issues
+
+
+
+
+ sonatype-nexus-snapshots
+ Sonatype Nexus snapshot repository
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ sonatype-nexus-staging
+ Sonatype Nexus release repository
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+
+
+
+ Apache 2.0
+ http://www.apache.org/licenses/LICENSE-2.0
+
+
+
+
+
+ com.google.android
+ android
+ ${platform.version}
+ provided
+
+
+ com.google.android
+ support-v13
+ r8
+
+
+ com.nineoldandroids
+ nineoldandroids
+ 2.4.0
+
+
+
+
+
+
+ com.jayway.maven.plugins.android.generation2
+ android-maven-plugin
+ 3.5.0
+
+ ${project.basedir}/AndroidManifest.xml
+ ${project.basedir}/assets
+ ${project.basedir}/res
+ ${project.basedir}/src/main/native
+
+ 16
+
+ true
+
+ true
+
+
+
+ maven-compiler-plugin
+ 2.5.1
+
+ 1.6
+ 1.6
+
+
+
+
+ com.github.github
+ downloads-maven-plugin
+ 0.5
+
+ ${project.version} release of ${project.name}
+ true
+ true
+
+
+ *.jar
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 2.2.2
+
+ -Dgpg.passphrase=${gpg.passphrase}
+
+
+
+ maven-assembly-plugin
+
+
+ jar-with-dependencies
+
+
+
+
+
+
+
+
+
+
+ release-sign-artifacts
+
+
+ performRelease
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.4
+
+ ${gpg.passphrase}
+
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
new file mode 100644
index 0000000..475b407
--- /dev/null
+++ b/res/values/attrs.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/fortysevendeg/android/swipelistview/SwipeListView.java b/src/main/java/com/fortysevendeg/android/swipelistview/SwipeListView.java
new file mode 100644
index 0000000..8768aec
--- /dev/null
+++ b/src/main/java/com/fortysevendeg/android/swipelistview/SwipeListView.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2013 47 Degrees, LLC
+ * http://47deg.com
+ * hello@47deg.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.fortysevendeg.android.swipelistview;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.ViewConfigurationCompat;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+public class SwipeListView extends ListView {
+
+ public final static int SWIPE_MODE_NONE = 0;
+ public final static int SWIPE_MODE_BOTH = 1;
+ public final static int SWIPE_MODE_RIGHT = 2;
+ public final static int SWIPE_MODE_LEFT = 3;
+
+ public final static int SWIPE_ACTION_REVEAL = 0;
+ public final static int SWIPE_ACTION_DISMISS = 1;
+ public final static int SWIPE_ACTION_CHECK = 2;
+ public final static int SWIPE_ACTION_NONE = 3;
+
+ private final static int TOUCH_STATE_REST = 0;
+ private final static int TOUCH_STATE_SCROLLING_X = 1;
+ private final static int TOUCH_STATE_SCROLLING_Y = 2;
+
+ private int touchState = TOUCH_STATE_REST;
+
+ private float lastMotionX;
+ private float lastMotionY;
+ private int touchSlop;
+
+ private SwipeListViewListener swipeListViewListener;
+
+ private SwipeListViewTouchListener touchListener;
+
+ public SwipeListView(Context context) {
+ super(context);
+ init(null);
+ }
+
+ public SwipeListView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs);
+ }
+
+ public SwipeListView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(attrs);
+ }
+
+ private void init(AttributeSet attrs) {
+
+ int swipeMode = SWIPE_MODE_BOTH;
+ boolean swipeOpenOnLongPress = true;
+ boolean swipeCloseAllItemsWhenMoveList = true;
+ int swipeFrontView = 0;
+ int swipeBackView = 0;
+ long swipeAnimationTime = 0;
+ float swipeOffsetLeft = 0;
+ float swipeOffsetRight = 0;
+
+ int swipeActionLeft = SWIPE_ACTION_REVEAL;
+ int swipeActionRight = SWIPE_ACTION_REVEAL;
+
+ if (attrs != null) {
+ TypedArray styled = getContext().obtainStyledAttributes(attrs, R.styleable.SwipeListView);
+ swipeMode = styled.getInt(R.styleable.SwipeListView_swipeMode, SWIPE_MODE_BOTH);
+ swipeActionLeft = styled.getInt(R.styleable.SwipeListView_swipeActionLeft, SWIPE_ACTION_REVEAL);
+ swipeActionRight = styled.getInt(R.styleable.SwipeListView_swipeActionRight, SWIPE_ACTION_REVEAL);
+ swipeOffsetLeft = styled.getDimension(R.styleable.SwipeListView_swipeOffsetLeft, 0);
+ swipeOffsetRight = styled.getDimension(R.styleable.SwipeListView_swipeOffsetRight, 0);
+ swipeOpenOnLongPress = styled.getBoolean(R.styleable.SwipeListView_swipeOpenOnLongPress, true);
+ swipeAnimationTime = styled.getInteger(R.styleable.SwipeListView_swipeAnimationTime, 0);
+ swipeCloseAllItemsWhenMoveList = styled.getBoolean(R.styleable.SwipeListView_swipeCloseAllItemsWhenMoveList, true);
+ swipeFrontView = styled.getResourceId(R.styleable.SwipeListView_swipeFrontView, 0);
+ swipeBackView = styled.getResourceId(R.styleable.SwipeListView_swipeBackView, 0);
+ }
+
+ if (swipeFrontView == 0 || swipeBackView == 0) {
+ throw new RuntimeException("Missed attribute swipeFrontView or swipeBackView");
+ }
+
+ final ViewConfiguration configuration = ViewConfiguration.get(getContext());
+ touchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
+ touchListener = new SwipeListViewTouchListener(this, swipeFrontView, swipeBackView);
+ if (swipeAnimationTime > 0) {
+ touchListener.setAnimationTime(swipeAnimationTime);
+ }
+ touchListener.setOffsetRight(swipeOffsetRight);
+ touchListener.setOffsetLeft(swipeOffsetLeft);
+ touchListener.setSwipeActionLeft(swipeActionLeft);
+ touchListener.setSwipeActionRight(swipeActionRight);
+ touchListener.setSwipeMode(swipeMode);
+ touchListener.setSwipeCloseAllItemsWhenMoveList(swipeCloseAllItemsWhenMoveList);
+ touchListener.setSwipeOpenOnLongPress(swipeOpenOnLongPress);
+ setOnTouchListener(touchListener);
+ setOnScrollListener(touchListener.makeScrollListener());
+ }
+
+ @Override
+ public void setAdapter(ListAdapter adapter) {
+ super.setAdapter(adapter);
+ touchListener.resetItems();
+ adapter.registerDataSetObserver(new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ super.onChanged();
+ onListChanged();
+ touchListener.resetItems();
+ }
+ });
+ }
+
+ public void openAnimate(int position) {
+ touchListener.openAnimate(position);
+ }
+
+ public void closeAnimate(int position) {
+ touchListener.closeAnimate(position);
+ }
+
+ protected void onDismiss(int[] reverseSortedPositions) {
+ if (swipeListViewListener != null) {
+ swipeListViewListener.onDismiss(reverseSortedPositions);
+ }
+ }
+
+ protected void onClickFrontView(int position) {
+ if (swipeListViewListener != null) {
+ swipeListViewListener.onClickFrontView(position);
+ }
+ }
+
+ protected void onClickBackView(int position) {
+ if (swipeListViewListener != null) {
+ swipeListViewListener.onClickBackView(position);
+ }
+ }
+
+ protected void onOpened(int position, boolean toRight) {
+ if (swipeListViewListener != null) {
+ swipeListViewListener.onOpened(position, toRight);
+ }
+ }
+
+ protected void onClosed(int position, boolean fromRight) {
+ if (swipeListViewListener != null) {
+ swipeListViewListener.onClosed(position, fromRight);
+ }
+ }
+
+ protected void onListChanged() {
+ if (swipeListViewListener != null) {
+ swipeListViewListener.onListChanged();
+ }
+ }
+
+ protected void onMove(int position, float x) {
+ if (swipeListViewListener != null) {
+ swipeListViewListener.onMove(position, x);
+ }
+ }
+
+ public void setSwipeListViewListener(SwipeListViewListener swipeListViewListener) {
+ this.swipeListViewListener = swipeListViewListener;
+ }
+
+ public void resetScrolling() {
+ touchState = TOUCH_STATE_REST;
+ }
+
+ public void setOffsetRight(float offsetRight) {
+ touchListener.setOffsetRight(offsetRight);
+ }
+
+ public void setOffsetLeft(float offsetLeft) {
+ touchListener.setOffsetLeft(offsetLeft);
+ }
+
+ public void setSwipeCloseAllItemsWhenMoveList(boolean swipeCloseAllItemsWhenMoveList) {
+ touchListener.setSwipeCloseAllItemsWhenMoveList(swipeCloseAllItemsWhenMoveList);
+ }
+
+ public void setSwipeOpenOnLongPress(boolean swipeOpenOnLongPress) {
+ touchListener.setSwipeOpenOnLongPress(swipeOpenOnLongPress);
+ }
+
+ public void setSwipeMode(int swipeMode) {
+ touchListener.setSwipeMode(swipeMode);
+ }
+
+ public float getSwipeActionLeft() {
+ return touchListener.getSwipeActionLeft();
+ }
+
+ public void setSwipeActionLeft(int swipeActionLeft) {
+ touchListener.setSwipeActionLeft(swipeActionLeft);
+ }
+
+ public float getSwipeActionRight() {
+ return touchListener.getSwipeActionRight();
+ }
+
+ public void setSwipeActionRight(int swipeActionRight) {
+ touchListener.setSwipeActionRight(swipeActionRight);
+ }
+
+ public void setAnimationTime(long animationTime) {
+ touchListener.setAnimationTime(animationTime);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ int action = MotionEventCompat.getActionMasked(ev);
+ final float x = ev.getX();
+ final float y = ev.getY();
+
+ if (touchState == TOUCH_STATE_SCROLLING_X) {
+ return touchListener.onTouch(this, ev);
+ }
+
+ switch (action) {
+ case MotionEvent.ACTION_MOVE:
+ checkInMovingX(x, y);
+ return touchState==TOUCH_STATE_SCROLLING_Y;
+ case MotionEvent.ACTION_DOWN:
+ touchListener.onTouch(this, ev);
+ lastMotionX = x;
+ lastMotionY = y;
+ return false;
+ case MotionEvent.ACTION_CANCEL:
+ touchState = TOUCH_STATE_REST;
+ break;
+ case MotionEvent.ACTION_UP:
+ touchListener.onTouch(this, ev);
+ touchState = TOUCH_STATE_REST;
+ return touchState==TOUCH_STATE_SCROLLING_Y;
+ default:
+ break;
+ }
+
+ return true;
+ }
+
+ private void checkInMovingX(float x, float y) {
+ final int xDiff = (int) Math.abs(x - lastMotionX);
+ final int yDiff = (int) Math.abs(y - lastMotionY);
+
+ final int touchSlop = this.touchSlop;
+ boolean xMoved = xDiff > touchSlop;
+ boolean yMoved = yDiff > touchSlop;
+
+ if (xMoved) {
+ touchState = TOUCH_STATE_SCROLLING_X;
+ lastMotionX = x;
+ lastMotionY = y;
+ }
+
+ if (yMoved) {
+ touchState = TOUCH_STATE_SCROLLING_Y;
+ lastMotionX = x;
+ lastMotionY = y;
+ }
+ }
+
+}
diff --git a/src/main/java/com/fortysevendeg/android/swipelistview/SwipeListViewListener.java b/src/main/java/com/fortysevendeg/android/swipelistview/SwipeListViewListener.java
new file mode 100644
index 0000000..3f4efcc
--- /dev/null
+++ b/src/main/java/com/fortysevendeg/android/swipelistview/SwipeListViewListener.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 47 Degrees, LLC
+ * http://47deg.com
+ * hello@47deg.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.fortysevendeg.android.swipelistview;
+
+public interface SwipeListViewListener {
+
+ void onOpened(int position, boolean toRight);
+
+ void onClosed(int position, boolean fromRight);
+
+ void onListChanged();
+
+ void onMove(int position, float x);
+
+ void onClickFrontView(int position);
+
+ void onClickBackView(int position);
+
+ void onDismiss(int[] reverseSortedPositions);
+
+}
diff --git a/src/main/java/com/fortysevendeg/android/swipelistview/SwipeListViewTouchListener.java b/src/main/java/com/fortysevendeg/android/swipelistview/SwipeListViewTouchListener.java
new file mode 100644
index 0000000..7117577
--- /dev/null
+++ b/src/main/java/com/fortysevendeg/android/swipelistview/SwipeListViewTouchListener.java
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2013 47 Degrees, LLC
+ * http://47deg.com
+ * hello@47deg.com
+ *
+ * Copyright 2012 Roman Nurik
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.fortysevendeg.android.swipelistview;
+
+import android.graphics.Rect;
+import android.view.*;
+import android.widget.AbsListView;
+import android.widget.ListView;
+import com.nineoldandroids.animation.Animator;
+import com.nineoldandroids.animation.AnimatorListenerAdapter;
+import com.nineoldandroids.animation.ValueAnimator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static com.nineoldandroids.view.ViewHelper.setAlpha;
+import static com.nineoldandroids.view.ViewHelper.setTranslationX;
+import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
+
+public class SwipeListViewTouchListener implements View.OnTouchListener {
+
+ private int swipeMode = SwipeListView.SWIPE_MODE_BOTH;
+ private boolean swipeOpenOnLongPress = true;
+ private boolean swipeCloseAllItemsWhenMoveList = true;
+
+ private int swipeFrontView = 0;
+ private int swipeBackView = 0;
+
+ // Cached ViewConfiguration and system-wide constant values
+ private int slop;
+ private int minFlingVelocity;
+ private int maxFlingVelocity;
+ private long configShortAnimationTime;
+ private long animationTime;
+
+ private float offsetLeft = 0;
+ private float offsetRight = 0;
+
+ // Fixed properties
+ private SwipeListView swipeListView;
+ private int viewWidth = 1; // 1 and not 0 to prevent dividing by zero
+
+ private List pendingDismisses = new ArrayList();
+ private int dismissAnimationRefCount = 0;
+
+ private float downX;
+ private boolean swiping;
+ private VelocityTracker velocityTracker;
+ private int downPosition;
+ private View parentView;
+ private View frontView;
+ private View backView;
+ private boolean paused;
+
+ private int swipeCurrentAction = SwipeListView.SWIPE_ACTION_NONE;
+
+ private int swipeActionLeft = SwipeListView.SWIPE_ACTION_REVEAL;
+ private int swipeActionRight = SwipeListView.SWIPE_ACTION_REVEAL;
+
+ private List opened = new ArrayList();
+ private List openedRight = new ArrayList();
+
+ public SwipeListViewTouchListener(SwipeListView swipeListView, int swipeFrontView, int swipeBackView) {
+ this.swipeFrontView = swipeFrontView;
+ this.swipeBackView = swipeBackView;
+ ViewConfiguration vc = ViewConfiguration.get(swipeListView.getContext());
+ slop = vc.getScaledTouchSlop();
+ minFlingVelocity = vc.getScaledMinimumFlingVelocity();
+ maxFlingVelocity = vc.getScaledMaximumFlingVelocity();
+ configShortAnimationTime = swipeListView.getContext().getResources().getInteger(android.R.integer.config_shortAnimTime);
+ animationTime = configShortAnimationTime;
+ this.swipeListView = swipeListView;
+ }
+
+ private void setParentView(View parentView) {
+ this.parentView = parentView;
+ }
+
+ private void setFrontView(View frontView) {
+ this.frontView = frontView;
+ frontView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ swipeListView.onClickFrontView(downPosition);
+ }
+ });
+ if (swipeOpenOnLongPress) {
+ frontView.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ openAnimate(downPosition);
+ return false;
+ }
+ });
+ }
+ }
+
+ private void setBackView(View backView) {
+ this.backView = backView;
+ backView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ swipeListView.onClickBackView(downPosition);
+ }
+ });
+ }
+
+ public void setAnimationTime(long animationTime) {
+ if (animationTime > 0) {
+ this.animationTime = animationTime;
+ } else {
+ this.animationTime = configShortAnimationTime;
+ }
+ }
+
+ public void setOffsetRight(float offsetRight) {
+ this.offsetRight = offsetRight;
+ }
+
+ public void setOffsetLeft(float offsetLeft) {
+ this.offsetLeft = offsetLeft;
+ }
+
+ public void setSwipeCloseAllItemsWhenMoveList(boolean swipeCloseAllItemsWhenMoveList) {
+ this.swipeCloseAllItemsWhenMoveList = swipeCloseAllItemsWhenMoveList;
+ }
+
+ public void setSwipeOpenOnLongPress(boolean swipeOpenOnLongPress) {
+ this.swipeOpenOnLongPress = swipeOpenOnLongPress;
+ }
+
+ public void setSwipeMode(int swipeMode) {
+ this.swipeMode = swipeMode;
+ }
+
+ public float getSwipeActionLeft() {
+ return swipeActionLeft;
+ }
+
+ public void setSwipeActionLeft(int swipeActionLeft) {
+ this.swipeActionLeft = swipeActionLeft;
+ }
+
+ public float getSwipeActionRight() {
+ return swipeActionRight;
+ }
+
+ public void setSwipeActionRight(int swipeActionRight) {
+ this.swipeActionRight = swipeActionRight;
+ }
+
+ public void resetItems() {
+ if (swipeListView.getAdapter() != null) {
+ int count = swipeListView.getAdapter().getCount();
+ for (int i = opened.size(); i <= count; i++) {
+ opened.add(false);
+ openedRight.add(false);
+ }
+ }
+ }
+
+ protected void openAnimate(int position) {
+ openAnimate(swipeListView.getChildAt(position - swipeListView.getFirstVisiblePosition()).findViewById(swipeFrontView), position);
+ }
+
+ protected void closeAnimate(int position) {
+ closeAnimate(swipeListView.getChildAt(position - swipeListView.getFirstVisiblePosition()).findViewById(swipeFrontView), position);
+ }
+
+ private void openAnimate(View view, int position) {
+ if (!opened.get(position)) {
+ generateRevealAnimate(view, true, false, position);
+ }
+ }
+
+ private void closeAnimate(View view, int position) {
+ if (opened.get(position)) {
+ generateRevealAnimate(view, true, false, position);
+ }
+ }
+
+ private void generateAnimate(final View view, final boolean swap, final boolean swapRight, final int position) {
+ if (swipeCurrentAction == SwipeListView.SWIPE_ACTION_REVEAL) {
+ generateRevealAnimate(view, swap, swapRight, position);
+ }
+ if (swipeCurrentAction == SwipeListView.SWIPE_ACTION_DISMISS) {
+ generateDismissAnimate(parentView, swap, swapRight, position);
+ }
+ }
+
+ private void generateDismissAnimate(final View view, final boolean swap, final boolean swapRight, final int position) {
+ int moveTo = 0;
+ if (opened.get(position)) {
+ if (!swap) {
+ moveTo = openedRight.get(position) ? (int) (viewWidth - offsetRight) : (int) (-viewWidth + offsetLeft);
+ }
+ } else {
+ if (swap) {
+ moveTo = swapRight ? (int) (viewWidth - offsetRight) : (int) (-viewWidth + offsetLeft);
+ }
+ }
+
+ int alpha = 1;
+ if (swap) {
+ ++dismissAnimationRefCount;
+ alpha = 0;
+ }
+
+ animate(view)
+ .translationX(moveTo)
+ .alpha(alpha)
+ .setDuration(animationTime)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (swap) {
+ performDismiss(view, position);
+ }
+ }
+ });
+
+ }
+
+ private void generateRevealAnimate(final View view, final boolean swap, final boolean swapRight, final int position) {
+ int moveTo = 0;
+ if (opened.get(position)) {
+ if (!swap) {
+ moveTo = openedRight.get(position) ? (int) (viewWidth - offsetRight) : (int) (-viewWidth + offsetLeft);
+ }
+ } else {
+ if (swap) {
+ moveTo = swapRight ? (int) (viewWidth - offsetRight) : (int) (-viewWidth + offsetLeft);
+ }
+ }
+
+ animate(view)
+ .translationX(moveTo)
+ .setDuration(animationTime)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ swipeListView.resetScrolling();
+ if (swap) {
+ boolean aux = !opened.get(position);
+ opened.set(position, aux);
+ if (aux) {
+ swipeListView.onOpened(position, swapRight);
+ openedRight.set(position, swapRight);
+ } else {
+ swipeListView.onClosed(position, openedRight.get(position));
+ }
+ }
+ }
+ });
+ }
+
+ public void setEnabled(boolean enabled) {
+ paused = !enabled;
+ }
+
+ public AbsListView.OnScrollListener makeScrollListener() {
+ return new AbsListView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(AbsListView absListView, int scrollState) {
+ setEnabled(scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
+ if (swipeCloseAllItemsWhenMoveList && scrollState == SCROLL_STATE_TOUCH_SCROLL) {
+ closeItemsOpened();
+ }
+ if (scrollState != AbsListView.OnScrollListener.SCROLL_STATE_FLING && scrollState != SCROLL_STATE_TOUCH_SCROLL) {
+ swipeListView.resetScrolling();
+ }
+ }
+
+ @Override
+ public void onScroll(AbsListView absListView, int i, int i1, int i2) {
+ }
+ };
+ }
+
+ private void closeItemsOpened() {
+ if (opened != null) {
+ int start = swipeListView.getFirstVisiblePosition();
+ int end = swipeListView.getLastVisiblePosition();
+ for (int i = start; i <= end; i++) {
+ if (opened.get(i)) {
+ closeAnimate(swipeListView.getChildAt(i - start).findViewById(swipeFrontView), i);
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ if (viewWidth < 2) {
+ viewWidth = swipeListView.getWidth();
+ }
+
+ switch (motionEvent.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN: {
+ if (paused) {
+ return false;
+ }
+ swipeCurrentAction = SwipeListView.SWIPE_ACTION_NONE;
+ Rect rect = new Rect();
+ int childCount = swipeListView.getChildCount();
+ int[] listViewCoords = new int[2];
+ swipeListView.getLocationOnScreen(listViewCoords);
+ int x = (int) motionEvent.getRawX() - listViewCoords[0];
+ int y = (int) motionEvent.getRawY() - listViewCoords[1];
+ View child;
+ for (int i = 0; i < childCount; i++) {
+ child = swipeListView.getChildAt(i);
+ child.getHitRect(rect);
+ if (rect.contains(x, y)) {
+ setParentView(child);
+ setFrontView(child.findViewById(swipeFrontView));
+ downX = motionEvent.getRawX();
+ downPosition = swipeListView.getPositionForView(child);
+
+ frontView.setClickable(!opened.get(downPosition));
+ frontView.setLongClickable(!opened.get(downPosition));
+
+ velocityTracker = VelocityTracker.obtain();
+ velocityTracker.addMovement(motionEvent);
+ if (swipeBackView > 0) {
+ setBackView(child.findViewById(swipeBackView));
+ }
+ break;
+ }
+ }
+ view.onTouchEvent(motionEvent);
+ return true;
+ }
+
+ case MotionEvent.ACTION_UP: {
+ if (velocityTracker == null || !swiping) {
+ break;
+ }
+
+ float deltaX = motionEvent.getRawX() - downX;
+ velocityTracker.addMovement(motionEvent);
+ velocityTracker.computeCurrentVelocity(1000);
+ float velocityX = Math.abs(velocityTracker.getXVelocity());
+ if (!opened.get(downPosition)) {
+ if (swipeMode == SwipeListView.SWIPE_MODE_LEFT && velocityTracker.getXVelocity() > 0) {
+ velocityX = 0;
+ }
+ if (swipeMode == SwipeListView.SWIPE_MODE_RIGHT && velocityTracker.getXVelocity() < 0) {
+ velocityX = 0;
+ }
+ }
+ float velocityY = Math.abs(velocityTracker.getYVelocity());
+ boolean swap = false;
+ boolean swapRight = false;
+ if (Math.abs(deltaX) > viewWidth / 2) {
+ swap = true;
+ swapRight = deltaX > 0;
+ } else if (minFlingVelocity <= velocityX && velocityX <= maxFlingVelocity && velocityY < velocityX) {
+ swap = true;
+ swapRight = velocityTracker.getXVelocity() > 0;
+ }
+ generateAnimate(frontView, swap, swapRight, downPosition);
+
+ velocityTracker = null;
+ downX = 0;
+ // change clickable front view
+ if (swap) {
+ frontView.setClickable(opened.get(downPosition));
+ frontView.setLongClickable(opened.get(downPosition));
+ }
+ frontView = null;
+ backView = null;
+ this.downPosition = ListView.INVALID_POSITION;
+ swiping = false;
+ break;
+ }
+
+ case MotionEvent.ACTION_MOVE: {
+ if (velocityTracker == null || paused) {
+ break;
+ }
+
+ velocityTracker.addMovement(motionEvent);
+ float deltaX = motionEvent.getRawX() - downX;
+ float deltaMode = Math.abs(deltaX);
+ if (swipeMode == SwipeListView.SWIPE_MODE_NONE) {
+ deltaMode = 0;
+ } else if (swipeMode != SwipeListView.SWIPE_MODE_BOTH) {
+ if (opened.get(downPosition)) {
+ if (swipeMode == SwipeListView.SWIPE_MODE_LEFT && deltaX < 0) {
+ deltaMode = 0;
+ } else if (swipeMode == SwipeListView.SWIPE_MODE_RIGHT && deltaX > 0) {
+ deltaMode = 0;
+ }
+ } else {
+ if (swipeMode == SwipeListView.SWIPE_MODE_LEFT && deltaX > 0) {
+ deltaMode = 0;
+ } else if (swipeMode == SwipeListView.SWIPE_MODE_RIGHT && deltaX < 0) {
+ deltaMode = 0;
+ }
+ }
+ }
+ if (deltaMode > slop && swipeCurrentAction == SwipeListView.SWIPE_ACTION_NONE) {
+ swiping = true;
+ boolean swipingRight = (deltaX > 0);
+ if (opened.get(downPosition)) {
+ swipeCurrentAction = SwipeListView.SWIPE_ACTION_REVEAL;
+ } else {
+ if (swipingRight && swipeActionRight == SwipeListView.SWIPE_ACTION_DISMISS) {
+ swipeCurrentAction = SwipeListView.SWIPE_ACTION_DISMISS;
+ } else if (!swipingRight && swipeActionLeft == SwipeListView.SWIPE_ACTION_DISMISS) {
+ swipeCurrentAction = SwipeListView.SWIPE_ACTION_DISMISS;
+ } else if (swipingRight && swipeActionRight == SwipeListView.SWIPE_ACTION_CHECK) {
+ swipeCurrentAction = SwipeListView.SWIPE_ACTION_CHECK;
+ } else if (!swipingRight && swipeActionLeft == SwipeListView.SWIPE_ACTION_CHECK) {
+ swipeCurrentAction = SwipeListView.SWIPE_ACTION_CHECK;
+ } else {
+ swipeCurrentAction = SwipeListView.SWIPE_ACTION_REVEAL;
+ }
+ }
+ swipeListView.requestDisallowInterceptTouchEvent(true);
+ MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
+ cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
+ (motionEvent.getActionIndex()
+ << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
+ swipeListView.onTouchEvent(cancelEvent);
+ }
+
+ if (swiping) {
+ if (opened.get(downPosition)) {
+ deltaX += openedRight.get(downPosition) ? viewWidth - offsetRight : -viewWidth + offsetLeft;
+ }
+ move(deltaX);
+ return true;
+ }
+ break;
+ }
+ }
+ return false;
+ }
+
+ public void move(float deltaX) {
+ swipeListView.onMove(downPosition, deltaX);
+ if (swipeCurrentAction == SwipeListView.SWIPE_ACTION_DISMISS) {
+ setTranslationX(parentView, deltaX);
+ setAlpha(parentView, Math.max(0f, Math.min(1f,
+ 1f - 2f * Math.abs(deltaX) / viewWidth)));
+ } else {
+ setTranslationX(frontView, deltaX);
+ }
+ }
+
+ class PendingDismissData implements Comparable {
+ public int position;
+ public View view;
+
+ public PendingDismissData(int position, View view) {
+ this.position = position;
+ this.view = view;
+ }
+
+ @Override
+ public int compareTo(PendingDismissData other) {
+ // Sort by descending position
+ return other.position - position;
+ }
+ }
+
+ private void performDismiss(final View dismissView, final int dismissPosition) {
+ final ViewGroup.LayoutParams lp = dismissView.getLayoutParams();
+ final int originalHeight = dismissView.getHeight();
+
+ ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(animationTime);
+
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ --dismissAnimationRefCount;
+ if (dismissAnimationRefCount == 0) {
+ // No active animations, process all pending dismisses.
+ // Sort by descending position
+ Collections.sort(pendingDismisses);
+
+ int[] dismissPositions = new int[pendingDismisses.size()];
+ for (int i = pendingDismisses.size() - 1; i >= 0; i--) {
+ dismissPositions[i] = pendingDismisses.get(i).position;
+ }
+ swipeListView.onDismiss(dismissPositions);
+
+ ViewGroup.LayoutParams lp;
+ for (PendingDismissData pendingDismiss : pendingDismisses) {
+ // Reset view presentation
+ setAlpha(pendingDismiss.view, 1f);
+ setTranslationX(pendingDismiss.view, 0);
+ lp = pendingDismiss.view.getLayoutParams();
+ lp.height = originalHeight;
+ pendingDismiss.view.setLayoutParams(lp);
+ }
+
+ pendingDismisses.clear();
+ }
+ }
+ });
+
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ lp.height = (Integer) valueAnimator.getAnimatedValue();
+ dismissView.setLayoutParams(lp);
+ }
+ });
+
+ pendingDismisses.add(new PendingDismissData(dismissPosition, dismissView));
+ animator.start();
+ }
+
+}