From 742494d08508b63bc41a7bb55c331cbb49d26767 Mon Sep 17 00:00:00 2001 From: linfaxin <673636904@qq.com> Date: Sun, 15 Mar 2015 20:53:54 +0800 Subject: [PATCH 1/8] improve touch handle and intercept logic : 1.The surface and bottom view could be clickable and longClickable, and it's selector drawables works fine; 2.The swipeLayout can wrap in other gestural layout, the swipe and other layout's gesture work's pretty; --- .../daimajia/swipedemo/ListViewExample.java | 2 +- .../com/daimajia/swipedemo/MyActivity.java | 33 +- .../swipedemo/adapter/ListViewAdapter.java | 6 + demo/src/main/res/drawable/dark_gray.xml | 8 + demo/src/main/res/drawable/red.xml | 8 + demo/src/main/res/drawable/white.xml | 8 + demo/src/main/res/layout/listview_item.xml | 2 +- demo/src/main/res/layout/main.xml | 34 +- demo/src/main/res/layout/sample1.xml | 11 +- demo/src/main/res/layout/sample2.xml | 4 +- demo/src/main/res/values/colors.xml | 4 + .../java/com/daimajia/swipe/SwipeLayout.java | 417 ++++++++---------- 12 files changed, 295 insertions(+), 242 deletions(-) create mode 100644 demo/src/main/res/drawable/dark_gray.xml create mode 100644 demo/src/main/res/drawable/red.xml create mode 100644 demo/src/main/res/drawable/white.xml diff --git a/demo/src/main/java/com/daimajia/swipedemo/ListViewExample.java b/demo/src/main/java/com/daimajia/swipedemo/ListViewExample.java index ab6edf4c..1a945e3b 100644 --- a/demo/src/main/java/com/daimajia/swipedemo/ListViewExample.java +++ b/demo/src/main/java/com/daimajia/swipedemo/ListViewExample.java @@ -68,7 +68,7 @@ public boolean onTouch(View v, MotionEvent event) { @Override public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { Toast.makeText(mContext, "OnItemLongClickListener", Toast.LENGTH_SHORT).show(); - return false; + return true; } }); mListView.setOnScrollListener(new AbsListView.OnScrollListener() { diff --git a/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java b/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java index 0db17605..d65c6d9d 100644 --- a/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java +++ b/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java @@ -4,6 +4,7 @@ import android.content.Intent; import android.graphics.Color; import android.os.Bundle; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -20,6 +21,9 @@ public class MyActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); + SwipeLayout godfatherSwipe = (SwipeLayout) findViewById(R.id.godfather); + godfatherSwipe.setDragEdges(SwipeLayout.DragEdge.Left, SwipeLayout.DragEdge.Right, SwipeLayout.DragEdge.Top, SwipeLayout.DragEdge.Bottom); + godfatherSwipe.setBottomViewIds(R.id.bird_left, R.id.bird_right, R.id.bird_top, R.id.bird_bottom); // SwipeLayout swipeLayout = (SwipeLayout)findViewById(R.id.godfather); // swipeLayout.setDragEdge(SwipeLayout.DragEdge.Bottom); // Set in XML @@ -38,6 +42,21 @@ public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int } }); + sample1.getSurfaceView().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Toast.makeText(MyActivity.this, "Click on surface", Toast.LENGTH_SHORT).show(); + Log.d(MyActivity.class.getName(), "click on surface"); + } + }); + sample1.getSurfaceView().setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + Toast.makeText(MyActivity.this, "longClick on surface", Toast.LENGTH_SHORT).show(); + Log.d(MyActivity.class.getName(), "longClick on surface"); + return true; + } + }); sample1.findViewById(R.id.star2).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -103,6 +122,12 @@ public void onClick(View v) { Toast.makeText(MyActivity.this, "Yo", Toast.LENGTH_SHORT).show(); } }); + sample2.getSurfaceView().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Toast.makeText(MyActivity.this, "Click on surface", Toast.LENGTH_SHORT).show(); + } + }); //sample3 @@ -120,12 +145,18 @@ public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int child.setBackgroundColor(c); } }); - sample3.findViewById(R.id.star).setOnClickListener(new View.OnClickListener() { + sample3.findViewById(R.id.bottom_wrapper_child1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MyActivity.this, "Yo!", Toast.LENGTH_SHORT).show(); } }); + sample3.getSurfaceView().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Toast.makeText(MyActivity.this, "Click on surface", Toast.LENGTH_SHORT).show(); + } + }); } diff --git a/demo/src/main/java/com/daimajia/swipedemo/adapter/ListViewAdapter.java b/demo/src/main/java/com/daimajia/swipedemo/adapter/ListViewAdapter.java index 074e2de2..e34f31de 100644 --- a/demo/src/main/java/com/daimajia/swipedemo/adapter/ListViewAdapter.java +++ b/demo/src/main/java/com/daimajia/swipedemo/adapter/ListViewAdapter.java @@ -43,6 +43,12 @@ public void onDoubleClick(SwipeLayout layout, boolean surface) { Toast.makeText(mContext, "DoubleClick", Toast.LENGTH_SHORT).show(); } }); + v.findViewById(R.id.delete).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Toast.makeText(mContext, "click delete", Toast.LENGTH_SHORT).show(); + } + }); return v; } diff --git a/demo/src/main/res/drawable/dark_gray.xml b/demo/src/main/res/drawable/dark_gray.xml new file mode 100644 index 00000000..46878503 --- /dev/null +++ b/demo/src/main/res/drawable/dark_gray.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/demo/src/main/res/drawable/red.xml b/demo/src/main/res/drawable/red.xml new file mode 100644 index 00000000..707047e9 --- /dev/null +++ b/demo/src/main/res/drawable/red.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/demo/src/main/res/drawable/white.xml b/demo/src/main/res/drawable/white.xml new file mode 100644 index 00000000..8dfff14a --- /dev/null +++ b/demo/src/main/res/drawable/white.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/demo/src/main/res/layout/listview_item.xml b/demo/src/main/res/layout/listview_item.xml index 89620277..4b2c5074 100644 --- a/demo/src/main/res/layout/listview_item.xml +++ b/demo/src/main/res/layout/listview_item.xml @@ -36,7 +36,7 @@ android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="4" - android:background="#ffffff" + android:background="@drawable/white" android:text="Yes,Delete" android:textColor="#FF5534" /> diff --git a/demo/src/main/res/layout/main.xml b/demo/src/main/res/layout/main.xml index 759c1c98..4ba646ad 100644 --- a/demo/src/main/res/layout/main.xml +++ b/demo/src/main/res/layout/main.xml @@ -4,9 +4,39 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/godfather" - android:layout_width="match_parent" android:layout_height="match_parent" - app:drag_edge="bottom"> + android:layout_width="match_parent" android:layout_height="match_parent"> + + + + + + + + + diff --git a/demo/src/main/res/layout/sample1.xml b/demo/src/main/res/layout/sample1.xml index 1dab32d8..01cb2116 100644 --- a/demo/src/main/res/layout/sample1.xml +++ b/demo/src/main/res/layout/sample1.xml @@ -1,7 +1,6 @@ @@ -19,7 +18,8 @@ android:text="Archive" android:layout_weight="0.5" android:gravity="center" - android:background="#FF1300" + android:clickable="true" + android:background="@drawable/red" android:layout_width="wrap_content" android:layout_height="match_parent" /> @@ -61,7 +61,7 @@ android:id="@+id/trash2" android:src="@drawable/trash" android:layout_width="70dp" - android:background="#FF3B30" + android:background="@drawable/red" android:paddingLeft="25dp" android:paddingRight="25dp" android:layout_height="match_parent" /> @@ -74,7 +74,8 @@ android:layout_height="match_parent"> diff --git a/demo/src/main/res/layout/sample2.xml b/demo/src/main/res/layout/sample2.xml index 539e5fa9..08da313e 100644 --- a/demo/src/main/res/layout/sample2.xml +++ b/demo/src/main/res/layout/sample2.xml @@ -26,7 +26,7 @@ android:id="@+id/trash" android:src="@drawable/trash" android:layout_width="70dp" - android:background="#FF3B30" + android:background="@drawable/red" android:paddingLeft="25dp" android:paddingRight="25dp" android:layout_height="match_parent" /> @@ -35,7 +35,7 @@ #E8E8E0 #DBDBD3 + #FF3B00 + #990000 + #4C535B + #ff7e8a97 \ No newline at end of file diff --git a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java index 8568aad9..576c5a23 100644 --- a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java +++ b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java @@ -7,17 +7,17 @@ import android.support.v4.widget.ViewDragHelper; import android.util.AttributeSet; import android.view.GestureDetector; +import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; -import android.widget.Adapter; +import android.widget.AbsListView; import android.widget.AdapterView; -import android.widget.BaseAdapter; import android.widget.FrameLayout; -import android.widget.ListAdapter; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -713,91 +713,128 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - dp2px(getCurrentOffset()); } - private boolean mTouchConsumedByChild = false; + private boolean mIsBeingDragged; + private void checkCanDrag(MotionEvent ev){ + if(mIsBeingDragged) return; + if(getOpenStatus()==Status.Middle){ + mIsBeingDragged = true; + return; + } + Status status = getOpenStatus(); + float distanceX = ev.getRawX() - sX; + float distanceY = ev.getRawY() - sY; + float angle = Math.abs(distanceY / distanceX); + angle = (float) Math.toDegrees(Math.atan(angle)); + if (getOpenStatus() == Status.Close) { + int lastCurrentDirectionIndex = mCurrentDirectionIndex; + if (angle < 45) { + if (mLeftIndex != -1 && distanceX > 0 && isLeftSwipeEnabled()) { + mCurrentDirectionIndex = mLeftIndex; + } else if (mRightIndex != -1 && distanceX < 0 && isRightSwipeEnabled()) { + mCurrentDirectionIndex = mRightIndex; + } + } else { + if (mTopIndex != -1 && distanceY > 0 && isTopSwipeEnabled()) { + mCurrentDirectionIndex = mTopIndex; + } else if (mBottomIndex != -1 && distanceY < 0 && isBottomSwipeEnabled()) { + mCurrentDirectionIndex = mBottomIndex; + } + } + if (lastCurrentDirectionIndex != mCurrentDirectionIndex) { + updateBottomViews(); + } + } + if (!shouldAllowSwipe()) return; - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { + boolean doNothing = false; + if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) { + boolean suitable = (status == Status.Open && distanceX > mTouchSlop) + || (status == Status.Close && distanceX < -mTouchSlop); + suitable = suitable || (status == Status.Middle); - if (!isEnabled() || !isEnabledInAdapterView()) { - return true; + if (angle > 30 || !suitable) { + doNothing = true; + } + } + + if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) { + boolean suitable = (status == Status.Open && distanceX < -mTouchSlop) + || (status == Status.Close && distanceX > mTouchSlop); + suitable = suitable || status == Status.Middle; + + if (angle > 30 || !suitable) { + doNothing = true; + } + } + + if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) { + boolean suitable = (status == Status.Open && distanceY < -mTouchSlop) + || (status == Status.Close && distanceY > mTouchSlop); + suitable = suitable || status == Status.Middle; + + if (angle < 60 || !suitable) { + doNothing = true; + } } + if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Bottom) { + boolean suitable = (status == Status.Open && distanceY > mTouchSlop) + || (status == Status.Close && distanceY < -mTouchSlop); + suitable = suitable || status == Status.Middle; + + if (angle < 60 || !suitable) { + doNothing = true; + } + } + mIsBeingDragged = !doNothing; + } + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { if (!isSwipeEnabled()) { return false; } - for (SwipeDenier denier : mSwipeDeniers) { if (denier != null && denier.shouldDenySwipe(ev)) { return false; } } - // - // if a child wants to handle the touch event, - // then let it do it. - // - int action = ev.getActionMasked(); - switch (action) { + + switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: - Status status = getOpenStatus(); - if (status == Status.Close) { - mTouchConsumedByChild = childNeedHandleTouchEvent(getSurfaceView(), ev) != null; - } else if (status == Status.Open) { - mTouchConsumedByChild = childNeedHandleTouchEvent(getBottomViews().get(mCurrentDirectionIndex), ev) != null; + mDragHelper.processTouchEvent(ev); + mIsBeingDragged = false; + sX = ev.getRawX(); + sY = ev.getRawY(); + //if the swipe is in middle state(scrolling), should intercept the touch + if(getOpenStatus() == Status.Middle){ + mIsBeingDragged = true; + } + break; + case MotionEvent.ACTION_MOVE: + boolean beforeCheck = mIsBeingDragged; + checkCanDrag(ev); + if (mIsBeingDragged) { + ViewParent parent = getParent(); + if(parent!=null){ + parent.requestDisallowInterceptTouchEvent(true); + } + } + if(!beforeCheck && mIsBeingDragged){ + //let children has one chance to catch the touch, and request the swipe not intercept + //useful when swipeLayout wrap a swipeLayout or other gestural layout + return false; } break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - mTouchConsumedByChild = false; - } - - if (mTouchConsumedByChild) return false; - return mDragHelper.shouldInterceptTouchEvent(ev); - } - - /** - * if the ViewGroup children want to handle this event. - * - * @param v - * @param event - * @return - */ - private View childNeedHandleTouchEvent(ViewGroup v, MotionEvent event) { - if (v == null) return null; - if (v.onTouchEvent(event)) return v; - - int childCount = v.getChildCount(); - for (int i = childCount - 1; i >= 0; i--) { - View child = v.getChildAt(i); - if (child instanceof ViewGroup) { - View grandChild = childNeedHandleTouchEvent((ViewGroup) child, event); - if (grandChild != null) return grandChild; - } else { - if (childNeedHandleTouchEvent(v.getChildAt(i), event)) return v.getChildAt(i); - } - } - return null; - } - - /** - * if the view (v) wants to handle this event. - * - * @param v - * @param event - * @return - */ - private boolean childNeedHandleTouchEvent(View v, MotionEvent event) { - if (v == null) return false; - - int[] loc = new int[2]; - v.getLocationOnScreen(loc); - int left = loc[0], top = loc[1]; - if (event.getRawX() > left && event.getRawX() < left + v.getWidth() && event.getRawY() > top - && event.getRawY() < top + v.getHeight()) { - return v.onTouchEvent(event); + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + mIsBeingDragged = false; + mDragHelper.processTouchEvent(ev); + break; + default://handle other action, such as ACTION_POINTER_DOWN/UP + mDragHelper.processTouchEvent(ev); } - - return false; + return mIsBeingDragged; } private float sX = -1, sY = -1; @@ -812,148 +849,38 @@ private boolean shouldAllowSwipe() { @Override public boolean onTouchEvent(MotionEvent event) { - if (!isEnabledInAdapterView() || !isEnabled()) return true; - if (!isSwipeEnabled()) return super.onTouchEvent(event); int action = event.getActionMasked(); - ViewParent parent = getParent(); - gestureDetector.onTouchEvent(event); - Status status = getOpenStatus(); - ViewGroup touching = null; - if (status == Status.Close) { - touching = getSurfaceView(); - } else if (status == Status.Open) { - touching = getBottomViews().get(mCurrentDirectionIndex); - } switch (action) { case MotionEvent.ACTION_DOWN: mDragHelper.processTouchEvent(event); - parent.requestDisallowInterceptTouchEvent(true); - sX = event.getRawX(); sY = event.getRawY(); - if (touching != null) touching.setPressed(true); - return true; - case MotionEvent.ACTION_MOVE: { - float distanceX = event.getRawX() - sX; - float distanceY = event.getRawY() - sY; - float angle = Math.abs(distanceY / distanceX); - angle = (float) Math.toDegrees(Math.atan(angle)); - if (getOpenStatus() == Status.Close) { - int lastCurrentDirectionIndex = mCurrentDirectionIndex; - if (angle < 45) { - if (mLeftIndex != -1 && distanceX > 0 && isLeftSwipeEnabled()) { - mCurrentDirectionIndex = mLeftIndex; - } else if (mRightIndex != -1 && distanceX < 0 && isRightSwipeEnabled()) { - mCurrentDirectionIndex = mRightIndex; - } - } else { - if (mTopIndex != -1 && distanceY > 0 && isTopSwipeEnabled()) { - mCurrentDirectionIndex = mTopIndex; - } else if (mBottomIndex != -1 && distanceY < 0 && isBottomSwipeEnabled()) { - mCurrentDirectionIndex = mBottomIndex; - } - } - if (lastCurrentDirectionIndex != mCurrentDirectionIndex) { - updateBottomViews(); - } - } - if (!shouldAllowSwipe()) return super.onTouchEvent(event); - - boolean doNothing = false; - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) { - boolean suitable = (status == Status.Open && distanceX > mTouchSlop) - || (status == Status.Close && distanceX < -mTouchSlop); - suitable = suitable || (status == Status.Middle); - - if (angle > 30 || !suitable) { - doNothing = true; - } - } - - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) { - boolean suitable = (status == Status.Open && distanceX < -mTouchSlop) - || (status == Status.Close && distanceX > mTouchSlop); - suitable = suitable || status == Status.Middle; - - if (angle > 30 || !suitable) { - doNothing = true; - } - } - - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) { - boolean suitable = (status == Status.Open && distanceY < -mTouchSlop) - || (status == Status.Close && distanceY > mTouchSlop); - suitable = suitable || status == Status.Middle; - - if (angle < 60 || !suitable) { - doNothing = true; - } - } - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Bottom) { - boolean suitable = (status == Status.Open && distanceY > mTouchSlop) - || (status == Status.Close && distanceY < -mTouchSlop); - suitable = suitable || status == Status.Middle; - - if (angle < 60 || !suitable) { - doNothing = true; - } - } - - if (doNothing) { - parent.requestDisallowInterceptTouchEvent(false); - return false; - } else { - if (touching != null) { - touching.setPressed(false); - } - parent.requestDisallowInterceptTouchEvent(true); + case MotionEvent.ACTION_MOVE: { + //the drag state and the direction are already judged at onInterceptTouchEvent + checkCanDrag(event); + if(mIsBeingDragged){ + getParent().requestDisallowInterceptTouchEvent(true); mDragHelper.processTouchEvent(event); } break; } case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: { - sX = -1; - sY = -1; - if (touching != null) { - touching.setPressed(false); - } - } - default: - parent.requestDisallowInterceptTouchEvent(true); + case MotionEvent.ACTION_CANCEL: + mIsBeingDragged = false; mDragHelper.processTouchEvent(event); - } - - return true; - } + break; - /** - * if working in {@link android.widget.AdapterView}, we should response - * {@link android.widget.Adapter} isEnable(int position). - * - * @return true when item is enabled, else disabled. - */ - private boolean isEnabledInAdapterView() { - AdapterView adapterView = getAdapterView(); - boolean enable = true; - if (adapterView != null) { - Adapter adapter = adapterView.getAdapter(); - if (adapter != null) { - int p = adapterView.getPositionForView(SwipeLayout.this); - if (adapter instanceof BaseAdapter) { - enable = ((BaseAdapter) adapter).isEnabled(p); - } else if (adapter instanceof ListAdapter) { - enable = ((ListAdapter) adapter).isEnabled(p); - } - } + default://handle other action, such as ACTION_POINTER_DOWN/UP + mDragHelper.processTouchEvent(event); } - return enable; + + return super.onTouchEvent(event) || mIsBeingDragged || action == MotionEvent.ACTION_DOWN; } public void setSwipeEnabled(boolean enabled) { @@ -995,7 +922,6 @@ public boolean isBottomSwipeEnabled() { public void setBottomSwipeEnabled(boolean bottomSwipeEnabled) { this.mBottomSwipeEnabled = bottomSwipeEnabled; } - private boolean insideAdapterView() { return getAdapterView() != null; } @@ -1011,7 +937,8 @@ private AdapterView getAdapterView() { return null; } - private void performAdapterViewItemClick(MotionEvent e) { + private void performAdapterViewItemClick() { + if(getOpenStatus()!= Status.Close) return; ViewParent t = getParent(); while (t != null) { if (t instanceof AdapterView) { @@ -1020,52 +947,82 @@ private void performAdapterViewItemClick(MotionEvent e) { if (p != AdapterView.INVALID_POSITION && view.performItemClick(view.getChildAt(p - view.getFirstVisiblePosition()), p, view .getAdapter().getItemId(p))) return; - } else { - if (t instanceof View && ((View) t).performClick()) return; } t = t.getParent(); } } + private boolean performAdapterViewItemLongClick() { + if(getOpenStatus()!= Status.Close) return false; + ViewParent t = getParent(); + while (t != null) { + if (t instanceof AdapterView) { - private GestureDetector gestureDetector = new GestureDetector(getContext(), new SwipeDetector()); - - class SwipeDetector extends GestureDetector.SimpleOnGestureListener { - @Override - public boolean onDown(MotionEvent e) { - return true; - } - - /** - * Simulate the touch event lifecycle. If you use SwipeLayout in - * {@link android.widget.AdapterView} ({@link android.widget.ListView}, - * {@link android.widget.GridView} etc.) It will manually call - * {@link android.widget.AdapterView}.performItemClick, - * performItemLongClick. - * - * @param e - * @return - */ - @Override - public boolean onSingleTapUp(MotionEvent e) { - if (mDoubleClickListener == null) { - performAdapterViewItemClick(e); + AdapterView view = (AdapterView) t; + int p = view.getPositionForView(SwipeLayout.this); + if (p == AdapterView.INVALID_POSITION) return false; + long vId = view.getItemIdAtPosition(p); + boolean handled = false; + try { + Method m = AbsListView.class.getDeclaredMethod("performLongPress", View.class, int.class, long.class); + m.setAccessible(true); + handled = (boolean) m.invoke(view, SwipeLayout.this, p, vId); + + } catch (Exception e) { + e.printStackTrace(); + + if (view.getOnItemLongClickListener() != null) { + handled = view.getOnItemLongClickListener().onItemLongClick(view, SwipeLayout.this, p, vId); + } + if (handled) { + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } + } + return handled; } - return true; + t = t.getParent(); } - - @Override - public boolean onSingleTapConfirmed(MotionEvent e) { - if (mDoubleClickListener != null) { - performAdapterViewItemClick(e); + return false; + } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if(insideAdapterView()){ + if(clickListener==null){ + setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + performAdapterViewItemClick(); + } + }); + } + if(longClickListener==null){ + setOnLongClickListener(new OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + performAdapterViewItemLongClick(); + return true; + } + }); } - return true; } + } + OnClickListener clickListener; + @Override + public void setOnClickListener(OnClickListener l) { + super.setOnClickListener(l); + clickListener = l; + } + OnLongClickListener longClickListener; + @Override + public void setOnLongClickListener(OnLongClickListener l) { + super.setOnLongClickListener(l); + longClickListener = l; + } - @Override - public void onLongPress(MotionEvent e) { - performLongClick(); - } + private GestureDetector gestureDetector = new GestureDetector(getContext(), new SwipeDetector()); + + class SwipeDetector extends GestureDetector.SimpleOnGestureListener { @Override public boolean onDoubleTap(MotionEvent e) { if (mDoubleClickListener != null) { From 8e89db06b0e599ad60930f6a4336aa93b3ef81b6 Mon Sep 17 00:00:00 2001 From: linfaxin <673636904@qq.com> Date: Mon, 16 Mar 2015 10:33:18 +0800 Subject: [PATCH 2/8] Handle the itemClick and the itemLongClick only when the SwipeLayout is the root of AdapterView's item, --- .../java/com/daimajia/swipe/SwipeLayout.java | 65 ++++++++----------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java index 576c5a23..d6b58f0e 100644 --- a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java +++ b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java @@ -928,11 +928,8 @@ private boolean insideAdapterView() { private AdapterView getAdapterView() { ViewParent t = getParent(); - while (t != null) { - if (t instanceof AdapterView) { - return (AdapterView) t; - } - t = t.getParent(); + if (t instanceof AdapterView) { + return (AdapterView) t; } return null; } @@ -940,46 +937,40 @@ private AdapterView getAdapterView() { private void performAdapterViewItemClick() { if(getOpenStatus()!= Status.Close) return; ViewParent t = getParent(); - while (t != null) { - if (t instanceof AdapterView) { - AdapterView view = (AdapterView) t; - int p = view.getPositionForView(SwipeLayout.this); - if (p != AdapterView.INVALID_POSITION - && view.performItemClick(view.getChildAt(p - view.getFirstVisiblePosition()), p, view - .getAdapter().getItemId(p))) return; + if (t instanceof AdapterView) { + AdapterView view = (AdapterView) t; + int p = view.getPositionForView(SwipeLayout.this); + if (p != AdapterView.INVALID_POSITION){ + view.performItemClick(view.getChildAt(p - view.getFirstVisiblePosition()), p, view + .getAdapter().getItemId(p)); } - t = t.getParent(); } } private boolean performAdapterViewItemLongClick() { if(getOpenStatus()!= Status.Close) return false; ViewParent t = getParent(); - while (t != null) { - if (t instanceof AdapterView) { - - AdapterView view = (AdapterView) t; - int p = view.getPositionForView(SwipeLayout.this); - if (p == AdapterView.INVALID_POSITION) return false; - long vId = view.getItemIdAtPosition(p); - boolean handled = false; - try { - Method m = AbsListView.class.getDeclaredMethod("performLongPress", View.class, int.class, long.class); - m.setAccessible(true); - handled = (boolean) m.invoke(view, SwipeLayout.this, p, vId); - - } catch (Exception e) { - e.printStackTrace(); - - if (view.getOnItemLongClickListener() != null) { - handled = view.getOnItemLongClickListener().onItemLongClick(view, SwipeLayout.this, p, vId); - } - if (handled) { - view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - } + if (t instanceof AdapterView) { + AdapterView view = (AdapterView) t; + int p = view.getPositionForView(SwipeLayout.this); + if (p == AdapterView.INVALID_POSITION) return false; + long vId = view.getItemIdAtPosition(p); + boolean handled = false; + try { + Method m = AbsListView.class.getDeclaredMethod("performLongPress", View.class, int.class, long.class); + m.setAccessible(true); + handled = (boolean) m.invoke(view, SwipeLayout.this, p, vId); + + } catch (Exception e) { + e.printStackTrace(); + + if (view.getOnItemLongClickListener() != null) { + handled = view.getOnItemLongClickListener().onItemLongClick(view, SwipeLayout.this, p, vId); + } + if (handled) { + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); } - return handled; } - t = t.getParent(); + return handled; } return false; } From 6e909b0343c03d95f76a16496b89459905ee54da Mon Sep 17 00:00:00 2001 From: linfaxin <673636904@qq.com> Date: Tue, 17 Mar 2015 18:33:37 +0800 Subject: [PATCH 3/8] The bottom and surface views needn't be ViewGroup. The bottom view can use layout_gravity to indicate the swiping direction --- .../com/daimajia/swipedemo/MyActivity.java | 3 - demo/src/main/res/layout/main.xml | 31 ++--- demo/src/main/res/layout/sample3.xml | 12 +- .../java/com/daimajia/swipe/SwipeLayout.java | 114 ++++++++++++++++-- 4 files changed, 123 insertions(+), 37 deletions(-) diff --git a/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java b/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java index d65c6d9d..d66656a6 100644 --- a/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java +++ b/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java @@ -21,9 +21,6 @@ public class MyActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); - SwipeLayout godfatherSwipe = (SwipeLayout) findViewById(R.id.godfather); - godfatherSwipe.setDragEdges(SwipeLayout.DragEdge.Left, SwipeLayout.DragEdge.Right, SwipeLayout.DragEdge.Top, SwipeLayout.DragEdge.Bottom); - godfatherSwipe.setBottomViewIds(R.id.bird_left, R.id.bird_right, R.id.bird_top, R.id.bird_bottom); // SwipeLayout swipeLayout = (SwipeLayout)findViewById(R.id.godfather); // swipeLayout.setDragEdge(SwipeLayout.DragEdge.Bottom); // Set in XML diff --git a/demo/src/main/res/layout/main.xml b/demo/src/main/res/layout/main.xml index 4ba646ad..55963be5 100644 --- a/demo/src/main/res/layout/main.xml +++ b/demo/src/main/res/layout/main.xml @@ -1,32 +1,24 @@ - - + - - - + - - + android:layout_height="match_parent" /> @@ -37,6 +29,7 @@ diff --git a/demo/src/main/res/layout/sample3.xml b/demo/src/main/res/layout/sample3.xml index dbad9873..199c59e8 100644 --- a/demo/src/main/res/layout/sample3.xml +++ b/demo/src/main/res/layout/sample3.xml @@ -22,15 +22,11 @@ - - - + android:layout_height="match_parent" /> \ No newline at end of file diff --git a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java index d6b58f0e..fb98b5ff 100644 --- a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java +++ b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java @@ -3,10 +3,13 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; +import android.os.Build; +import android.support.v4.view.GravityCompat; import android.support.v4.view.ViewCompat; import android.support.v4.widget.ViewDragHelper; import android.util.AttributeSet; import android.view.GestureDetector; +import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; @@ -19,6 +22,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -118,6 +122,7 @@ public SwipeLayout(Context context, AttributeSet attrs, int defStyle) { int ordinal = a.getInt(R.styleable.SwipeLayout_show_mode, ShowMode.PullOut.ordinal()); mShowMode = ShowMode.values()[ordinal]; a.recycle(); + } public interface SwipeListener { @@ -660,12 +665,95 @@ public void addOnLayoutListener(OnLayout l) { public void removeOnLayoutListener(OnLayout l) { if (mOnLayoutListeners != null) mOnLayoutListeners.remove(l); } + public void addBottomView(View child, DragEdge dragEdge){ + addBottomView(child, null, dragEdge); + } + public void addBottomView(View child, ViewGroup.LayoutParams params, DragEdge dragEdge){ + if(params==null){ + params = generateDefaultLayoutParams(); + } + if(!checkLayoutParams(params)){ + params = generateLayoutParams(params); + } + int gravity = -1; + switch (dragEdge){ + case Left:gravity = Gravity.LEFT;break; + case Right:gravity = Gravity.RIGHT;break; + case Top:gravity = Gravity.TOP;break; + case Bottom:gravity = Gravity.BOTTOM;break; + } + if(params instanceof FrameLayout.LayoutParams){ + ((LayoutParams) params).gravity = gravity; + } + super.addView(child, 0, params); + } + @Override + public void addView(View child, int index, ViewGroup.LayoutParams params) { + //the child should be viewGroup, convert child here + if(!(child instanceof ViewGroup)){ + WrapGroup childContain = new WrapGroup(getContext()); + childContain.addView(child); + child = childContain; + } + + int gravity = Gravity.NO_GRAVITY; + try { + gravity = (Integer) params.getClass().getField("gravity").get(params); + } catch (Exception e) { + e.printStackTrace(); + } + + if(gravity>0){ + //declared the layout_gravity, set the child's drag edge + if(child.getId()==View.NO_ID){ + if(Build.VERSION.SDK_INT<17){ + child.setId(child.hashCode()); + }else{ + child.setId(View.generateViewId()); + } + } + gravity = GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this)); + + if(gravity == Gravity.LEFT){ + mBottomViewIdsSet = true; + if(!mDragEdges.contains(DragEdge.Left)){ + mDragEdges.add(DragEdge.Left); + } + mBottomViewIdMap.put(DragEdge.Left, child.getId()); + } + if(gravity == Gravity.RIGHT){ + mBottomViewIdsSet = true; + if(!mDragEdges.contains(DragEdge.Right)){ + mDragEdges.add(DragEdge.Right); + } + mBottomViewIdMap.put(DragEdge.Right, child.getId()); + } + if(gravity == Gravity.TOP){ + mBottomViewIdsSet = true; + if(!mDragEdges.contains(DragEdge.Top)){ + mDragEdges.add(DragEdge.Top); + } + mBottomViewIdMap.put(DragEdge.Top, child.getId()); + } + if(gravity == Gravity.BOTTOM){ + mBottomViewIdsSet = true; + if(!mDragEdges.contains(DragEdge.Bottom)){ + mDragEdges.add(DragEdge.Bottom); + } + mBottomViewIdMap.put(DragEdge.Bottom, child.getId()); + } + populateIndexes(); + } + super.addView(child, index, params); + } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); if (childCount != 1 + mDragEdges.size()) { - throw new IllegalStateException("You need to have one surface view plus one view for each of your drag edges"); + throw new IllegalStateException("You need to have one surface view plus one view for each of your drag edges." + + " ChildCount:" + childCount + + ", mDragEdges.size():"+ mDragEdges.size()); } for (int i = 0; i < childCount; i++) { if (!(getChildAt(i) instanceof ViewGroup)) { @@ -1081,21 +1169,26 @@ public ViewGroup getSurfaceView() { return (ViewGroup) getChildAt(getChildCount() - 1); } + /** + * @return all bottomViews. + */ public List getBottomViews() { List lvg = new ArrayList(); // If the user has provided a map for views to if (mBottomViewIdsSet) { + lvg.addAll(Arrays.asList(new ViewGroup[mDragEdges.size()])); + if (mDragEdges.contains(DragEdge.Left)) { - lvg.add(mLeftIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Left)))); - } - if (mDragEdges.contains(DragEdge.Right)) { - lvg.add(mRightIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Right)))); + lvg.set(mLeftIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Left)))); } if (mDragEdges.contains(DragEdge.Top)) { - lvg.add(mTopIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Top)))); + lvg.set(mTopIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Top)))); + } + if (mDragEdges.contains(DragEdge.Right)) { + lvg.set(mRightIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Right)))); } if (mDragEdges.contains(DragEdge.Bottom)) { - lvg.add(mBottomIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Bottom)))); + lvg.set(mBottomIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Bottom)))); } } // Default behaviour is to simply use the first n-1 children in the order they're listed in the layout @@ -1524,4 +1617,11 @@ private void updateBottomViews() { mOnLayoutListeners.get(i).onLayout(this); } } + + //if child is not viewGroup, this group will wrap it + public class WrapGroup extends FrameLayout{ + public WrapGroup(Context context) { + super(context); + } + } } From 8412d5013119cde192bec9e44a2dbc34ac9e7bfc Mon Sep 17 00:00:00 2001 From: linfaxin <673636904@qq.com> Date: Thu, 19 Mar 2015 11:36:29 +0800 Subject: [PATCH 4/8] Support clickToClose attr, if set to true, the opened swipeLayout will auto close when click on it's surface view --- demo/src/main/res/layout/sample1.xml | 7 ++++-- .../java/com/daimajia/swipe/SwipeLayout.java | 23 +++++++++++++++++++ library/src/main/res/values/attrs.xml | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/demo/src/main/res/layout/sample1.xml b/demo/src/main/res/layout/sample1.xml index 01cb2116..fd776dd9 100644 --- a/demo/src/main/res/layout/sample1.xml +++ b/demo/src/main/res/layout/sample1.xml @@ -1,8 +1,11 @@ - + android:layout_height="80dp" + app:clickToClose="true"> (); if ((dragEdgeChoices & DRAG_LEFT) == DRAG_LEFT) { @@ -881,6 +883,13 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { if (!isSwipeEnabled()) { return false; } + if(mClickToClose && getOpenStatus() == Status.Open && getSurfaceView()!=null){ + Rect rect = new Rect(); + getSurfaceView().getHitRect(rect); + if(rect.contains((int)ev.getX(), (int)ev.getY())){ + return true; + } + } for (SwipeDenier denier : mSwipeDeniers) { if (denier != null && denier.shouldDenySwipe(ev)) { return false; @@ -970,6 +979,13 @@ public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event) || mIsBeingDragged || action == MotionEvent.ACTION_DOWN; } + public boolean isClickToClose() { + return mClickToClose; + } + + public void setClickToClose(boolean mClickToClose) { + this.mClickToClose = mClickToClose; + } public void setSwipeEnabled(boolean enabled) { mSwipeEnabled = enabled; @@ -1102,6 +1118,13 @@ public void setOnLongClickListener(OnLongClickListener l) { private GestureDetector gestureDetector = new GestureDetector(getContext(), new SwipeDetector()); class SwipeDetector extends GestureDetector.SimpleOnGestureListener { + @Override + public boolean onSingleTapUp(MotionEvent e) { + if(mClickToClose){ + close(); + } + return super.onSingleTapUp(e); + } @Override public boolean onDoubleTap(MotionEvent e) { if (mDoubleClickListener != null) { diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 249b944e..a671fc5f 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -15,5 +15,6 @@ + \ No newline at end of file From 8fea955083c0f0ef8f39d632ba98c156b4d82dae Mon Sep 17 00:00:00 2001 From: linfaxin <673636904@qq.com> Date: Thu, 19 Mar 2015 20:26:34 +0800 Subject: [PATCH 5/8] Improve the release drag logic. --- .../java/com/daimajia/swipe/SwipeLayout.java | 74 +++++++++++++------ 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java index 71c0cb34..ab695bd2 100644 --- a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java +++ b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java @@ -323,7 +323,11 @@ public int clampViewPositionVertical(View child, int top, int dy) { @Override public boolean tryCaptureView(View child, int pointerId) { - return child == getSurfaceView() || getBottomViews().contains(child); + boolean result = child == getSurfaceView() || getBottomViews().contains(child); + if(result){ + isCloseBeforeDrag = getOpenStatus() == Status.Close; + } + return result; } @Override @@ -336,13 +340,14 @@ public int getViewVerticalDragRange(View child) { return mDragDistance; } + boolean isCloseBeforeDrag = true; @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); for (SwipeListener l : mSwipeListeners) l.onHandRelease(SwipeLayout.this, xvel, yvel); if (releasedChild == getSurfaceView()) { - processSurfaceRelease(xvel, yvel); + processSurfaceRelease(xvel, yvel, isCloseBeforeDrag); } else if (getBottomViews().contains(releasedChild)) { if (getShowMode() == ShowMode.PullOut) { processBottomPullOutRelease(xvel, yvel); @@ -1284,37 +1289,58 @@ public Status getOpenStatus() { return Status.Middle; } + /** * Process the surface release event. * - * @param xvel - * @param yvel + * @param xvel xVelocity + * @param yvel yVelocity + * @param isCloseBeforeDragged the open state before drag */ - private void processSurfaceRelease(float xvel, float yvel) { - if (xvel == 0 && getOpenStatus() == Status.Middle) close(); - - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left - || mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) { - if (xvel > 0) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) - open(); + private void processSurfaceRelease(float xvel, float yvel, boolean isCloseBeforeDragged) { + float minVelocity = mDragHelper.getMinVelocity(); + View surfaceView = getSurfaceView(); + DragEdge currentDragEdge = null; + try { + currentDragEdge = mDragEdges.get(mCurrentDirectionIndex); + } catch (Exception e) { + e.printStackTrace(); + } + if(currentDragEdge == null || surfaceView == null){ + return; + } + float willOpenPercent = (isCloseBeforeDragged ? .3f : .7f); + if(currentDragEdge == DragEdge.Left){ + if(xvel > minVelocity) open(); + else if(xvel < -minVelocity) close(); + else{ + float openPercent = 1f * getSurfaceView().getLeft() / mDragDistance; + if(openPercent > willOpenPercent ) open(); else close(); } - if (xvel < 0) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) - close(); - else open(); + }else if(currentDragEdge == DragEdge.Right){ + if(xvel > minVelocity) close(); + else if(xvel < -minVelocity) open(); + else{ + float openPercent = 1f * (-getSurfaceView().getLeft()) / mDragDistance; + if(openPercent > willOpenPercent ) open(); + else close(); } - } else { - if (yvel > 0) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) - open(); + }else if(currentDragEdge == DragEdge.Top){ + if(yvel > minVelocity) open(); + else if(yvel < -minVelocity) close(); + else{ + float openPercent = 1f * getSurfaceView().getTop() / mDragDistance; + if(openPercent > willOpenPercent ) open(); else close(); } - if (yvel < 0) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) - close(); - else open(); + }else if(currentDragEdge == DragEdge.Bottom){ + if(yvel > minVelocity) close(); + else if(yvel < -minVelocity) open(); + else{ + float openPercent = 1f * (-getSurfaceView().getTop()) / mDragDistance; + if(openPercent > willOpenPercent ) open(); + else close(); } } } From b460d4dd47a417de24ec9ae28234ac943c57dc28 Mon Sep 17 00:00:00 2001 From: linfaxin <673636904@qq.com> Date: Sat, 21 Mar 2015 22:39:41 +0800 Subject: [PATCH 6/8] Optimize the implement when surface or bottom not a GroupView --- demo/src/main/res/layout/sample1.xml | 13 ++--- .../java/com/daimajia/swipe/SwipeLayout.java | 51 ++++++------------- 2 files changed, 20 insertions(+), 44 deletions(-) diff --git a/demo/src/main/res/layout/sample1.xml b/demo/src/main/res/layout/sample1.xml index fd776dd9..350bdb0f 100644 --- a/demo/src/main/res/layout/sample1.xml +++ b/demo/src/main/res/layout/sample1.xml @@ -91,17 +91,12 @@ - - - - + android:layout_height="match_parent" /> diff --git a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java index ab695bd2..b95ce6ba 100644 --- a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java +++ b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java @@ -560,10 +560,10 @@ protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, boolean open) */ private void safeBottomView() { Status status = getOpenStatus(); - List bottoms = getBottomViews(); + List bottoms = getBottomViews(); if (status == Status.Close) { - for (ViewGroup bottom : bottoms) { + for (View bottom : bottoms) { if (bottom.getVisibility() != INVISIBLE) bottom.setVisibility(INVISIBLE); } } else { @@ -696,13 +696,6 @@ public void addBottomView(View child, ViewGroup.LayoutParams params, DragEdge dr } @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { - //the child should be viewGroup, convert child here - if(!(child instanceof ViewGroup)){ - WrapGroup childContain = new WrapGroup(getContext()); - childContain.addView(child); - child = childContain; - } - int gravity = Gravity.NO_GRAVITY; try { gravity = (Integer) params.getClass().getField("gravity").get(params); @@ -762,11 +755,6 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { " ChildCount:" + childCount + ", mDragEdges.size():"+ mDragEdges.size()); } - for (int i = 0; i < childCount; i++) { - if (!(getChildAt(i) instanceof ViewGroup)) { - throw new IllegalArgumentException("All the children in SwipeLayout must be an instance of ViewGroup"); - } - } if (mShowMode == ShowMode.PullOut) layoutPullOut(); @@ -1134,8 +1122,8 @@ public boolean onSingleTapUp(MotionEvent e) { public boolean onDoubleTap(MotionEvent e) { if (mDoubleClickListener != null) { View target; - ViewGroup bottom = getBottomViews().get(mCurrentDirectionIndex); - ViewGroup surface = getSurfaceView(); + View bottom = getBottomViews().get(mCurrentDirectionIndex); + View surface = getSurfaceView(); if (e.getX() > bottom.getLeft() && e.getX() < bottom.getRight() && e.getY() > bottom.getTop() && e.getY() < bottom.getBottom()) { target = bottom; @@ -1193,37 +1181,37 @@ public ShowMode getShowMode() { return mShowMode; } - public ViewGroup getSurfaceView() { - return (ViewGroup) getChildAt(getChildCount() - 1); + public View getSurfaceView() { + return (View) getChildAt(getChildCount() - 1); } /** * @return all bottomViews. */ - public List getBottomViews() { - List lvg = new ArrayList(); + public List getBottomViews() { + List lvg = new ArrayList(); // If the user has provided a map for views to if (mBottomViewIdsSet) { - lvg.addAll(Arrays.asList(new ViewGroup[mDragEdges.size()])); + lvg.addAll(Arrays.asList(new View[mDragEdges.size()])); if (mDragEdges.contains(DragEdge.Left)) { - lvg.set(mLeftIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Left)))); + lvg.set(mLeftIndex, ((View) findViewById(mBottomViewIdMap.get(DragEdge.Left)))); } if (mDragEdges.contains(DragEdge.Top)) { - lvg.set(mTopIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Top)))); + lvg.set(mTopIndex, ((View) findViewById(mBottomViewIdMap.get(DragEdge.Top)))); } if (mDragEdges.contains(DragEdge.Right)) { - lvg.set(mRightIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Right)))); + lvg.set(mRightIndex, ((View) findViewById(mBottomViewIdMap.get(DragEdge.Right)))); } if (mDragEdges.contains(DragEdge.Bottom)) { - lvg.set(mBottomIndex, ((ViewGroup) findViewById(mBottomViewIdMap.get(DragEdge.Bottom)))); + lvg.set(mBottomIndex, ((View) findViewById(mBottomViewIdMap.get(DragEdge.Bottom)))); } } // Default behaviour is to simply use the first n-1 children in the order they're listed in the layout // and return them in else { for (int i = 0; i < (getChildCount() - 1); i++) { - lvg.add((ViewGroup) getChildAt(i)); + lvg.add((View) getChildAt(i)); } } return lvg; @@ -1418,7 +1406,7 @@ public void open(boolean smooth) { } public void open(boolean smooth, boolean notify) { - ViewGroup surface = getSurfaceView(), bottom = getBottomViews().get(mCurrentDirectionIndex); + View surface = getSurfaceView(), bottom = getBottomViews().get(mCurrentDirectionIndex); int dx, dy; Rect rect = computeSurfaceLayoutArea(true); if (smooth) { @@ -1501,7 +1489,7 @@ public void close(boolean smooth) { * @param notify if notify all the listeners. */ public void close(boolean smooth, boolean notify) { - ViewGroup surface = getSurfaceView(); + View surface = getSurfaceView(); int dx, dy; if (smooth) mDragHelper.smoothSlideViewTo(getSurfaceView(), getPaddingLeft(), getPaddingTop()); @@ -1666,11 +1654,4 @@ private void updateBottomViews() { mOnLayoutListeners.get(i).onLayout(this); } } - - //if child is not viewGroup, this group will wrap it - public class WrapGroup extends FrameLayout{ - public WrapGroup(Context context) { - super(context); - } - } } From 79bb4ecb36cfa82595a176e72bebafff7261d50c Mon Sep 17 00:00:00 2001 From: linfaxin <673636904@qq.com> Date: Sun, 22 Mar 2015 11:14:54 +0800 Subject: [PATCH 7/8] Refactor. Stronger and easier. --- .../com/daimajia/swipedemo/MyActivity.java | 4 +- demo/src/main/res/layout/main.xml | 22 +- .../java/com/daimajia/swipe/SwipeLayout.java | 727 +++++++----------- 3 files changed, 300 insertions(+), 453 deletions(-) diff --git a/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java b/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java index d66656a6..f7ba4476 100644 --- a/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java +++ b/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java @@ -29,9 +29,9 @@ protected void onCreate(Bundle savedInstanceState) { sample1 = (SwipeLayout) findViewById(R.id.sample1); sample1.setShowMode(SwipeLayout.ShowMode.PullOut); - sample1.setDragEdges(SwipeLayout.DragEdge.Left, SwipeLayout.DragEdge.Right, SwipeLayout.DragEdge.Top); +// sample1.setDragEdges(SwipeLayout.DragEdge.Left, SwipeLayout.DragEdge.Right, SwipeLayout.DragEdge.Top); // When using multiple drag edges it's a good idea to pass the ids of the views that you're using for the left, right, top bottom views (-1 if you're not using a particular view) - sample1.setBottomViewIds(R.id.bottom_wrapper, R.id.bottom_wrapper_2, R.id.starbott, SwipeLayout.EMPTY_LAYOUT); + sample1.setBottomViewIds(R.id.bottom_wrapper, R.id.bottom_wrapper_2, R.id.starbott, R.id.starbott); sample1.addRevealListener(R.id.delete, new SwipeLayout.OnRevealListener() { @Override public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int distance) { diff --git a/demo/src/main/res/layout/main.xml b/demo/src/main/res/layout/main.xml index 55963be5..cf05988e 100644 --- a/demo/src/main/res/layout/main.xml +++ b/demo/src/main/res/layout/main.xml @@ -5,28 +5,10 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - - + android:layout_height="100dp" /> mDragEdges; + private LinkedHashMap mDragEdges = new LinkedHashMap(); private ShowMode mShowMode; - private float mLeftEdgeSwipeOffset; - private float mRightEdgeSwipeOffset; - private float mTopEdgeSwipeOffset; - private float mBottomEdgeSwipeOffset; - - private Map mBottomViewIdMap = new HashMap(); - private boolean mBottomViewIdsSet = false; + private float[] mEdgeSwipesOffset = new float[4]; private List mSwipeListeners = new ArrayList(); private List mSwipeDeniers = new ArrayList(); @@ -66,21 +56,16 @@ public class SwipeLayout extends FrameLayout { private DoubleClickListener mDoubleClickListener; private boolean mSwipeEnabled = true; - private boolean mLeftSwipeEnabled = true; - private boolean mRightSwipeEnabled = true; - private boolean mTopSwipeEnabled = true; - private boolean mBottomSwipeEnabled = true; - private boolean mClickToClose = true; + private boolean[] mSwipesEnabled = new boolean[]{true, true, true, true}; + private boolean mClickToClose = false; public static enum DragEdge { Left, - Right, Top, - Bottom; + Right, + Bottom } - ; - public static enum ShowMode { LayDown, PullOut @@ -101,26 +86,24 @@ public SwipeLayout(Context context, AttributeSet attrs, int defStyle) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SwipeLayout); int dragEdgeChoices = a.getInt(R.styleable.SwipeLayout_drag_edge, DRAG_RIGHT); - mLeftEdgeSwipeOffset = a.getDimension(R.styleable.SwipeLayout_leftEdgeSwipeOffset, 0); - mRightEdgeSwipeOffset = a.getDimension(R.styleable.SwipeLayout_rightEdgeSwipeOffset, 0); - mTopEdgeSwipeOffset = a.getDimension(R.styleable.SwipeLayout_topEdgeSwipeOffset, 0); - mBottomEdgeSwipeOffset = a.getDimension(R.styleable.SwipeLayout_bottomEdgeSwipeOffset, 0); + mEdgeSwipesOffset[DragEdge.Left.ordinal()] = a.getDimension(R.styleable.SwipeLayout_leftEdgeSwipeOffset, 0); + mEdgeSwipesOffset[DragEdge.Right.ordinal()] = a.getDimension(R.styleable.SwipeLayout_rightEdgeSwipeOffset, 0); + mEdgeSwipesOffset[DragEdge.Top.ordinal()] = a.getDimension(R.styleable.SwipeLayout_topEdgeSwipeOffset, 0); + mEdgeSwipesOffset[DragEdge.Bottom.ordinal()] = a.getDimension(R.styleable.SwipeLayout_bottomEdgeSwipeOffset, 0); setClickToClose(a.getBoolean(R.styleable.SwipeLayout_clickToClose, mClickToClose)); - mDragEdges = new ArrayList(); if ((dragEdgeChoices & DRAG_LEFT) == DRAG_LEFT) { - mDragEdges.add(DragEdge.Left); - } - if ((dragEdgeChoices & DRAG_RIGHT) == DRAG_RIGHT) { - mDragEdges.add(DragEdge.Right); + mDragEdges.put(DragEdge.Left, null); } if ((dragEdgeChoices & DRAG_TOP) == DRAG_TOP) { - mDragEdges.add(DragEdge.Top); + mDragEdges.put(DragEdge.Top, null); + } + if ((dragEdgeChoices & DRAG_RIGHT) == DRAG_RIGHT) { + mDragEdges.put(DragEdge.Right, null); } if ((dragEdgeChoices & DRAG_BOTTOM) == DRAG_BOTTOM) { - mDragEdges.add(DragEdge.Bottom); + mDragEdges.put(DragEdge.Bottom, null); } - populateIndexes(); int ordinal = a.getInt(R.styleable.SwipeLayout_show_mode, ShowMode.PullOut.ordinal()); mShowMode = ShowMode.values()[ordinal]; a.recycle(); @@ -233,7 +216,7 @@ public void removeAllRevealListeners(int childId) { @Override public int clampViewPositionHorizontal(View child, int left, int dx) { if (child == getSurfaceView()) { - switch (mDragEdges.get(mCurrentDirectionIndex)) { + switch (mCurrentDragEdge) { case Top: case Bottom: return getPaddingLeft(); @@ -248,9 +231,9 @@ public int clampViewPositionHorizontal(View child, int left, int dx) { return getPaddingLeft() - mDragDistance; break; } - } else if (getBottomViews().get(mCurrentDirectionIndex) == child) { + } else if (getCurrentBottomView() == child) { - switch (mDragEdges.get(mCurrentDirectionIndex)) { + switch (mCurrentDragEdge) { case Top: case Bottom: return getPaddingLeft(); @@ -274,7 +257,7 @@ public int clampViewPositionHorizontal(View child, int left, int dx) { @Override public int clampViewPositionVertical(View child, int top, int dy) { if (child == getSurfaceView()) { - switch (mDragEdges.get(mCurrentDirectionIndex)) { + switch (mCurrentDragEdge) { case Left: case Right: return getPaddingTop(); @@ -292,7 +275,9 @@ public int clampViewPositionVertical(View child, int top, int dy) { } } } else { - switch (mDragEdges.get(mCurrentDirectionIndex)) { + View surfaceView = getSurfaceView(); + int surfaceViewTop = surfaceView==null?0:surfaceView.getTop(); + switch (mCurrentDragEdge) { case Left: case Right: return getPaddingTop(); @@ -300,9 +285,9 @@ public int clampViewPositionVertical(View child, int top, int dy) { if (mShowMode == ShowMode.PullOut) { if (top > getPaddingTop()) return getPaddingTop(); } else { - if (getSurfaceView().getTop() + dy < getPaddingTop()) + if (surfaceViewTop + dy < getPaddingTop()) return getPaddingTop(); - if (getSurfaceView().getTop() + dy > getPaddingTop() + mDragDistance) + if (surfaceViewTop + dy > getPaddingTop() + mDragDistance) return getPaddingTop() + mDragDistance; } break; @@ -311,9 +296,9 @@ public int clampViewPositionVertical(View child, int top, int dy) { if (top < getMeasuredHeight() - mDragDistance) return getMeasuredHeight() - mDragDistance; } else { - if (getSurfaceView().getTop() + dy >= getPaddingTop()) + if (surfaceViewTop + dy >= getPaddingTop()) return getPaddingTop(); - if (getSurfaceView().getTop() + dy <= getPaddingTop() - mDragDistance) + if (surfaceViewTop + dy <= getPaddingTop() - mDragDistance) return getPaddingTop() - mDragDistance; } } @@ -344,56 +329,56 @@ public int getViewVerticalDragRange(View child) { @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); - for (SwipeListener l : mSwipeListeners) + for (SwipeListener l : mSwipeListeners){ l.onHandRelease(SwipeLayout.this, xvel, yvel); - if (releasedChild == getSurfaceView()) { - processSurfaceRelease(xvel, yvel, isCloseBeforeDrag); - } else if (getBottomViews().contains(releasedChild)) { - if (getShowMode() == ShowMode.PullOut) { - processBottomPullOutRelease(xvel, yvel); - } else if (getShowMode() == ShowMode.LayDown) { - processBottomLayDownMode(xvel, yvel); - } } + processHandRelease(xvel, yvel, isCloseBeforeDrag); invalidate(); } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { - int evLeft = getSurfaceView().getLeft(), evRight = getSurfaceView().getRight(), evTop = getSurfaceView() - .getTop(), evBottom = getSurfaceView().getBottom(); - if (changedView == getSurfaceView()) { - - if (mShowMode == ShowMode.PullOut) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left - || mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) - getBottomViews().get(mCurrentDirectionIndex).offsetLeftAndRight(dx); - else getBottomViews().get(mCurrentDirectionIndex).offsetTopAndBottom(dy); + View surfaceView = getSurfaceView(); + if(surfaceView==null) return; + View currentBottomView = getCurrentBottomView(); + int evLeft = surfaceView.getLeft(), + evRight = surfaceView.getRight(), + evTop = surfaceView.getTop(), + evBottom = surfaceView.getBottom(); + if (changedView == surfaceView) { + + if (mShowMode == ShowMode.PullOut && currentBottomView!=null) { + if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right){ + currentBottomView.offsetLeftAndRight(dx); + } else { + currentBottomView.offsetTopAndBottom(dy); + } } } else if (getBottomViews().contains(changedView)) { if (mShowMode == ShowMode.PullOut) { - getSurfaceView().offsetLeftAndRight(dx); - getSurfaceView().offsetTopAndBottom(dy); + surfaceView.offsetLeftAndRight(dx); + surfaceView.offsetTopAndBottom(dy); } else { - Rect rect = computeBottomLayDown(mDragEdges.get(mCurrentDirectionIndex)); - getBottomViews().get(mCurrentDirectionIndex).layout(rect.left, rect.top, rect.right, rect.bottom); + Rect rect = computeBottomLayDown(mCurrentDragEdge); + if(currentBottomView!=null){ + currentBottomView.layout(rect.left, rect.top, rect.right, rect.bottom); + } - int newLeft = getSurfaceView().getLeft() + dx, newTop = getSurfaceView().getTop() + dy; + int newLeft = surfaceView.getLeft() + dx, newTop = surfaceView.getTop() + dy; - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left && newLeft < getPaddingLeft()) + if (mCurrentDragEdge == DragEdge.Left && newLeft < getPaddingLeft()) newLeft = getPaddingLeft(); - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right && newLeft > getPaddingLeft()) + else if (mCurrentDragEdge == DragEdge.Right && newLeft > getPaddingLeft()) newLeft = getPaddingLeft(); - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top && newTop < getPaddingTop()) + else if (mCurrentDragEdge == DragEdge.Top && newTop < getPaddingTop()) newTop = getPaddingTop(); - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Bottom && newTop > getPaddingTop()) + else if (mCurrentDragEdge == DragEdge.Bottom && newTop > getPaddingTop()) newTop = getPaddingTop(); - getSurfaceView() - .layout(newLeft, newTop, newLeft + getMeasuredWidth(), newTop + getMeasuredHeight()); + surfaceView.layout(newLeft, newTop, newLeft + getMeasuredWidth(), newTop + getMeasuredHeight()); } } @@ -409,15 +394,6 @@ else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Bottom && newTop > g * the dispatchRevealEvent method may not always get accurate position, it * makes the view may not always get the event when the view is totally * show( fraction = 1), so , we need to calculate every time. - * - * @param child - * @param relativePosition - * @param edge - * @param surfaceLeft - * @param surfaceTop - * @param surfaceRight - * @param surfaceBottom - * @return */ protected boolean isViewTotallyFirstShowed(View child, Rect relativePosition, DragEdge edge, int surfaceLeft, int surfaceTop, int surfaceRight, int surfaceBottom) { @@ -546,7 +522,10 @@ protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, boolean open) } if (status == Status.Open) { - getBottomViews().get(mCurrentDirectionIndex).setEnabled(true); + View currentBottomView = getCurrentBottomView(); + if(currentBottomView!=null){ + currentBottomView.setEnabled(true); + } for (SwipeListener l : mSwipeListeners) { l.onOpen(SwipeLayout.this); } @@ -564,11 +543,15 @@ private void safeBottomView() { if (status == Status.Close) { for (View bottom : bottoms) { - if (bottom.getVisibility() != INVISIBLE) bottom.setVisibility(INVISIBLE); + if (bottom!=null && bottom.getVisibility() != INVISIBLE){ + bottom.setVisibility(INVISIBLE); + } } } else { - if (bottoms.get(mCurrentDirectionIndex).getVisibility() != VISIBLE) - bottoms.get(mCurrentDirectionIndex).setVisibility(VISIBLE); + View currentBottomView = getCurrentBottomView(); + if (currentBottomView!=null && currentBottomView.getVisibility() != VISIBLE){ + currentBottomView.setVisibility(VISIBLE); + } } } @@ -578,13 +561,13 @@ protected void dispatchRevealEvent(final int surfaceLeft, final int surfaceTop, for (Map.Entry> entry : mRevealListeners.entrySet()) { View child = entry.getKey(); Rect rect = getRelativePosition(child); - if (isViewShowing(child, rect, mDragEdges.get(mCurrentDirectionIndex), surfaceLeft, surfaceTop, + if (isViewShowing(child, rect, mCurrentDragEdge, surfaceLeft, surfaceTop, surfaceRight, surfaceBottom)) { mShowEntirely.put(child, false); int distance = 0; float fraction = 0f; if (getShowMode() == ShowMode.LayDown) { - switch (mDragEdges.get(mCurrentDirectionIndex)) { + switch (mCurrentDragEdge) { case Left: distance = rect.left - surfaceLeft; fraction = distance / (float) child.getWidth(); @@ -603,7 +586,7 @@ protected void dispatchRevealEvent(final int surfaceLeft, final int surfaceTop, break; } } else if (getShowMode() == ShowMode.PullOut) { - switch (mDragEdges.get(mCurrentDirectionIndex)) { + switch (mCurrentDragEdge) { case Left: distance = rect.right - getPaddingLeft(); fraction = distance / (float) child.getWidth(); @@ -624,22 +607,22 @@ protected void dispatchRevealEvent(final int surfaceLeft, final int surfaceTop, } for (OnRevealListener l : entry.getValue()) { - l.onReveal(child, mDragEdges.get(mCurrentDirectionIndex), Math.abs(fraction), distance); + l.onReveal(child, mCurrentDragEdge, Math.abs(fraction), distance); if (Math.abs(fraction) == 1) { mShowEntirely.put(child, true); } } } - if (isViewTotallyFirstShowed(child, rect, mDragEdges.get(mCurrentDirectionIndex), surfaceLeft, surfaceTop, + if (isViewTotallyFirstShowed(child, rect, mCurrentDragEdge, surfaceLeft, surfaceTop, surfaceRight, surfaceBottom)) { mShowEntirely.put(child, true); for (OnRevealListener l : entry.getValue()) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left - || mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) - l.onReveal(child, mDragEdges.get(mCurrentDirectionIndex), 1, child.getWidth()); + if (mCurrentDragEdge == DragEdge.Left + || mCurrentDragEdge == DragEdge.Right) + l.onReveal(child, mCurrentDragEdge, 1, child.getWidth()); else - l.onReveal(child, mDragEdges.get(mCurrentDirectionIndex), 1, child.getHeight()); + l.onReveal(child, mCurrentDragEdge, 1, child.getHeight()); } } @@ -672,10 +655,10 @@ public void addOnLayoutListener(OnLayout l) { public void removeOnLayoutListener(OnLayout l) { if (mOnLayoutListeners != null) mOnLayoutListeners.remove(l); } - public void addBottomView(View child, DragEdge dragEdge){ - addBottomView(child, null, dragEdge); + public void addDrag(DragEdge dragEdge, View child){ + addDrag(dragEdge, child, null); } - public void addBottomView(View child, ViewGroup.LayoutParams params, DragEdge dragEdge){ + public void addDrag(DragEdge dragEdge, View child, ViewGroup.LayoutParams params){ if(params==null){ params = generateDefaultLayoutParams(); } @@ -692,7 +675,7 @@ public void addBottomView(View child, ViewGroup.LayoutParams params, DragEdge dr if(params instanceof FrameLayout.LayoutParams){ ((LayoutParams) params).gravity = gravity; } - super.addView(child, 0, params); + addView(child, 0, params); } @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { @@ -704,96 +687,70 @@ public void addView(View child, int index, ViewGroup.LayoutParams params) { } if(gravity>0){ - //declared the layout_gravity, set the child's drag edge - if(child.getId()==View.NO_ID){ - if(Build.VERSION.SDK_INT<17){ - child.setId(child.hashCode()); - }else{ - child.setId(View.generateViewId()); - } - } gravity = GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this)); - if(gravity == Gravity.LEFT){ - mBottomViewIdsSet = true; - if(!mDragEdges.contains(DragEdge.Left)){ - mDragEdges.add(DragEdge.Left); - } - mBottomViewIdMap.put(DragEdge.Left, child.getId()); + if((gravity & Gravity.LEFT) == Gravity.LEFT){ + mDragEdges.put(DragEdge.Left, child); } - if(gravity == Gravity.RIGHT){ - mBottomViewIdsSet = true; - if(!mDragEdges.contains(DragEdge.Right)){ - mDragEdges.add(DragEdge.Right); - } - mBottomViewIdMap.put(DragEdge.Right, child.getId()); + if((gravity & Gravity.RIGHT) == Gravity.RIGHT){ + mDragEdges.put(DragEdge.Right, child); } - if(gravity == Gravity.TOP){ - mBottomViewIdsSet = true; - if(!mDragEdges.contains(DragEdge.Top)){ - mDragEdges.add(DragEdge.Top); - } - mBottomViewIdMap.put(DragEdge.Top, child.getId()); + if((gravity & Gravity.TOP) == Gravity.TOP){ + mDragEdges.put(DragEdge.Top, child); } - if(gravity == Gravity.BOTTOM){ - mBottomViewIdsSet = true; - if(!mDragEdges.contains(DragEdge.Bottom)){ - mDragEdges.add(DragEdge.Bottom); + if((gravity & Gravity.BOTTOM) == Gravity.BOTTOM){ + mDragEdges.put(DragEdge.Bottom, child); + } + }else{ + for(Map.Entry entry : mDragEdges.entrySet()){ + if(entry.getValue() == null){ + //means used the drag_edge attr, the no gravity child should be use set + mDragEdges.put(entry.getKey(), child); + break; } - mBottomViewIdMap.put(DragEdge.Bottom, child.getId()); } - populateIndexes(); + } + if(child==null || child.getParent() == this){ + return; } super.addView(child, index, params); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { - int childCount = getChildCount(); - if (childCount != 1 + mDragEdges.size()) { - throw new IllegalStateException("You need to have one surface view plus one view for each of your drag edges." + - " ChildCount:" + childCount + - ", mDragEdges.size():"+ mDragEdges.size()); - } - - if (mShowMode == ShowMode.PullOut) - layoutPullOut(); - else if (mShowMode == ShowMode.LayDown) layoutLayDown(); - - safeBottomView(); + updateBottomViews(); if (mOnLayoutListeners != null) for (int i = 0; i < mOnLayoutListeners.size(); i++) { mOnLayoutListeners.get(i).onLayout(this); } - } void layoutPullOut() { Rect rect = computeSurfaceLayoutArea(false); - getSurfaceView().layout(rect.left, rect.top, rect.right, rect.bottom); + View surfaceView = getSurfaceView(); + if(surfaceView!=null){ + surfaceView.layout(rect.left, rect.top, rect.right, rect.bottom); + bringChildToFront(surfaceView); + } rect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, rect); - getBottomViews().get(mCurrentDirectionIndex).layout(rect.left, rect.top, rect.right, rect.bottom); - bringChildToFront(getSurfaceView()); + View currentBottomView = getCurrentBottomView(); + if(currentBottomView!=null){ + currentBottomView.layout(rect.left, rect.top, rect.right, rect.bottom); + } } void layoutLayDown() { Rect rect = computeSurfaceLayoutArea(false); - getSurfaceView().layout(rect.left, rect.top, rect.right, rect.bottom); + View surfaceView = getSurfaceView(); + if(surfaceView!=null){ + surfaceView.layout(rect.left, rect.top, rect.right, rect.bottom); + bringChildToFront(surfaceView); + } rect = computeBottomLayoutAreaViaSurface(ShowMode.LayDown, rect); - getBottomViews().get(mCurrentDirectionIndex).layout(rect.left, rect.top, rect.right, rect.bottom); - bringChildToFront(getSurfaceView()); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left - || mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) - mDragDistance = getBottomViews().get(mCurrentDirectionIndex).getMeasuredWidth() - - dp2px(getCurrentOffset()); - else mDragDistance = getBottomViews().get(mCurrentDirectionIndex).getMeasuredHeight() - - dp2px(getCurrentOffset()); + View currentBottomView = getCurrentBottomView(); + if(currentBottomView!=null){ + currentBottomView.layout(rect.left, rect.top, rect.right, rect.bottom); + } } private boolean mIsBeingDragged; @@ -809,28 +766,26 @@ private void checkCanDrag(MotionEvent ev){ float angle = Math.abs(distanceY / distanceX); angle = (float) Math.toDegrees(Math.atan(angle)); if (getOpenStatus() == Status.Close) { - int lastCurrentDirectionIndex = mCurrentDirectionIndex; + DragEdge dragEdge; if (angle < 45) { - if (mLeftIndex != -1 && distanceX > 0 && isLeftSwipeEnabled()) { - mCurrentDirectionIndex = mLeftIndex; - } else if (mRightIndex != -1 && distanceX < 0 && isRightSwipeEnabled()) { - mCurrentDirectionIndex = mRightIndex; - } + if (distanceX > 0 && isLeftSwipeEnabled()) { + dragEdge = DragEdge.Left; + } else if (distanceX < 0 && isRightSwipeEnabled()) { + dragEdge = DragEdge.Right; + }else return; + } else { - if (mTopIndex != -1 && distanceY > 0 && isTopSwipeEnabled()) { - mCurrentDirectionIndex = mTopIndex; - } else if (mBottomIndex != -1 && distanceY < 0 && isBottomSwipeEnabled()) { - mCurrentDirectionIndex = mBottomIndex; - } - } - if (lastCurrentDirectionIndex != mCurrentDirectionIndex) { - updateBottomViews(); + if (distanceY > 0 && isTopSwipeEnabled()) { + dragEdge = DragEdge.Top; + } else if (distanceY < 0 && isBottomSwipeEnabled()) { + dragEdge = DragEdge.Bottom; + }else return; } + setCurrentDragEdge(dragEdge); } - if (!shouldAllowSwipe()) return; boolean doNothing = false; - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) { + if (mCurrentDragEdge == DragEdge.Right) { boolean suitable = (status == Status.Open && distanceX > mTouchSlop) || (status == Status.Close && distanceX < -mTouchSlop); suitable = suitable || (status == Status.Middle); @@ -840,7 +795,7 @@ private void checkCanDrag(MotionEvent ev){ } } - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) { + if (mCurrentDragEdge == DragEdge.Left) { boolean suitable = (status == Status.Open && distanceX < -mTouchSlop) || (status == Status.Close && distanceX > mTouchSlop); suitable = suitable || status == Status.Middle; @@ -850,7 +805,7 @@ private void checkCanDrag(MotionEvent ev){ } } - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) { + if (mCurrentDragEdge == DragEdge.Top) { boolean suitable = (status == Status.Open && distanceY < -mTouchSlop) || (status == Status.Close && distanceY > mTouchSlop); suitable = suitable || status == Status.Middle; @@ -860,7 +815,7 @@ private void checkCanDrag(MotionEvent ev){ } } - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Bottom) { + if (mCurrentDragEdge == DragEdge.Bottom) { boolean suitable = (status == Status.Open && distanceY > mTouchSlop) || (status == Status.Close && distanceY < -mTouchSlop); suitable = suitable || status == Status.Middle; @@ -876,12 +831,8 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { if (!isSwipeEnabled()) { return false; } - if(mClickToClose && getOpenStatus() == Status.Open && getSurfaceView()!=null){ - Rect rect = new Rect(); - getSurfaceView().getHitRect(rect); - if(rect.contains((int)ev.getX(), (int)ev.getY())){ - return true; - } + if(mClickToClose && getOpenStatus() == Status.Open && isTouchOnSurface(ev)){ + return true; } for (SwipeDenier denier : mSwipeDeniers) { if (denier != null && denier.shouldDenySwipe(ev)) { @@ -929,14 +880,6 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { private float sX = -1, sY = -1; - private boolean shouldAllowSwipe() { - if (mCurrentDirectionIndex == mLeftIndex && !mLeftSwipeEnabled) return false; - if (mCurrentDirectionIndex == mRightIndex && !mRightSwipeEnabled) return false; - if (mCurrentDirectionIndex == mTopIndex && !mTopSwipeEnabled) return false; - if (mCurrentDirectionIndex == mBottomIndex && !mBottomSwipeEnabled) return false; - return true; - } - @Override public boolean onTouchEvent(MotionEvent event) { if (!isSwipeEnabled()) return super.onTouchEvent(event); @@ -989,35 +932,43 @@ public boolean isSwipeEnabled() { } public boolean isLeftSwipeEnabled() { - return mLeftSwipeEnabled; + View bottomView = mDragEdges.get(DragEdge.Left); + return bottomView != null && bottomView.getParent() == this + && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Left.ordinal()]; } public void setLeftSwipeEnabled(boolean leftSwipeEnabled) { - this.mLeftSwipeEnabled = leftSwipeEnabled; + this.mSwipesEnabled[DragEdge.Left.ordinal()] = leftSwipeEnabled; } public boolean isRightSwipeEnabled() { - return mRightSwipeEnabled; + View bottomView = mDragEdges.get(DragEdge.Right); + return bottomView!=null && bottomView.getParent()==this + && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Right.ordinal()]; } public void setRightSwipeEnabled(boolean rightSwipeEnabled) { - this.mRightSwipeEnabled = rightSwipeEnabled; + this.mSwipesEnabled[DragEdge.Right.ordinal()] = rightSwipeEnabled; } public boolean isTopSwipeEnabled() { - return mTopSwipeEnabled; + View bottomView = mDragEdges.get(DragEdge.Top); + return bottomView!=null && bottomView.getParent()==this + && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Top.ordinal()]; } public void setTopSwipeEnabled(boolean topSwipeEnabled) { - this.mTopSwipeEnabled = topSwipeEnabled; + this.mSwipesEnabled[DragEdge.Top.ordinal()] = topSwipeEnabled; } public boolean isBottomSwipeEnabled() { - return mBottomSwipeEnabled; + View bottomView = mDragEdges.get(DragEdge.Bottom); + return bottomView!=null && bottomView.getParent()==this + && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Bottom.ordinal()]; } public void setBottomSwipeEnabled(boolean bottomSwipeEnabled) { - this.mBottomSwipeEnabled = bottomSwipeEnabled; + this.mSwipesEnabled[DragEdge.Bottom.ordinal()] = bottomSwipeEnabled; } private boolean insideAdapterView() { return getAdapterView() != null; @@ -1107,13 +1058,24 @@ public void setOnLongClickListener(OnLongClickListener l) { longClickListener = l; } - + private Rect hitSurfaceRect; + private boolean isTouchOnSurface(MotionEvent ev){ + View surfaceView = getSurfaceView(); + if(surfaceView==null){ + return false; + } + if(hitSurfaceRect == null){ + hitSurfaceRect = new Rect(); + } + surfaceView.getHitRect(hitSurfaceRect); + return hitSurfaceRect.contains((int) ev.getX(), (int) ev.getY()); + } private GestureDetector gestureDetector = new GestureDetector(getContext(), new SwipeDetector()); class SwipeDetector extends GestureDetector.SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { - if(mClickToClose){ + if(mClickToClose && isTouchOnSurface(e)){ close(); } return super.onSingleTapUp(e); @@ -1122,10 +1084,10 @@ public boolean onSingleTapUp(MotionEvent e) { public boolean onDoubleTap(MotionEvent e) { if (mDoubleClickListener != null) { View target; - View bottom = getBottomViews().get(mCurrentDirectionIndex); + View bottom = getCurrentBottomView(); View surface = getSurfaceView(); - if (e.getX() > bottom.getLeft() && e.getX() < bottom.getRight() && e.getY() > bottom.getTop() - && e.getY() < bottom.getBottom()) { + if (bottom!=null && e.getX() > bottom.getLeft() && e.getX() < bottom.getRight() + && e.getY() > bottom.getTop() && e.getY() < bottom.getBottom()) { target = bottom; } else { target = surface; @@ -1136,23 +1098,14 @@ public boolean onDoubleTap(MotionEvent e) { } } - public void setDragEdge(DragEdge dragEdge) { - mDragEdges = new ArrayList(); - mDragEdges.add(dragEdge); - mCurrentDirectionIndex = 0; - populateIndexes(); - requestLayout(); - updateBottomViews(); - } - /** * set the drag distance, it will force set the bottom view's width or * height via this value. * - * @param max + * @param max max distance in dp unit */ public void setDragDistance(int max) { - if (max < 0) throw new IllegalArgumentException("Drag distance can not be < 0"); + if (max < 0) max = 0; mDragDistance = dp2px(max); requestLayout(); } @@ -1170,7 +1123,7 @@ public void setShowMode(ShowMode mode) { } public DragEdge getDragEdge() { - return mDragEdges.get(mCurrentDirectionIndex); + return mCurrentDragEdge; } public int getDragDistance() { @@ -1181,76 +1134,30 @@ public ShowMode getShowMode() { return mShowMode; } + /**return null if there is no surface view(no children) */ public View getSurfaceView() { - return (View) getChildAt(getChildCount() - 1); + if(getChildCount()==0) return null; + return getChildAt(getChildCount() - 1); } + /**return null if there is no bottom view */ + @Nullable + public View getCurrentBottomView(){ + List bottoms = getBottomViews(); + if(mCurrentDragEdge.ordinal() < bottoms.size()){ + return bottoms.get(mCurrentDragEdge.ordinal()); + } + return null; + } /** - * @return all bottomViews. + * @return all bottomViews: left, top, right, bottom (may null if the edge is not set) */ public List getBottomViews() { - List lvg = new ArrayList(); - // If the user has provided a map for views to - if (mBottomViewIdsSet) { - lvg.addAll(Arrays.asList(new View[mDragEdges.size()])); - - if (mDragEdges.contains(DragEdge.Left)) { - lvg.set(mLeftIndex, ((View) findViewById(mBottomViewIdMap.get(DragEdge.Left)))); - } - if (mDragEdges.contains(DragEdge.Top)) { - lvg.set(mTopIndex, ((View) findViewById(mBottomViewIdMap.get(DragEdge.Top)))); - } - if (mDragEdges.contains(DragEdge.Right)) { - lvg.set(mRightIndex, ((View) findViewById(mBottomViewIdMap.get(DragEdge.Right)))); - } - if (mDragEdges.contains(DragEdge.Bottom)) { - lvg.set(mBottomIndex, ((View) findViewById(mBottomViewIdMap.get(DragEdge.Bottom)))); - } - } - // Default behaviour is to simply use the first n-1 children in the order they're listed in the layout - // and return them in - else { - for (int i = 0; i < (getChildCount() - 1); i++) { - lvg.add((View) getChildAt(i)); - } - } - return lvg; - } - - // Pass the id of the view if set, otherwise pass -1 - public void setBottomViewIds(int left, int right, int top, int bottom) { - if (mDragEdges.contains(DragEdge.Left)) { - if (left == EMPTY_LAYOUT) { - mBottomViewIdsSet = false; - } else { - mBottomViewIdMap.put(DragEdge.Left, left); - mBottomViewIdsSet = true; - } - } - if (mDragEdges.contains(DragEdge.Right)) { - if (right == EMPTY_LAYOUT) { - mBottomViewIdsSet = false; - } else { - mBottomViewIdMap.put(DragEdge.Right, right); - mBottomViewIdsSet = true; - } - } - if (mDragEdges.contains(DragEdge.Top)) { - if (top == EMPTY_LAYOUT) { - mBottomViewIdsSet = false; - } else { - mBottomViewIdMap.put(DragEdge.Top, top); - mBottomViewIdsSet = true; - } - } - if (mDragEdges.contains(DragEdge.Bottom)) { - if (bottom == EMPTY_LAYOUT) { - mBottomViewIdsSet = false; - } else { - mBottomViewIdMap.put(DragEdge.Bottom, bottom); - mBottomViewIdsSet = true; - } + ArrayList bottoms = new ArrayList(); + for(DragEdge dragEdge : DragEdge.values()){ + bottoms.add(mDragEdges.get(dragEdge)); } + return bottoms; } public enum Status { @@ -1266,8 +1173,12 @@ public enum Status { * Middle. */ public Status getOpenStatus() { - int surfaceLeft = getSurfaceView().getLeft(); - int surfaceTop = getSurfaceView().getTop(); + View surfaceView = getSurfaceView(); + if(surfaceView==null){ + return Status.Close; + } + int surfaceLeft = surfaceView.getLeft(); + int surfaceTop = surfaceView.getTop(); if (surfaceLeft == getPaddingLeft() && surfaceTop == getPaddingTop()) return Status.Close; if (surfaceLeft == (getPaddingLeft() - mDragDistance) || surfaceLeft == (getPaddingLeft() + mDragDistance) @@ -1285,19 +1196,19 @@ public Status getOpenStatus() { * @param yvel yVelocity * @param isCloseBeforeDragged the open state before drag */ - private void processSurfaceRelease(float xvel, float yvel, boolean isCloseBeforeDragged) { + protected void processHandRelease(float xvel, float yvel, boolean isCloseBeforeDragged) { float minVelocity = mDragHelper.getMinVelocity(); View surfaceView = getSurfaceView(); DragEdge currentDragEdge = null; try { - currentDragEdge = mDragEdges.get(mCurrentDirectionIndex); + currentDragEdge = mCurrentDragEdge; } catch (Exception e) { e.printStackTrace(); } if(currentDragEdge == null || surfaceView == null){ return; } - float willOpenPercent = (isCloseBeforeDragged ? .3f : .7f); + float willOpenPercent = (isCloseBeforeDragged ? .25f : .75f); if(currentDragEdge == DragEdge.Left){ if(xvel > minVelocity) open(); else if(xvel < -minVelocity) close(); @@ -1333,67 +1244,6 @@ private void processSurfaceRelease(float xvel, float yvel, boolean isCloseBefore } } - /** - * process bottom (PullOut mode) hand release event. - * - * @param xvel - * @param yvel - */ - private void processBottomPullOutRelease(float xvel, float yvel) { - - if (xvel == 0 && getOpenStatus() == Status.Middle) close(); - - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left - || mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) { - if (xvel > 0) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) - open(); - else close(); - } - if (xvel < 0) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) - close(); - else open(); - } - } else { - if (yvel > 0) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) - open(); - else close(); - } - - if (yvel < 0) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) - close(); - else open(); - } - } - } - - /** - * process bottom (LayDown mode) hand release event. - * - * @param xvel - * @param yvel - */ - private void processBottomLayDownMode(float xvel, float yvel) { - - if (xvel == 0 && getOpenStatus() == Status.Middle) close(); - - int l = getPaddingLeft(), t = getPaddingTop(); - - if (xvel < 0 && mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) - l -= mDragDistance; - if (xvel > 0 && mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) l += mDragDistance; - - if (yvel > 0 && mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) t += mDragDistance; - if (yvel < 0 && mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Bottom) - t -= mDragDistance; - - mDragHelper.smoothSlideViewTo(getSurfaceView(), l, t); - invalidate(); - } - /** * smoothly open surface. */ @@ -1406,18 +1256,23 @@ public void open(boolean smooth) { } public void open(boolean smooth, boolean notify) { - View surface = getSurfaceView(), bottom = getBottomViews().get(mCurrentDirectionIndex); + View surface = getSurfaceView(), bottom = getCurrentBottomView(); + if(surface == null){ + return; + } int dx, dy; Rect rect = computeSurfaceLayoutArea(true); if (smooth) { - mDragHelper.smoothSlideViewTo(getSurfaceView(), rect.left, rect.top); + mDragHelper.smoothSlideViewTo(surface, rect.left, rect.top); } else { dx = rect.left - surface.getLeft(); dy = rect.top - surface.getTop(); surface.layout(rect.left, rect.top, rect.right, rect.bottom); if (getShowMode() == ShowMode.PullOut) { Rect bRect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, rect); - bottom.layout(bRect.left, bRect.top, bRect.right, bRect.bottom); + if(bottom!=null){ + bottom.layout(bRect.left, bRect.top, bRect.right, bRect.bottom); + } } if (notify) { dispatchRevealEvent(rect.left, rect.top, rect.right, rect.bottom); @@ -1430,44 +1285,17 @@ public void open(boolean smooth, boolean notify) { } public void open(DragEdge edge) { - switch (edge) { - case Left: - mCurrentDirectionIndex = mLeftIndex; - case Right: - mCurrentDirectionIndex = mRightIndex; - case Top: - mCurrentDirectionIndex = mTopIndex; - case Bottom: - mCurrentDirectionIndex = mBottomIndex; - } + setCurrentDragEdge(edge); open(true, true); } public void open(boolean smooth, DragEdge edge) { - switch (edge) { - case Left: - mCurrentDirectionIndex = mLeftIndex; - case Right: - mCurrentDirectionIndex = mRightIndex; - case Top: - mCurrentDirectionIndex = mTopIndex; - case Bottom: - mCurrentDirectionIndex = mBottomIndex; - } + setCurrentDragEdge(edge); open(smooth, true); } public void open(boolean smooth, boolean notify, DragEdge edge) { - switch (edge) { - case Left: - mCurrentDirectionIndex = mLeftIndex; - case Right: - mCurrentDirectionIndex = mRightIndex; - case Top: - mCurrentDirectionIndex = mTopIndex; - case Bottom: - mCurrentDirectionIndex = mBottomIndex; - } + setCurrentDragEdge(edge); open(smooth, notify); } @@ -1490,6 +1318,9 @@ public void close(boolean smooth) { */ public void close(boolean smooth, boolean notify) { View surface = getSurfaceView(); + if(surface==null){ + return; + } int dx, dy; if (smooth) mDragHelper.smoothSlideViewTo(getSurfaceView(), getPaddingLeft(), getPaddingTop()); @@ -1518,20 +1349,19 @@ public void toggle(boolean smooth) { else if (getOpenStatus() == Status.Close) open(smooth); } + /** * a helper function to compute the Rect area that surface will hold in. - * * @param open open status or close status. - * @return */ private Rect computeSurfaceLayoutArea(boolean open) { int l = getPaddingLeft(), t = getPaddingTop(); if (open) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) + if (mCurrentDragEdge == DragEdge.Left) l = getPaddingLeft() + mDragDistance; - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) + else if (mCurrentDragEdge == DragEdge.Right) l = getPaddingLeft() - mDragDistance; - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) + else if (mCurrentDragEdge == DragEdge.Top) t = getPaddingTop() + mDragDistance; else t = getPaddingTop() - mDragDistance; } @@ -1540,30 +1370,31 @@ else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) private Rect computeBottomLayoutAreaViaSurface(ShowMode mode, Rect surfaceArea) { Rect rect = surfaceArea; + View bottomView = getCurrentBottomView(); int bl = rect.left, bt = rect.top, br = rect.right, bb = rect.bottom; if (mode == ShowMode.PullOut) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) + if (mCurrentDragEdge == DragEdge.Left) bl = rect.left - mDragDistance; - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) + else if (mCurrentDragEdge == DragEdge.Right) bl = rect.right; - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) + else if (mCurrentDragEdge == DragEdge.Top) bt = rect.top - mDragDistance; else bt = rect.bottom; - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left || mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) { + if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) { bb = rect.bottom; - br = bl + getBottomViews().get(mCurrentDirectionIndex).getMeasuredWidth(); + br = bl + (bottomView == null? 0 :bottomView.getMeasuredWidth()); } else { - bb = bt + getBottomViews().get(mCurrentDirectionIndex).getMeasuredHeight(); + bb = bt + (bottomView == null? 0 :bottomView.getMeasuredHeight()); br = rect.right; } } else if (mode == ShowMode.LayDown) { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) + if (mCurrentDragEdge == DragEdge.Left) br = bl + mDragDistance; - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) + else if (mCurrentDragEdge == DragEdge.Right) bl = br - mDragDistance; - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) + else if (mCurrentDragEdge == DragEdge.Top) bb = bt + mDragDistance; else bt = bb - mDragDistance; @@ -1602,56 +1433,90 @@ private int dp2px(float dp) { return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f); } - public List getDragEdges() { + + /**Deprecated, use {@link #addDrag(DragEdge, View)} */ + @Deprecated + public void setDragEdge(DragEdge dragEdge) { + if(getChildCount() >= 2){ + mDragEdges.put(dragEdge, getChildAt(getChildCount()-2)); + } + setCurrentDragEdge(dragEdge); + } + + protected void onViewRemoved(View child) { + for(Map.Entry entry : new HashMap(mDragEdges).entrySet()){ + if(entry.getValue() == child){ + mDragEdges.remove(entry.getKey()); + } + } + } + public Map getDragEdgeMap(){ return mDragEdges; } - public void setDragEdges(List mDragEdges) { - this.mDragEdges = mDragEdges; - mCurrentDirectionIndex = 0; - populateIndexes(); - updateBottomViews(); + /**Deprecated, use {@link #getDragEdgeMap()} */ + @Deprecated + public List getDragEdges() { + return new ArrayList(mDragEdges.keySet()); } - public void setDragEdges(DragEdge... mDragEdges) { - this.mDragEdges = new ArrayList(); - for (DragEdge e : mDragEdges) { - this.mDragEdges.add(e); + /**Deprecated, use {@link #addDrag(DragEdge, View)} */ + @Deprecated + public void setDragEdges(List dragEdges) { + for (int i = 0, size = Math.min(dragEdges.size(), getChildCount() - 1); i < size; i++) { + DragEdge dragEdge = dragEdges.get(i); + mDragEdges.put(dragEdge, getChildAt(i)); + } + if(dragEdges.size()==0 || dragEdges.contains(DefaultDragEdge)){ + setCurrentDragEdge(DefaultDragEdge); + }else{ + setCurrentDragEdge(dragEdges.get(0)); } - mCurrentDirectionIndex = 0; - populateIndexes(); - updateBottomViews(); } - private void populateIndexes() { - mLeftIndex = this.mDragEdges.indexOf(DragEdge.Left); - mRightIndex = this.mDragEdges.indexOf(DragEdge.Right); - mTopIndex = this.mDragEdges.indexOf(DragEdge.Top); - mBottomIndex = this.mDragEdges.indexOf(DragEdge.Bottom); + /**Deprecated, use {@link #addDrag(DragEdge, View)} */ + @Deprecated + public void setDragEdges(DragEdge... mDragEdges) { + setDragEdges(Arrays.asList(mDragEdges)); + } + /** + * Deprecated, use {@link #addDrag(DragEdge, View)} + * When using multiple drag edges it's a good idea to pass the ids of the views that + * you're using for the left, right, top bottom views (-1 if you're not using a particular view) + */ + @Deprecated + public void setBottomViewIds(int leftId, int rightId, int topId, int bottomId) { + addDrag(DragEdge.Left, findViewById(leftId)); + addDrag(DragEdge.Right, findViewById(rightId)); + addDrag(DragEdge.Top, findViewById(topId)); + addDrag(DragEdge.Bottom, findViewById(bottomId)); } private float getCurrentOffset() { - if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Left) return mLeftEdgeSwipeOffset; - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Right) - return mRightEdgeSwipeOffset; - else if (mDragEdges.get(mCurrentDirectionIndex) == DragEdge.Top) return mTopEdgeSwipeOffset; - else return mBottomEdgeSwipeOffset; + if(mCurrentDragEdge==null) return 0; + return mEdgeSwipesOffset[mCurrentDragEdge.ordinal()]; + } + + private void setCurrentDragEdge(DragEdge dragEdge){ + if(mCurrentDragEdge != dragEdge){ + mCurrentDragEdge = dragEdge; + updateBottomViews(); + } } private void updateBottomViews() { -// removeAllViews(); -// addView(getBottomViews().get(mCurrentDirectionIndex)); -// addView(getSurfaceView()); -// getBottomViews().get(mCurrentDirectionIndex).bringToFront(); -// getSurfaceView().bringToFront(); + View currentBottomView = getCurrentBottomView(); + if(currentBottomView!=null){ + if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) { + mDragDistance = currentBottomView.getMeasuredWidth() - dp2px(getCurrentOffset()); + } + else mDragDistance = currentBottomView.getMeasuredHeight() - dp2px(getCurrentOffset()); + } + if (mShowMode == ShowMode.PullOut) layoutPullOut(); else if (mShowMode == ShowMode.LayDown) layoutLayDown(); safeBottomView(); - - if (mOnLayoutListeners != null) for (int i = 0; i < mOnLayoutListeners.size(); i++) { - mOnLayoutListeners.get(i).onLayout(this); - } } } From 0e0390c1ff8933577ad424dd4b4fc3d9675504d9 Mon Sep 17 00:00:00 2001 From: linfaxin <673636904@qq.com> Date: Wed, 8 Apr 2015 10:21:36 +0800 Subject: [PATCH 8/8] remove a useless try catch --- library/src/main/java/com/daimajia/swipe/SwipeLayout.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java index a6217070..a451bf98 100644 --- a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java +++ b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java @@ -1199,12 +1199,7 @@ public Status getOpenStatus() { protected void processHandRelease(float xvel, float yvel, boolean isCloseBeforeDragged) { float minVelocity = mDragHelper.getMinVelocity(); View surfaceView = getSurfaceView(); - DragEdge currentDragEdge = null; - try { - currentDragEdge = mCurrentDragEdge; - } catch (Exception e) { - e.printStackTrace(); - } + DragEdge currentDragEdge = mCurrentDragEdge; if(currentDragEdge == null || surfaceView == null){ return; }