Skip to content

Instantly share code, notes, and snippets.

@fdoyle
Created October 30, 2013 19:24
Show Gist options
  • Save fdoyle/7238594 to your computer and use it in GitHub Desktop.
Save fdoyle/7238594 to your computer and use it in GitHub Desktop.
Swipe to dismiss view. gotta put this in a library
package com.blah.lol.swipetodismiss;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.widget.FrameLayout;
import com.blah.lol.R;
/**
* Created by fdoyle on 10/28/13.
*/
public class SwipeAwayView extends FrameLayout {
public static final int SWIPED_RIGHT = 1;
public static final int SWIPED_LEFT = -1;
public static final int SWIPED_CENTER = 0;
public View topView;
public View bottomView;
VelocityTracker tracker;
int swipedPosition;
OnItemSwipedListener listener;
int index;
int pointerId;
int marginInPixels = 200;
public SwipeAwayView(Context context) {
super(context);
}
public SwipeAwayView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setOnItemSwipedListener(OnItemSwipedListener listener, int index) {
this.listener = listener;
this.index = index;
}
public void setupView() {
topView = getChildAt(1);
bottomView = getChildAt(0);
bottomView.setVisibility(INVISIBLE);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setupView();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
float currentX = event.getX();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
tracker = VelocityTracker.obtain();
pointerId = event.getPointerId(0);
startX = currentX;
return false;
case MotionEvent.ACTION_MOVE:
float topViewLeftBound = topView.getX();
float topViewRightBound = topViewLeftBound + topView.getWidth();
if (Math.abs(startX - event.getX()) > 10 && startX < topViewRightBound && startX > topViewLeftBound)
return true;
return false;
case MotionEvent.ACTION_UP:
return false;
default:
return false;
}
}
float startX;
float lastX;
public void setSwipedPositionAnimated(int position) {
swipedPosition = position;
topView.animate().translationX(swipedPosition * (getWidth() - marginInPixels)).setDuration(200).withEndAction(new Runnable() {
@Override
public void run() {
if (bottomView != null)
if (swipedPosition == SWIPED_CENTER) {
bottomView.setVisibility(INVISIBLE);
} else {
bottomView.setVisibility(VISIBLE);
}
if (listener != null)
listener.onItemSwiped(index, swipedPosition);
}
}).start();
}
public void setSwipedPositionImmediate(int position) {
swipedPosition = position;
topView.animate().translationX(swipedPosition * (getWidth() - marginInPixels)).setDuration(0).withEndAction(new Runnable() {
@Override
public void run() {
if(bottomView != null)
if (swipedPosition == SWIPED_CENTER) {
bottomView.setVisibility(INVISIBLE);
} else {
bottomView.setVisibility(VISIBLE);
}
if (listener != null)
listener.onItemSwiped(index, swipedPosition);
}
}).start();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float currentX = event.getX();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: //because events are not intercepted until after ACTION_DOWN, this will never be reached
return false;
case MotionEvent.ACTION_MOVE:
if (event.getPointerId(0) != 0)
return false;
tracker.addMovement(event);
if (lastX != 0) {
topView.animate().translationXBy(currentX - lastX).setDuration(0).start();
bottomView.setVisibility(VISIBLE);
getParent().requestDisallowInterceptTouchEvent(true);
}
lastX = currentX;
return true;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_UP:
if (event.getPointerId(0) != 0)
return false;
getParent().requestDisallowInterceptTouchEvent(false);
tracker.computeCurrentVelocity(1);
boolean flinging = Math.abs(tracker.getXVelocity()) > 3;
boolean draggedFarEnough = Math.abs(startX - currentX) > getWidth() / 2.5;
boolean xIncreasing;
if (flinging) {
xIncreasing = tracker.getXVelocity() > 0;
} else {
xIncreasing = startX < currentX;
}
final int direction;
if (xIncreasing) {
direction = SWIPED_RIGHT;
} else {
direction = SWIPED_LEFT;
}
if ((flinging || draggedFarEnough)) {
if (swipedPosition == SWIPED_CENTER) { //if it's center, move it in direction
swipedPosition += direction;
} else if (swipedPosition + direction == SWIPED_CENTER) { //if moving it in direction would center it, center it.
swipedPosition = SWIPED_CENTER;
}
//move to resting state in appropriate position
topView.animate().translationX(swipedPosition * (getWidth() - marginInPixels)).setDuration(200).withEndAction(new Runnable() {
@Override
public void run() {
if(bottomView == null) {
} else if (swipedPosition == SWIPED_CENTER) {
bottomView.setVisibility(INVISIBLE);
} else {
bottomView.setVisibility(VISIBLE);
}
if (listener != null)
listener.onItemSwiped(index, swipedPosition);
}
}).start();
} else {
topView.animate().translationX(swipedPosition * (getWidth() - marginInPixels)).setDuration(200).withEndAction(new Runnable() {
@Override
public void run() {
if (swipedPosition == SWIPED_CENTER && bottomView != null)
bottomView.setVisibility(INVISIBLE);
}
}).start();
}
tracker.clear();
tracker.recycle();
tracker = null;
lastX = 0;
startX = 0;
return true;
default:
return false;
}
}
public interface OnItemSwipedListener {
public void onItemSwiped(int index, int direction);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment