it.vibin.sideswipe.drag.SwipeMenuManager.java Source code

Java tutorial

Introduction

Here is the source code for it.vibin.sideswipe.drag.SwipeMenuManager.java

Source

/*
 * Copyright 2015 www.vibin.it (vic.choy@gmail.com, victor.cui@vibin.it) 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package it.vibin.sideswipe.drag;

import it.vibin.sideswipe.drag.VerticalViewPager.OnReadyListener;

import java.util.HashMap;
import java.util.Iterator;

import android.content.ClipData;
import android.content.Context;
import android.graphics.Canvas;
import android.support.v4.view.GestureDetectorCompat;
import android.util.Log;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.Toast;

public class SwipeMenuManager implements OnTouchListener, OnDragListener, OnReadyListener {

    public static final String TAG = "SwipeMenuManager";

    private static final int VERTICAL_TRAVEL_LIMIT = 7;
    private static final int HORIZONTAL_TRAVEL_MAX = 60;
    private static final int HORIZONTAL_TRAVEL_MIN = 10;

    private Context mContext = null;
    private SwipeMenuEvents mEventListener = null;
    private SwipeMenuGestureDetector mDetector = null;

    private VerticalViewPager mViewPager = null;
    private View mCurrentView = null;
    private HashMap<DropZone, View> mDropZones = new HashMap<DropZone, View>();

    private int mX = 0;
    private int mY = 0;
    private boolean mIsDragging = false;
    private boolean mLockedOnX = false;

    public static enum DropZone {
        Idle, Left, Right
    }

    public interface SwipeMenuEvents {
        public void postback_touchEvent(MotionEvent event);

        public void postback_drop(View currentView, DropZone dropZone, View dropZoneView);
    }

    private class SwipeMenuGestureDetector extends GestureDetectorCompat {

        public SwipeMenuGestureDetector(Context context, OnGestureListener listener) {
            super(context, listener);
            Log.d(TAG, "<<<<<<<<<< CONSTRUCT");
        }
    }

    private OnGestureListener mGestureListener = new OnGestureListener() {

        @Override
        public boolean onDown(MotionEvent e) {
            Log.d(TAG, "<<<<<<<<<<<<<<<<<<<<<< ON DOWN");
            return true;
        }

        @Override
        public void onShowPress(MotionEvent e) {
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return false;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            //Log.d(TAG, "<<<<<<<<<<<<<<<<<<<<<< ON SCROLL");
            if (e1 == null || e2 == null)
                return false;
            float x1 = e1.getX();
            float x2 = e2.getX();
            Log.d(TAG, "x1: " + x1 + ", x2: " + x2 + ", distanceX: " + distanceX + ", distanceY: " + distanceY);
            distanceY = Math.abs(distanceY);
            if (distanceY > VERTICAL_TRAVEL_LIMIT) {
                // not a clean horizontal gesture
                if (mViewPager != null) {
                    mViewPager.onTouchEvent(e2);
                    mLockedOnX = false;
                }
                return false;
            }
            if (Math.abs(distanceX) > HORIZONTAL_TRAVEL_MAX) {
                // it's a bit like a fling, don't drag
                mLockedOnX = false;
                return false;
            }
            if (distanceX > HORIZONTAL_TRAVEL_MIN || distanceX < -HORIZONTAL_TRAVEL_MIN) {
                if (mCurrentView != null && !mIsDragging) {
                    mLockedOnX = true;
                    mIsDragging = true;
                    ClipData data = ClipData.newPlainText("", "");
                    //SwipeMenuDragShadowBuilder shadowBuilder = new SwipeMenuDragShadowBuilder(mCurrentView);
                    //shadowBuilder.setCoordinates(x2, mY);
                    DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(mCurrentView);
                    mCurrentView.startDrag(data, shadowBuilder, mCurrentView, 0);
                    mCurrentView.setVisibility(View.INVISIBLE);
                    //mViewPager.requestDisallowInterceptTouchEvent(true);
                }
                return true;
            }
            if (mViewPager != null) {
                mLockedOnX = false;
                mViewPager.onTouchEvent(e2);
            }
            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;
        }
    };

    public SwipeMenuManager(Context context, SwipeMenuEvents eventListener) {
        mContext = context;
        mEventListener = eventListener;
        mDetector = new SwipeMenuGestureDetector(context, mGestureListener);
    }

    @Override
    public void onViewPagerReady(VerticalViewPager viewPager) {
        Log.d(TAG, "@@@@@@@@@@@@@@@@@@@@@");
        Log.d(TAG, "@@@@@@@@ READY! @@@@@");
        Log.d(TAG, "@@@@@@@@@@@@@@@@@@@@@");
        mViewPager.setCurrentItem(0);
        View v = mViewPager.getChildAt(0);
        mY = (int) v.getY();
        setCurrentCard(mViewPager.getChildAt(0), View.VISIBLE);
    }

    /**
     * Must be a VerticalViewPager.
     * NOTE: VerticalViewPager should have this snippet of code within
     * 
     * <pre>
     * public OnReadyListener mListener;
     * public boolean mInit = false;
     * public interface OnReadyListener {
     *    public void onViewPagerReady(VerticalViewPager viewPager);
     * }
     * public void setOnReadyListener(OnReadyListener listener) {
     *    mListener = listener;
     * }
     * @Override
     * public void onWindowFocusChanged(boolean hasFocus) {
     *    super.onWindowFocusChanged(hasFocus);
     *    if (!hasFocus) return;
     *    if (!mInit && mListener != null) {
     *       mInit = true;
     *       mListener.onViewPagerReady(this);
     *    }
     * }
     * </pre>
     * 
     * @param viewPager
     */
    public void setViewPager(VerticalViewPager viewPager) {
        mViewPager = viewPager;
        mViewPager.setOnReadyListener(this);
    }

    /**
     * DropZone.Idle MUST be set (should be the lowest Z-axis view, which is as large as the screen).
     * 
     * @param dropZone   {@link DropZone}
     * @param view      View
     */
    public void setDropZone(DropZone dropZone, View view) {
        view.setOnDragListener(this);
        mDropZones.put(dropZone, view);
    }

    /**
     * SwipeMenuManager needs to know which card is in the foreground position of VerticalViewPager, so
     * this method needs to be updated with new card everything the viewpager is updated.
     * 
     * @param view         View
     * @param visibility   int
     */
    public void setCurrentCard(View view, int visibility) {
        Log.d(TAG, "==========> new foreground card!");
        view.setVisibility(visibility);
        view.setOnTouchListener(this);
        mCurrentView = view;
    }

    /**
     * Call this function when the view should go back to original position in VerticalViewPager
     */
    public void recall() {
        mCurrentView.setVisibility(View.VISIBLE);
    }

    @Override
    public boolean onDrag(View v, DragEvent event) {
        int action = event.getAction();
        final View dropView = (View) event.getLocalState();
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
        switch (action) {
        case DragEvent.ACTION_DRAG_STARTED:
            mY = (int) dropView.getY() - params.topMargin;
            break;
        case DragEvent.ACTION_DRAG_LOCATION:
            break;
        case DragEvent.ACTION_DROP:
        case DragEvent.ACTION_DRAG_EXITED:
            Iterator<DropZone> iter = mDropZones.keySet().iterator();
            while (iter.hasNext()) {
                DropZone dropZone = iter.next();
                View dropZoneView = mDropZones.get(dropZone);
                if (v.getId() == dropZoneView.getId()) {
                    mEventListener.postback_drop(dropView, dropZone, v);
                }
                //mViewPager.requestDisallowInterceptTouchEvent(false);
            }
            mLockedOnX = false;
            mIsDragging = false;
            break;
        case DragEvent.ACTION_DRAG_ENDED:
            Log.d(TAG, "=============> DRAG ENDED!");
            dropView.post(new Runnable() {
                @Override
                public void run() {
                    //dropView.setVisibility(View.VISIBLE);
                    mLockedOnX = false;
                    mIsDragging = false;
                    //mViewPager.requestDisallowInterceptTouchEvent(false);
                }
            });
            break;
        }
        return true;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        //Log.d(TAG, "===========> TOUCH!");
        Log.d(TAG, "locked on X? " + mLockedOnX);
        if (event.getAction() == MotionEvent.ACTION_UP) {
            Log.d(TAG, "==========> UP!");
            mLockedOnX = false;
            mIsDragging = false;
            recall();
            //         if (mCurrentView != null) {
            //            mCurrentView.setVisibility(View.VISIBLE);
            //         }
        }
        return mDetector.onTouchEvent(event);
    }
}