This question refers to the SwipeListView component found here: https://github.com/47deg/android-swipelistview
After trying out several implementations and fixes I found on the web I decided to modify the sources a little.
I will post this here since i know it's a known issue and all the versions I found proved to have some issues eventually.
SwipeListViewTouchListener.java
has suffered the following changes:
...
/**
* Create reveal animation
*
* @param view affected view
* @param swap If will change state. If "false" returns to the original
* position
* @param swapRight If swap is true, this parameter tells if movement is toward
* right or left
* @param position list 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 - rightOffset) : (int) (-viewWidth + leftOffset);
}
} else {
if (swap) {
moveTo = swapRight ? (int) (viewWidth - rightOffset) : (int) (-viewWidth + leftOffset);
}
}
final boolean aux = !opened.get(position);
if(swap) {
opened.set(position, aux);
openedRight.set(position, swapRight);
}
animate(view).translationX(moveTo).setDuration(animationTime).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
swipeListView.resetScrolling();
if (swap) {
if (aux) {
swipeListView.onOpened(position, swapRight);
} else {
swipeListView.onClosed(position, openedRight.get(position));
}
}
// if (aux || !swap) {
// resetCell();
// }
}
});
}
...
/**
* Close all opened items
*/
void closeOtherOpenedItems() {
if (opened != null && downPosition != SwipeListView.INVALID_POSITION) {
int start = swipeListView.getFirstVisiblePosition();
int end = swipeListView.getLastVisiblePosition();
for (int i = start; i <= end; i++) {
if (opened.get(i) && i != downPosition) {
closeAnimate(swipeListView.getChildAt(i - start).findViewById(swipeFrontView), i);
}
}
}
}
...
/**
* @see View.OnTouchListener#onTouch(android.view.View,
* android.view.MotionEvent)
*/
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
...
closeOtherOpenedItems();
view.onTouchEvent(motionEvent);
return true;
}
The rest of the code not mentioned is the same.
Any comments highly appreciated, this changes prevent you from having to implement the SwipeListViewOnTouchListener
in the activity which inflates the list.
Cons: doesn't close the row opened by openAnimate()
BaseSwipeListViewListener swipeListViewListener = new BaseSwipeListViewListener() {
int openItem = -1;
@Override
public void onStartOpen(int position, int action, boolean right) {
super.onStartOpen(position, action, right);
if (openItem > -1)
swipeListView.closeAnimate(openItem);
openItem = position;
}
}
Or better way:
@Override
public void onStartOpen(int position, int action, boolean right) {
super.onStartOpen(position, action, right);
swipeListView.closeOpenedItems();
}
And set the listener to the listView:
swipeListView.setSwipeListViewListener(swipeListViewListener);
If you're going to modify the swipelistview
library itself I have a simpler solution.
Add the following if block to SwipeListViewTouchListener.java
in the onTouch
method right at the beginning of case MotionEvent.ACTION_DOWN:
if(lastOpenedPosition != downPosition && opened.get(lastOpenedPosition)) {
closeAnimate(lastOpenedPosition);
return false;
}
Create an int lastOpenedPosition
field and initialize it to 0, and in the generateRevealAnimate
method inside the if (aux)
block add:
lastOpenedPosition = position;
I would also add config variable (in res/values/swipelistview_attrs.xml
) to SwipeListView
and add it to the onTouch
if block, to add the ability to turn this feature off and on.
This basically results in if the list is touched while a row is open, than the row will close. Which, imho, is better functionality than the row closing only after you finished opening another row.
Your fix worked, but there is a way to do it without affecting the original code:
swipeListView.setSwipeListViewListener(new BaseSwipeListViewListener() {
int openItem = -1;
int lastOpenedItem = -1;
int lastClosedItem = -1;
@Override
public void onOpened(int position, boolean toRight) {
lastOpenedItem = position;
if (openItem > -1 && lastOpenedItem != lastClosedItem) {
swipeListView.closeAnimate(openItem);
}
openItem = position;
}
@Override
public void onStartClose(int position, boolean right) {
Log.d("swipe", String.format("onStartClose %d", position));
lastClosedItem = position;
}
}
You should however, send a pull request to apply your code as that would fix the bug.
Source: https://github.com/47deg/android-swipelistview/issues/46
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With