happyhuman
happyhuman

Reputation: 1651

A custom Android View with 4-direction swipe gesture

I am working on an Android App which shows a series of cards. Each card almost takes the whole screen. I want the user to be able to view the previous and next cards by swiping left and right and for that ViewPager is working nicely.

However I also want the user to be able to swipe up and down a card to like/dislike a it. The swipe up/down gesture should move up/down the card according to the user's hand gesture. After a card is swiped up/down, it should be removed from the list of cards.

I searched online for a solution or a costume view. But most of the solutions I found are for 2-directional swipes (either left/right or up/down). Is there a nice solution or a library for a 4-directional Swipe View?

Upvotes: 1

Views: 5515

Answers (2)

happyhuman
happyhuman

Reputation: 1651

After some online research, I came up with the following implementation which works nicely. The CardView class extends Fragment which can be used in a class.

    public class CardView extends Fragment {
        private static float CARDS_SWIPE_LENGTH = 250;
        private float originalX = 0;
        private float originalY = 0;    
        private float startMoveX = 0;
        private float startMoveY = 0;

        public CardView() {
            super();
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.card_template, container, false);

            rootView.setOnTouchListener(new View.OnTouchListener() {
                public boolean onTouch(View view, MotionEvent event) {
                        final float X = event.getRawX();
                        final float Y =  event.getRawY();
                        float deltaX = X - startMoveX;
                        float deltaY = Y - startMoveY;
                        switch (event.getAction() & MotionEvent.ACTION_MASK) {
                            case MotionEvent.ACTION_DOWN:
                                startMoveX = X;
                                startMoveY = Y;
                                break;
                            case MotionEvent.ACTION_UP:
                                childView.getBackground().setColorFilter(R.color.color_card_background, PorterDuff.Mode.DST);
                                if ( Math.abs(deltaY) < CARDS_SWIPE_LENGTH ) {
                                    rootView.setX(originalX);
                                    rootView.setY(originalY);
                                } else if ( deltaY > 0 ) { 
                                    onCardSwipeDown();
                                } else {
                                    onCardSwipeUp();
                                }
                                break;
                            case MotionEvent.ACTION_POINTER_DOWN:
                                break;
                            case MotionEvent.ACTION_POINTER_UP:
                                break;
                            case MotionEvent.ACTION_MOVE:
                                int newColor = 0;
                                if ( deltaY < 0 ) {
                                    int rb = (int)(255+deltaY/10);
                                    newColor = Color.argb(170, rb, 255, rb);
                                } else {
                                    int gb = (int)(255-deltaY/10);
                                    newColor = Color.argb(170, 255, gb, gb);                                
                                }
                                rootView.getBackground().setColorFilter(newColor, PorterDuff.Mode.DARKEN);
                                rootView.setTranslationY(deltaY);
                                break;
                        }
                        rootView.invalidate();
                    return true;
                }
            });
            return rootView;
        }

        protected void onCardSwipeUp() {
            Log.i(AppUtil.APP, "Swiped Up");
        }

        protected void onCardSwipeDown() {
            Log.i(AppUtil.APP, "Swiped Down");
        }

    }
}

Upvotes: 8

Marcus Gabilheri
Marcus Gabilheri

Reputation: 1289

You could use a ViewPager to change between the cards. Them you could @Override the motionEvents of Up and Down to do whatever you want with your cards. You could store them in an ArrayAdapter to switch between them. When the user swipes DOWN or UP you remove the card from the adapter and use the viewPager.setCurrentItem(viewPager.getCurrentItem() +1) to go to the next card.

http://developer.android.com/reference/android/view/MotionEvent.html http://developer.android.com/reference/android/support/v4/view/ViewPager.html

Upvotes: 1

Related Questions