Home | History | Annotate | Download | only in com.example.android.elevationdrag
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.elevationdrag;
     18 
     19 import android.content.Context;
     20 import android.support.v4.widget.ViewDragHelper;
     21 import android.util.AttributeSet;
     22 import android.view.MotionEvent;
     23 import android.view.View;
     24 import android.widget.FrameLayout;
     25 
     26 import java.util.ArrayList;
     27 import java.util.List;
     28 
     29 /**
     30  * A {@link FrameLayout} that allows the user to drag and reposition child views.
     31  */
     32 public class DragFrameLayout extends FrameLayout {
     33 
     34     /**
     35      * The list of {@link View}s that will be draggable.
     36      */
     37     private List<View> mDragViews;
     38 
     39     /**
     40      * The {@link DragFrameLayoutController} that will be notify on drag.
     41      */
     42     private DragFrameLayoutController mDragFrameLayoutController;
     43 
     44     private ViewDragHelper mDragHelper;
     45 
     46     public DragFrameLayout(Context context) {
     47         this(context, null, 0, 0);
     48     }
     49 
     50     public DragFrameLayout(Context context, AttributeSet attrs) {
     51         this(context, attrs, 0, 0);
     52     }
     53 
     54     public DragFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
     55         this(context, attrs, defStyleAttr, 0);
     56     }
     57 
     58     public DragFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
     59         super(context, attrs, defStyleAttr, defStyleRes);
     60         mDragViews = new ArrayList<View>();
     61 
     62         /**
     63          * Create the {@link ViewDragHelper} and set its callback.
     64          */
     65         mDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
     66             @Override
     67             public boolean tryCaptureView(View child, int pointerId) {
     68                 return mDragViews.contains(child);
     69             }
     70 
     71             @Override
     72             public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
     73                 super.onViewPositionChanged(changedView, left, top, dx, dy);
     74             }
     75 
     76             @Override
     77             public int clampViewPositionHorizontal(View child, int left, int dx) {
     78                 return left;
     79             }
     80 
     81             @Override
     82             public int clampViewPositionVertical(View child, int top, int dy) {
     83                 return top;
     84             }
     85 
     86             @Override
     87             public void onViewCaptured(View capturedChild, int activePointerId) {
     88                 super.onViewCaptured(capturedChild, activePointerId);
     89                 if (mDragFrameLayoutController != null) {
     90                     mDragFrameLayoutController.onDragDrop(true);
     91                 }
     92             }
     93 
     94             @Override
     95             public void onViewReleased(View releasedChild, float xvel, float yvel) {
     96                 super.onViewReleased(releasedChild, xvel, yvel);
     97                 if (mDragFrameLayoutController != null) {
     98                     mDragFrameLayoutController.onDragDrop(false);
     99                 }
    100             }
    101         });
    102     }
    103 
    104     @Override
    105     public boolean onInterceptTouchEvent(MotionEvent ev) {
    106         final int action = ev.getActionMasked();
    107         if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
    108             mDragHelper.cancel();
    109             return false;
    110         }
    111         return mDragHelper.shouldInterceptTouchEvent(ev);
    112     }
    113 
    114     @Override
    115     public boolean onTouchEvent(MotionEvent ev) {
    116         mDragHelper.processTouchEvent(ev);
    117         return true;
    118     }
    119 
    120     /**
    121      * Adds a new {@link View} to the list of views that are draggable within the container.
    122      * @param dragView the {@link View} to make draggable
    123      */
    124     public void addDragView(View dragView) {
    125         mDragViews.add(dragView);
    126     }
    127 
    128     /**
    129      * Sets the {@link DragFrameLayoutController} that will receive the drag events.
    130      * @param dragFrameLayoutController a {@link DragFrameLayoutController}
    131      */
    132     public void setDragFrameController(DragFrameLayoutController dragFrameLayoutController) {
    133         mDragFrameLayoutController = dragFrameLayoutController;
    134     }
    135 
    136     /**
    137      * A controller that will receive the drag events.
    138      */
    139     public interface DragFrameLayoutController {
    140 
    141         public void onDragDrop(boolean captured);
    142     }
    143 }
    144