library - swipe recyclerview android
Android-ListView diapositiva izquierda/derecha como Samsung contacto ListView (3)
Estoy desarrollando una aplicación, y necesito un ListView como el conctact ListView de mi Samsung Galaxy S:
Cuando deslizo mi dedo hacia la derecha, puedo enviar un mensaje a este contacto.
Cuando deslizo mi dedo hacia la derecha, puedo llamar a mi contacto.
Tengo mi ListView y solo necesito la función para hacerlo ...
Gracias por adelantado.
PD: Busqué mucho y no he encontrado nada. Lo más parecido: Recurso para Android Acción deslizante izquierda / derecha leve en listview
Si desea realizar una acción al deslizar :
Echa un vistazo a SwipeActionAdapter
Es una biblioteca impresionante que permite deslizar en ambas direcciones con un Layout
o Color
subyacente, y realiza una acción deseada cuando se realiza el gesto deslizar / deslizar. Puede configurarlo para revelar / cambiar el diseño.
~ No he usado la aplicación Samsung Contacts, pero parece que esto es lo que quieres
SwipeActionAdapter SwipeActionAdapter
Si quieres deslizar para revelar botones accionables:
Echa un vistazo a SwipeMenuListView
En cierto sentido, es más parecido a las TableViews con capacidad de deslizamiento en iOS.
Desde otra publicación, había un enlace a este código de Google: https://gist.github.com/2980593 que provienen de esta publicación de Google+: https://plus.google.com/u/0/113735310430199015092/posts/Fgo1p5uWZLu . Esta es una funcionalidad de Deslizar para despedir.
A partir de esto, puede proporcionar su propio código Swipe-To-Action. Así que aquí está mi versión, si puedo personalizar la acción izquierda y derecha y puedes activar la animación de Descartar (esto es solo una modificación del código de Roman Nuric).
Debes incluir esta clase en tu proyecto:
public class SwipeListViewTouchListener implements View.OnTouchListener {
// Cached ViewConfiguration and system-wide constant values
private int mSlop;
private int mMinFlingVelocity;
private int mMaxFlingVelocity;
private long mAnimationTime;
// Fixed properties
private ListView mListView;
private OnSwipeCallback mCallback;
private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
private boolean dismissLeft = true;
private boolean dismissRight = true;
// Transient properties
private List < PendingSwipeData > mPendingSwipes = new ArrayList < PendingSwipeData > ();
private int mDismissAnimationRefCount = 0;
private float mDownX;
private boolean mSwiping;
private VelocityTracker mVelocityTracker;
private int mDownPosition;
private View mDownView;
private boolean mPaused;
/**
* The callback interface used by {@link SwipeListViewTouchListener} to inform its client
* about a successful swipe of one or more list item positions.
*/
public interface OnSwipeCallback {
/**
* Called when the user has swiped the list item to the left.
*
* @param listView The originating {@link ListView}.
* @param reverseSortedPositions An array of positions to dismiss, sorted in descending
* order for convenience.
*/
void onSwipeLeft(ListView listView, int[] reverseSortedPositions);
void onSwipeRight(ListView listView, int[] reverseSortedPositions);
}
/**
* Constructs a new swipe-to-action touch listener for the given list view.
*
* @param listView The list view whose items should be dismissable.
* @param callback The callback to trigger when the user has indicated that she would like to
* dismiss one or more list items.
*/
public SwipeListViewTouchListener(ListView listView, OnSwipeCallback callback) {
ViewConfiguration vc = ViewConfiguration.get(listView.getContext());
mSlop = vc.getScaledTouchSlop();
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
mAnimationTime = listView.getContext().getResources().getInteger(
android.R.integer.config_shortAnimTime);
mListView = listView;
mCallback = callback;
}
/**
* Constructs a new swipe-to-action touch listener for the given list view.
*
* @param listView The list view whose items should be dismissable.
* @param callback The callback to trigger when the user has indicated that she would like to
* dismiss one or more list items.
* @param dismissLeft set if the dismiss animation is up when the user swipe to the left
* @param dismissRight set if the dismiss animation is up when the user swipe to the right
* @see #SwipeListViewTouchListener(ListView, OnSwipeCallback, boolean, boolean)
*/
public SwipeListViewTouchListener(ListView listView, OnSwipeCallback callback, boolean dismissLeft, boolean dismissRight) {
this(listView, callback);
this.dismissLeft = dismissLeft;
this.dismissRight = dismissRight;
}
/**
* Enables or disables (pauses or resumes) watching for swipe-to-dismiss gestures.
*
* @param enabled Whether or not to watch for gestures.
*/
public void setEnabled(boolean enabled) {
mPaused = !enabled;
}
/**
* Returns an {@link android.widget.AbsListView.OnScrollListener} to be added to the
* {@link ListView} using
* {@link ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener)}.
* If a scroll listener is already assigned, the caller should still pass scroll changes
* through to this listener. This will ensure that this
* {@link SwipeListViewTouchListener} is paused during list view scrolling.</p>
*
* @see {@link SwipeListViewTouchListener}
*/
public AbsListView.OnScrollListener makeScrollListener() {
return new AbsListView.OnScrollListener() {@
Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
setEnabled(scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
@
Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {}
};
}
@
Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (mViewWidth < 2) {
mViewWidth = mListView.getWidth();
}
switch (motionEvent.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
{
if (mPaused) {
return false;
}
// TODO: ensure this is a finger, and set a flag
// Find the child view that was touched (perform a hit test)
Rect rect = new Rect();
int childCount = mListView.getChildCount();
int[] listViewCoords = new int[2];
mListView.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 = mListView.getChildAt(i);
child.getHitRect(rect);
if (rect.contains(x, y)) {
mDownView = child;
break;
}
}
if (mDownView != null) {
mDownX = motionEvent.getRawX();
mDownPosition = mListView.getPositionForView(mDownView);
mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(motionEvent);
}
view.onTouchEvent(motionEvent);
return true;
}
case MotionEvent.ACTION_UP:
{
if (mVelocityTracker == null) {
break;
}
float deltaX = motionEvent.getRawX() - mDownX;
mVelocityTracker.addMovement(motionEvent);
mVelocityTracker.computeCurrentVelocity(500); // 1000 by defaut but it was too much
float velocityX = Math.abs(mVelocityTracker.getXVelocity());
float velocityY = Math.abs(mVelocityTracker.getYVelocity());
boolean swipe = false;
boolean swipeRight = false;
if (Math.abs(deltaX) > mViewWidth / 2) {
swipe = true;
swipeRight = deltaX > 0;
} else if (mMinFlingVelocity <= velocityX && velocityX <= mMaxFlingVelocity && velocityY < velocityX) {
swipe = true;
swipeRight = mVelocityTracker.getXVelocity() > 0;
}
if (swipe) {
// sufficent swipe value
final View downView = mDownView; // mDownView gets null''d before animation ends
final int downPosition = mDownPosition;
final boolean toTheRight = swipeRight;
++mDismissAnimationRefCount;
mDownView.animate()
.translationX(swipeRight ? mViewWidth : -mViewWidth)
.alpha(0)
.setDuration(mAnimationTime)
.setListener(new AnimatorListenerAdapter() {@
Override
public void onAnimationEnd(Animator animation) {
performSwipeAction(downView, downPosition, toTheRight, toTheRight ? dismissRight : dismissLeft);
}
});
} else {
// cancel
mDownView.animate()
.translationX(0)
.alpha(1)
.setDuration(mAnimationTime)
.setListener(null);
}
mVelocityTracker = null;
mDownX = 0;
mDownView = null;
mDownPosition = ListView.INVALID_POSITION;
mSwiping = false;
break;
}
case MotionEvent.ACTION_MOVE:
{
if (mVelocityTracker == null || mPaused) {
break;
}
mVelocityTracker.addMovement(motionEvent);
float deltaX = motionEvent.getRawX() - mDownX;
if (Math.abs(deltaX) > mSlop) {
mSwiping = true;
mListView.requestDisallowInterceptTouchEvent(true);
// Cancel ListView''s touch (un-highlighting the item)
MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
(motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
mListView.onTouchEvent(cancelEvent);
}
if (mSwiping) {
mDownView.setTranslationX(deltaX);
mDownView.setAlpha(Math.max(0f, Math.min(1f,
1f - 2f * Math.abs(deltaX) / mViewWidth)));
return true;
}
break;
}
}
return false;
}
class PendingSwipeData implements Comparable < PendingSwipeData > {
public int position;
public View view;
public PendingSwipeData(int position, View view) {
this.position = position;
this.view = view;
}
@
Override
public int compareTo(PendingSwipeData other) {
// Sort by descending position
return other.position - position;
}
}
private void performSwipeAction(final View swipeView, final int swipePosition, boolean toTheRight, boolean dismiss) {
// Animate the dismissed list item to zero-height and fire the dismiss callback when
// all dismissed list item animations have completed. This triggers layout on each animation
// frame; in the future we may want to do something smarter and more performant.
final ViewGroup.LayoutParams lp = swipeView.getLayoutParams();
final int originalHeight = swipeView.getHeight();
final boolean swipeRight = toTheRight;
ValueAnimator animator;
if (dismiss)
animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(mAnimationTime);
else
animator = ValueAnimator.ofInt(originalHeight, originalHeight - 1).setDuration(mAnimationTime);
animator.addListener(new AnimatorListenerAdapter() {@
Override
public void onAnimationEnd(Animator animation) {
--mDismissAnimationRefCount;
if (mDismissAnimationRefCount == 0) {
// No active animations, process all pending dismisses.
// Sort by descending position
Collections.sort(mPendingSwipes);
int[] swipePositions = new int[mPendingSwipes.size()];
for (int i = mPendingSwipes.size() - 1; i >= 0; i--) {
swipePositions[i] = mPendingSwipes.get(i).position;
}
if (swipeRight)
mCallback.onSwipeRight(mListView, swipePositions);
else
mCallback.onSwipeLeft(mListView, swipePositions);
ViewGroup.LayoutParams lp;
for (PendingSwipeData pendingDismiss: mPendingSwipes) {
// Reset view presentation
pendingDismiss.view.setAlpha(1f);
pendingDismiss.view.setTranslationX(0);
lp = pendingDismiss.view.getLayoutParams();
lp.height = originalHeight;
pendingDismiss.view.setLayoutParams(lp);
}
mPendingSwipes.clear();
}
}
});
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@
Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
lp.height = (Integer) valueAnimator.getAnimatedValue();
swipeView.setLayoutParams(lp);
}
});
mPendingSwipes.add(new PendingSwipeData(swipePosition, swipeView));
animator.start();
}
}
Desde allí, puede agregar el siguiente código a su onCreate en la Actividad con el ListView:
// Create a ListView-specific touch listener. ListViews are given special treatment because
// by default they handle touches for their list items... i.e. they''re in charge of drawing
// the pressed state (the list selector), handling list item clicks, etc.
SwipeListViewTouchListener touchListener =
new SwipeListViewTouchListener(
listView,
new SwipeListViewTouchListener.OnSwipeCallback() {
@Override
public void onSwipeLeft(ListView listView, int [] reverseSortedPositions) {
// Log.i(this.getClass().getName(), "swipe left : pos="+reverseSortedPositions[0]);
// TODO : YOUR CODE HERE FOR LEFT ACTION
}
@Override
public void onSwipeRight(ListView listView, int [] reverseSortedPositions) {
// Log.i(ProfileMenuActivity.class.getClass().getName(), "swipe right : pos="+reverseSortedPositions[0]);
// TODO : YOUR CODE HERE FOR RIGHT ACTION
}
},
true, // example : left action = dismiss
false); // example : right action without dismiss animation
listView.setOnTouchListener(touchListener);
// Setting this scroll listener is required to ensure that during ListView scrolling,
// we don''t look for swipes.
listView.setOnScrollListener(touchListener.makeScrollListener());
Editar: para agregar una modificación de color al deslizar, su código debe estar en el case MotionEvent.ACTION_MOVE
cerca de mDownView.setAlpha
.
Lo que podrías hacer aquí es crear una nueva vista especialmente para la vista de lista (llámala ListViewFlinger o algo así). Luego, en esta vista, anule su método onTouchEvent y coloque algún código allí para determinar un gesto de deslizamiento. Una vez que tenga el gesto de deslizar, ejecute un evento onSlideComplete (tendrá que hacer que el oyente) sea un voialla, un ListView con contenido activado por diapositivas.
float historicX = Float.NaN, historicY = Float.NaN;
static final TRIGGER_DELTA = 50; // Number of pixels to travel till trigger
@Override public boolean onTouchEvent(MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
historicX = e.getX();
historicY = e.getY();
break;
case MotionEvent.ACTION_UP:
if (e.getX() - historicX > -TRIGGER_DELTA) {
onSlideComplete(Direction.LEFT);
return true;
}
else if (e.getX() - historicX > TRIGGER_DELTA) {
onSlideComplete(Direction.RIGHT);
return true;
} break;
default:
return super.onTouchEvent(e);
}
}
enum Direction {
LEFT, RIGHT;
}
interface OnSlideCompleteListener {
void onSlideComplete(Direction dir);
}