Android ListView faites glisser vers la gauche/droite comme Samsung contact ListView

je suis en train de développer une application, et j'ai besoin d'un ListView comme celui de mon Samsung Galaxy S:

img

quand je glisse mon doigt à droite, je peux envoyer un message à ce contact.

quand je glisse mon doigt à droite, je peux appeler mon contact.

j'ai mon ListView et j'ai seulement besoin de la fonction pour le faire...

Merci à l'avance.

PD: J'ai beaucoup cherché et n'ai rien trouvé. Les plus similaires: des Ressources pour Android Légèrement à Gauche/Droite de la Diapositive action sur listview

30
demandé sur Community 2012-02-17 04:00:40

3 réponses

ce que vous pourriez faire ici est de créer une nouvelle vue spécialement pour la vue Liste (appelez-la ListViewFlinger ou quelque chose comme ça). Ensuite, dans cette vue, outrepasser sa méthode onTouchEvent et y placer un certain code pour déterminer un geste de glissement. Une fois que vous avez le geste de la diapositive, lancez un événement onSlideComplete (vous devrez faire de cet auditeur) une voialla, vous une ListView avec un contenu activé par la diapositive.

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);
}
18
répondu AedonEtLIRA 2012-02-17 00:29:34

D'un autre billet, il y avait un lien vers ce code Google: https://gist.github.com/2980593 Qui proviennent de ce Google + post: https://plus.google.com/u/0/113735310430199015092/posts/Fgo1p5uWZLu . C'est un mouvement de Balayage À Rejeter la fonctionnalité.

à partir de cela, vous pouvez fournir votre propre code de passage à l'Action. Donc voici ma version, si je pouvais personnaliser l'action de gauche et de droite et vous pouvez déclencher le rejet animation (c'est juste une modification du code de Roman Nuric).

Vous devez inclure cette classe dans votre projet :

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();
    }
}

de là, vous pouvez ajouter le code suivant à votre onCreate dans L'activité avec 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());

Edit: Pour ajouter une modification de couleur lors du balayage, votre code doit être dans le case MotionEvent.ACTION_MOVE proche du mDownView.setAlpha .

28
répondu Solostaran14 2013-08-29 08:50:17

si vous souhaitez effectuer une action sur Swiping :

Check out SwipeActionAdapter

c'est une bibliothèque impressionnante qui permet de glisser dans les deux directions avec un Layout ou Color , et effectue une action désirée quand le geste de glisser/glisser est fait. Vous pouvez le configurer pour afficher/modifier la mise en page.

~ Je n'ai pas utilisé L'application Samsung Contacts, mais on dirait que c'est ce que vous voulez

Left Swipe Right Swipe


Si tu veux balayez vers Révéler exploitables boutons:

Check out SwipeMenuListView

dans un sens, il est plus comme les vues de table glissantes dans iOS.

SwipeMenuListView SwipeMenuListView SwipeMenuListView

1
répondu Sheharyar 2015-02-01 21:03:18