SwipeableListView.java revision 4485ade4b8c949a222f8b98650a9a48d074dc87e
1f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira/* 2f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Copyright (C) 2012 Google Inc. 3f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Licensed to The Android Open Source Project. 4f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * 5f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 6f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * you may not use this file except in compliance with the License. 7f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * You may obtain a copy of the License at 8f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * 9f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 10f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * 11f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Unless required by applicable law or agreed to in writing, software 12f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 13f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * See the License for the specific language governing permissions and 15f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * limitations under the License. 16f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira */ 17f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 18f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereirapackage com.android.mail.ui; 19f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 20b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huangimport android.content.ContentValues; 21f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.content.Context; 22f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereiraimport android.content.res.Configuration; 237517e3b61b898a57f19be0671f70d58a82224643Andy Huangimport android.graphics.Rect; 248db7e407109532557718c6b8064792f2df7a073dMindy Pereiraimport android.net.Uri; 25f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.util.AttributeSet; 2669b440141f402669fe44dfd8924a94fd22ebccf7mindypimport android.widget.AbsListView; 2769b440141f402669fe44dfd8924a94fd22ebccf7mindypimport android.widget.AbsListView.OnScrollListener; 28f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.MotionEvent; 29f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.View; 30f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereiraimport android.view.ViewConfiguration; 31f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.widget.ListView; 32f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 33f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.R; 34bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport com.android.mail.browse.ConversationCursor; 35f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.browse.ConversationItemView; 361ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereiraimport com.android.mail.browse.SwipeableConversationItemView; 37f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.providers.Conversation; 3806642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereiraimport com.android.mail.providers.Folder; 39b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huangimport com.android.mail.providers.FolderList; 40f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.ui.SwipeHelper.Callback; 41b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 42b0219eb7b77212902a38821c050922ac73a68250Mindy Pereiraimport com.android.mail.utils.LogUtils; 437517e3b61b898a57f19be0671f70d58a82224643Andy Huangimport com.android.mail.utils.Utils; 44f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 45866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereiraimport java.util.ArrayList; 46f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport java.util.Collection; 478db7e407109532557718c6b8064792f2df7a073dMindy Pereiraimport java.util.HashMap; 48f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 4969b440141f402669fe44dfd8924a94fd22ebccf7mindyppublic class SwipeableListView extends ListView implements Callback, OnScrollListener { 50f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private SwipeHelper mSwipeHelper; 51ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira private boolean mEnableSwipe = false; 52489dd22c64c718b6953b4bd6acef925e82c53c87Andy Huang 53b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook public static final String LOG_TAG = LogTag.getLogTag(); 54f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 55866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira private ConversationSelectionSet mConvSelectionSet; 566c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira private int mSwipeAction; 5706642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira private Folder mFolder; 589365a826b46b0e274df88e92534f7d871eef2aa2mindyp private ListItemSwipedListener mSwipedListener; 5969b440141f402669fe44dfd8924a94fd22ebccf7mindyp private boolean mScrolling; 60866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 614485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal // Instantiated through view inflation 624485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal @SuppressWarnings("unused") 63f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public SwipeableListView(Context context) { 64f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira this(context, null); 65f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 66f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 67f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public SwipeableListView(Context context, AttributeSet attrs) { 68f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira this(context, attrs, -1); 69f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 70f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 71f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public SwipeableListView(Context context, AttributeSet attrs, int defStyle) { 72f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira super(context, attrs, defStyle); 73f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira float densityScale = getResources().getDisplayMetrics().density; 74f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira float pagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop(); 756f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, densityScale, 766f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira pagingTouchSlop); 7769b440141f402669fe44dfd8924a94fd22ebccf7mindyp setOnScrollListener(this); 78f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 79f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 80f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira @Override 81f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira protected void onConfigurationChanged(Configuration newConfig) { 82f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira super.onConfigurationChanged(newConfig); 83f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira float densityScale = getResources().getDisplayMetrics().density; 84f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira mSwipeHelper.setDensityScale(densityScale); 85f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop(); 86f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira mSwipeHelper.setPagingTouchSlop(pagingTouchSlop); 87f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira } 88f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira 897517e3b61b898a57f19be0671f70d58a82224643Andy Huang @Override 907517e3b61b898a57f19be0671f70d58a82224643Andy Huang protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 91bc88f16af48d9538b79cbeab88cd275cb769a67dVikram Aggarwal LogUtils.d(Utils.VIEW_DEBUGGING_TAG, 927517e3b61b898a57f19be0671f70d58a82224643Andy Huang "START CLF-ListView.onFocusChanged layoutRequested=%s root.layoutRequested=%s", 937517e3b61b898a57f19be0671f70d58a82224643Andy Huang isLayoutRequested(), getRootView().isLayoutRequested()); 947517e3b61b898a57f19be0671f70d58a82224643Andy Huang super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); 95bc88f16af48d9538b79cbeab88cd275cb769a67dVikram Aggarwal LogUtils.d(Utils.VIEW_DEBUGGING_TAG, new Error(), 967517e3b61b898a57f19be0671f70d58a82224643Andy Huang "FINISH CLF-ListView.onFocusChanged layoutRequested=%s root.layoutRequested=%s", 977517e3b61b898a57f19be0671f70d58a82224643Andy Huang isLayoutRequested(), getRootView().isLayoutRequested()); 987517e3b61b898a57f19be0671f70d58a82224643Andy Huang } 997517e3b61b898a57f19be0671f70d58a82224643Andy Huang 100ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira /** 101ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira * Enable swipe gestures. 102ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira */ 103ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira public void enableSwipe(boolean enable) { 104ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira mEnableSwipe = enable; 105ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira } 106ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira 1076c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira public void setSwipeAction(int action) { 1086c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira mSwipeAction = action; 109f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 110f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 1119365a826b46b0e274df88e92534f7d871eef2aa2mindyp public void setSwipedListener(ListItemSwipedListener listener) { 1129365a826b46b0e274df88e92534f7d871eef2aa2mindyp mSwipedListener = listener; 1139365a826b46b0e274df88e92534f7d871eef2aa2mindyp } 1149365a826b46b0e274df88e92534f7d871eef2aa2mindyp 115de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira public int getSwipeAction() { 116de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira return mSwipeAction; 117de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira } 118de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira 119866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira public void setSelectionSet(ConversationSelectionSet set) { 120866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira mConvSelectionSet = set; 121866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 122866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 12306642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira public void setCurrentFolder(Folder folder) { 12406642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira mFolder = folder; 12506642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira } 12606642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira 127866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira @Override 128866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira public ConversationSelectionSet getSelectionSet() { 129866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira return mConvSelectionSet; 130866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 131866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 132f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira @Override 133f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public boolean onInterceptTouchEvent(MotionEvent ev) { 13469b440141f402669fe44dfd8924a94fd22ebccf7mindyp if (mScrolling || !mEnableSwipe) { 13519bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira return super.onInterceptTouchEvent(ev); 13669b440141f402669fe44dfd8924a94fd22ebccf7mindyp } else { 13769b440141f402669fe44dfd8924a94fd22ebccf7mindyp return mSwipeHelper.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev); 13819bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira } 139f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 140f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 141f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira @Override 142f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public boolean onTouchEvent(MotionEvent ev) { 143ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira if (mEnableSwipe) { 14419bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev); 14519bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira } else { 14619bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira return super.onTouchEvent(ev); 14719bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira } 148f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 149f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 150f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira @Override 151f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public View getChildAtPosition(MotionEvent ev) { 152f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira // find the view under the pointer, accounting for GONE views 153f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira final int count = getChildCount(); 154f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira int touchY = (int) ev.getY(); 155f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira int childIdx = 0; 156f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira View slidingChild; 157f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira for (; childIdx < count; childIdx++) { 158f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira slidingChild = getChildAt(childIdx); 159f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (slidingChild.getVisibility() == GONE) { 160f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira continue; 161f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 162866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira if (touchY >= slidingChild.getTop() && touchY <= slidingChild.getBottom()) { 1631ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira if (slidingChild instanceof SwipeableConversationItemView) { 1641ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira return ((SwipeableConversationItemView) slidingChild).getSwipeableItemView(); 1651ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira } 166866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira return slidingChild; 167866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 168f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 169f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira return null; 170f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 171f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 172f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira @Override 1736c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira public boolean canChildBeDismissed(SwipeableItemView v) { 174a538984fcc19e7624f2650b119ede39bf1f35846mindyp return v.canChildBeDismissed(); 175f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 176f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 177f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira @Override 1786c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira public void onChildDismissed(SwipeableItemView v) { 1790760bfbf8259e4161ce7737fc980b6b9297885ccmindyp if (v != null) { 1800760bfbf8259e4161ce7737fc980b6b9297885ccmindyp v.dismiss(); 1810760bfbf8259e4161ce7737fc980b6b9297885ccmindyp } 182f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 183f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 1848937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira // Call this whenever a new action is taken; this forces a commit of any 1858937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira // existing destructive actions. 186c6adce3cf6887c4c6dd5005724565702751843d0mindyp public void commitDestructiveActions(boolean animate) { 1870fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira final AnimatedAdapter adapter = getAnimatedAdapter(); 1888937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira if (adapter != null) { 189c6adce3cf6887c4c6dd5005724565702751843d0mindyp adapter.commitLeaveBehindItems(animate); 1908937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira } 1918937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira } 1928937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira 193a538984fcc19e7624f2650b119ede39bf1f35846mindyp public void dismissChild(final ConversationItemView target) { 194d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira final ToastBarOperation undoOp; 195866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 1966a3d5ce0b18f58fcfa1af0315dc8ddc7331c2c5fScott Kennedy undoOp = new ToastBarOperation(1, mSwipeAction, ToastBarOperation.UNDO, false /* batch */, 1976a3d5ce0b18f58fcfa1af0315dc8ddc7331c2c5fScott Kennedy mFolder); 1986c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira Conversation conv = target.getConversation(); 19913e6243683cc8cb998a43d06f25d6ff1aab9d93bMindy Pereira target.getConversation().position = findConversation(target, conv); 2000fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira final AnimatedAdapter adapter = getAnimatedAdapter(); 20109f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira if (adapter == null) { 20209f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira return; 20309f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira } 2046c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira adapter.setupLeaveBehind(conv, undoOp, conv.position); 20500ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira ConversationCursor cc = (ConversationCursor) adapter.getCursor(); 2069365a826b46b0e274df88e92534f7d871eef2aa2mindyp Collection<Conversation> convList = Conversation.listOf(conv); 2075cc0ab20009100e3ef259fe3d2e3ddc357f79285mindyp ArrayList<Uri> folderUris; 2085cc0ab20009100e3ef259fe3d2e3ddc357f79285mindyp ArrayList<Boolean> adds; 2096c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira switch (mSwipeAction) { 21001f30509c4c8ad0d13b7635447b7f023c7a0cab7Mindy Pereira case R.id.remove_folder: 2118db7e407109532557718c6b8064792f2df7a073dMindy Pereira FolderOperation folderOp = new FolderOperation(mFolder, false); 2128db7e407109532557718c6b8064792f2df7a073dMindy Pereira HashMap<Uri, Folder> targetFolders = Folder 21368f83843e821d9627a53f68244dbc4cb26662edcMindy Pereira .hashMapForFolders(conv.getRawFolders()); 2148db7e407109532557718c6b8064792f2df7a073dMindy Pereira targetFolders.remove(folderOp.mFolder.uri); 215b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang final FolderList folders = FolderList.copyOf(targetFolders.values()); 216b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang conv.setRawFolders(folders); 217b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang final ContentValues values = new ContentValues(); 2185cc0ab20009100e3ef259fe3d2e3ddc357f79285mindyp folderUris = new ArrayList<Uri>(); 2195cc0ab20009100e3ef259fe3d2e3ddc357f79285mindyp folderUris.add(mFolder.uri); 2205cc0ab20009100e3ef259fe3d2e3ddc357f79285mindyp adds = new ArrayList<Boolean>(); 2215cc0ab20009100e3ef259fe3d2e3ddc357f79285mindyp adds.add(Boolean.FALSE); 2229e2d407fdafeb874e640eb84017feaf784309075Scott Kennedy ConversationCursor.addFolderUpdates(folderUris, adds, values); 2239e2d407fdafeb874e640eb84017feaf784309075Scott Kennedy ConversationCursor.addTargetFolders(targetFolders.values(), values); 2249e2d407fdafeb874e640eb84017feaf784309075Scott Kennedy cc.mostlyDestructiveUpdate(Conversation.listOf(conv), values); 22506642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira break; 2266c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira case R.id.archive: 2279e2d407fdafeb874e640eb84017feaf784309075Scott Kennedy cc.mostlyArchive(convList); 2286c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira break; 2296c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira case R.id.delete: 2309e2d407fdafeb874e640eb84017feaf784309075Scott Kennedy cc.mostlyDelete(convList); 2316c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira break; 2326c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 2339365a826b46b0e274df88e92534f7d871eef2aa2mindyp if (mSwipedListener != null) { 2349365a826b46b0e274df88e92534f7d871eef2aa2mindyp mSwipedListener.onListItemSwiped(convList); 2359365a826b46b0e274df88e92534f7d871eef2aa2mindyp } 2366c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira adapter.notifyDataSetChanged(); 237a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira if (mConvSelectionSet != null && !mConvSelectionSet.isEmpty() 238a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira && mConvSelectionSet.contains(conv)) { 239a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira mConvSelectionSet.toggle(null, conv); 24054f120f6ada40c7191811dfff99b151e9e192c78mindyp // Don't commit destructive actions if the item we just removed from 24154f120f6ada40c7191811dfff99b151e9e192c78mindyp // the selection set is the item we just destroyed! 24254f120f6ada40c7191811dfff99b151e9e192c78mindyp if (!conv.isMostlyDead() && mConvSelectionSet.isEmpty()) { 24354f120f6ada40c7191811dfff99b151e9e192c78mindyp commitDestructiveActions(true); 24454f120f6ada40c7191811dfff99b151e9e192c78mindyp } 245cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira } 246f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 247f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 248f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira @Override 249f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public void onBeginDrag(View v) { 250f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira // We do this so the underlying ScrollView knows that it won't get 251f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira // the chance to intercept events anymore 252f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira requestDisallowInterceptTouchEvent(true); 2531ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira SwipeableConversationItemView view = null; 2541ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira if (v instanceof ConversationItemView) { 25500ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira view = (SwipeableConversationItemView) v.getParent(); 2561ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira } 2571ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira if (view != null) { 25884f9b5c60dc023570202859ba1d30cf9cb5e6e7aMindy Pereira view.addBackground(getContext()); 2591ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira view.setBackgroundVisibility(View.VISIBLE); 2601ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira } 2613b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp cancelDismissCounter(); 262f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 263f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 264f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira @Override 2656c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira public void onDragCancelled(SwipeableItemView v) { 266709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira SwipeableConversationItemView view = null; 267709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira if (v instanceof ConversationItemView) { 26800ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira view = (SwipeableConversationItemView) ((View) v).getParent(); 269709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira } 270709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira if (view != null) { 271709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira view.removeBackground(); 272709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira } 2733b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp final AnimatedAdapter adapter = getAnimatedAdapter(); 2743b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (adapter != null) { 2753b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp adapter.startDismissCounter(); 2764d4531a63cff536d2ee1a2929d0820981df8516amindyp adapter.cancelFadeOutLastLeaveBehindItemText(); 2773b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 278f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 279f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 28007118a01f7183645957010779222b84930f75b4eMindy Pereira /** 28107118a01f7183645957010779222b84930f75b4eMindy Pereira * Archive items using the swipe away animation before shrinking them away. 28207118a01f7183645957010779222b84930f75b4eMindy Pereira */ 283cec3e0b9c90173e0bdb2d072046b38714fc9186ePaul Westbrook public boolean destroyItems(Collection<Conversation> convs, 28484f7d32bdc79263004ed5241480988e02f8e618cmindyp final ListItemsRemovedListener listener) { 28584f7d32bdc79263004ed5241480988e02f8e618cmindyp if (convs == null) { 286cec3e0b9c90173e0bdb2d072046b38714fc9186ePaul Westbrook LogUtils.e(LOG_TAG, "SwipeableListView.destroyItems: null conversations."); 287cec3e0b9c90173e0bdb2d072046b38714fc9186ePaul Westbrook return false; 28884f7d32bdc79263004ed5241480988e02f8e618cmindyp } 289a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwal final AnimatedAdapter adapter = getAnimatedAdapter(); 290a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwal if (adapter == null) { 291a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwal LogUtils.e(LOG_TAG, "SwipeableListView.destroyItems: Cannot destroy: adapter is null."); 292cec3e0b9c90173e0bdb2d072046b38714fc9186ePaul Westbrook return false; 293067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 29484f7d32bdc79263004ed5241480988e02f8e618cmindyp adapter.swipeDelete(convs, listener); 295cec3e0b9c90173e0bdb2d072046b38714fc9186ePaul Westbrook return true; 296067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 297067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 298cc2f9296ad63ed681c200feb118c5caace36e72emindyp public int findConversation(ConversationItemView view, Conversation conv) { 299067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira int position = conv.position; 300067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira long convId = conv.id; 301067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira try { 302067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (position == INVALID_POSITION) { 303067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira position = getPositionForView(view); 304067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 305067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } catch (Exception e) { 306067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira position = INVALID_POSITION; 307067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira LogUtils.w(LOG_TAG, "Exception finding position; using alternate strategy"); 308067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 309067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (position == INVALID_POSITION) { 310067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira // Try the other way! 311067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira Conversation foundConv; 312067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira long foundId; 313067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira for (int i = 0; i < getChildCount(); i++) { 314067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira View child = getChildAt(i); 315067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (child instanceof SwipeableConversationItemView) { 316067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira foundConv = ((SwipeableConversationItemView) child).getSwipeableItemView() 317067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira .getConversation(); 318067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira foundId = foundConv.id; 319067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (foundId == convId) { 320067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira position = i; 321067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira break; 322067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 323067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 324067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 325c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira } 326067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return position; 32707118a01f7183645957010779222b84930f75b4eMindy Pereira } 32807118a01f7183645957010779222b84930f75b4eMindy Pereira 3290fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira private AnimatedAdapter getAnimatedAdapter() { 3300fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira return (AnimatedAdapter) getAdapter(); 3310fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira } 3320fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira 3338937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira @Override 3348937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira public boolean performItemClick(View view, int pos, long id) { 335dd9d3a16148b178cb95fd4db4168a67c64eb944fMindy Pereira boolean handled = super.performItemClick(view, pos, id); 33600ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira // Commit any existing destructive actions when the user selects a 33700ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira // conversation to view. 338c6adce3cf6887c4c6dd5005724565702751843d0mindyp commitDestructiveActions(true); 339dd9d3a16148b178cb95fd4db4168a67c64eb944fMindy Pereira return handled; 3408937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira } 3415254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp 3425254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp @Override 343d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp public void onScroll() { 344d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp commitDestructiveActions(true); 3455254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp } 3469365a826b46b0e274df88e92534f7d871eef2aa2mindyp 3479365a826b46b0e274df88e92534f7d871eef2aa2mindyp public interface ListItemsRemovedListener { 3489365a826b46b0e274df88e92534f7d871eef2aa2mindyp public void onListItemsRemoved(); 3499365a826b46b0e274df88e92534f7d871eef2aa2mindyp } 3509365a826b46b0e274df88e92534f7d871eef2aa2mindyp 3519365a826b46b0e274df88e92534f7d871eef2aa2mindyp public interface ListItemSwipedListener { 3529365a826b46b0e274df88e92534f7d871eef2aa2mindyp public void onListItemSwiped(Collection<Conversation> conversations); 3539365a826b46b0e274df88e92534f7d871eef2aa2mindyp } 35469b440141f402669fe44dfd8924a94fd22ebccf7mindyp 35569b440141f402669fe44dfd8924a94fd22ebccf7mindyp @Override 35669b440141f402669fe44dfd8924a94fd22ebccf7mindyp public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) { 35769b440141f402669fe44dfd8924a94fd22ebccf7mindyp // Do nothing. 35869b440141f402669fe44dfd8924a94fd22ebccf7mindyp } 35969b440141f402669fe44dfd8924a94fd22ebccf7mindyp 36069b440141f402669fe44dfd8924a94fd22ebccf7mindyp @Override 36169b440141f402669fe44dfd8924a94fd22ebccf7mindyp public void onScrollStateChanged(AbsListView arg0, int scrollState) { 36269b440141f402669fe44dfd8924a94fd22ebccf7mindyp switch (scrollState) { 36369b440141f402669fe44dfd8924a94fd22ebccf7mindyp case OnScrollListener.SCROLL_STATE_IDLE: 36469b440141f402669fe44dfd8924a94fd22ebccf7mindyp mScrolling = false; 36569b440141f402669fe44dfd8924a94fd22ebccf7mindyp break; 36669b440141f402669fe44dfd8924a94fd22ebccf7mindyp default: 36769b440141f402669fe44dfd8924a94fd22ebccf7mindyp mScrolling = true; 36869b440141f402669fe44dfd8924a94fd22ebccf7mindyp } 36969b440141f402669fe44dfd8924a94fd22ebccf7mindyp } 3703b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp 3713b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp @Override 3723b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp public void cancelDismissCounter() { 3733b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp AnimatedAdapter adapter = getAnimatedAdapter(); 3743b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (adapter != null) { 3753b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp adapter.cancelDismissCounter(); 3763b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 3773b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 3787af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp 3797af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp @Override 3807af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp public LeaveBehindItem getLastSwipedItem() { 3817af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp AnimatedAdapter adapter = getAnimatedAdapter(); 3827af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp if (adapter != null) { 3837af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp return adapter.getLastLeaveBehindItem(); 3847af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp } 3857af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp return null; 3867af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp } 38700ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira} 388