SwipeableListView.java revision 3432b636fbcf7d6cc551b9705ed4dd88ae2b4f49
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;
26f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.MotionEvent;
27f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.View;
28f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereiraimport android.view.ViewConfiguration;
297c411aafd9ef059f881b7532426e61d1def54a07Andrew Sappersteinimport android.widget.AbsListView;
307c411aafd9ef059f881b7532426e61d1def54a07Andrew Sappersteinimport android.widget.AbsListView.OnScrollListener;
31f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.widget.ListView;
32f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
33f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.R;
34042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huangimport com.android.mail.analytics.Analytics;
35bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport com.android.mail.browse.ConversationCursor;
36f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.browse.ConversationItemView;
371ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereiraimport com.android.mail.browse.SwipeableConversationItemView;
386126d72ae2769bd39451872f45781cadb5b90515Mark Weiimport com.android.mail.providers.Account;
39f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.providers.Conversation;
4006642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereiraimport com.android.mail.providers.Folder;
41b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huangimport com.android.mail.providers.FolderList;
42f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.ui.SwipeHelper.Callback;
43b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag;
44b0219eb7b77212902a38821c050922ac73a68250Mindy Pereiraimport com.android.mail.utils.LogUtils;
457517e3b61b898a57f19be0671f70d58a82224643Andy Huangimport com.android.mail.utils.Utils;
46f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
47866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereiraimport java.util.ArrayList;
48f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport java.util.Collection;
498db7e407109532557718c6b8064792f2df7a073dMindy Pereiraimport java.util.HashMap;
50f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
5169b440141f402669fe44dfd8924a94fd22ebccf7mindyppublic class SwipeableListView extends ListView implements Callback, OnScrollListener {
526126d72ae2769bd39451872f45781cadb5b90515Mark Wei    private final SwipeHelper mSwipeHelper;
53ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    private boolean mEnableSwipe = false;
54489dd22c64c718b6953b4bd6acef925e82c53c87Andy Huang
55b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook    public static final String LOG_TAG = LogTag.getLogTag();
56479505d71969e26b0785d8e0e1b81108731cf827Mark Wei    /**
57479505d71969e26b0785d8e0e1b81108731cf827Mark Wei     * Set to false to prevent the FLING scroll state from pausing the photo manager loaders.
58479505d71969e26b0785d8e0e1b81108731cf827Mark Wei     */
59479505d71969e26b0785d8e0e1b81108731cf827Mark Wei    private final static boolean SCROLL_PAUSE_ENABLE = true;
60f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
6179c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang    /**
6279c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang     * Set to true to enable parallax effect for attachment previews as the scroll position varies.
6379c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang     * This effect triggers invalidations on scroll (!) and requires more memory for attachment
6479c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang     * preview bitmaps.
6579c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang     */
6679c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang    public static final boolean ENABLE_ATTACHMENT_PARALLAX = true;
6765b6d180f50922a3393795203cae68a5a2f6a33dMark Wei
6865b6d180f50922a3393795203cae68a5a2f6a33dMark Wei    /**
6965b6d180f50922a3393795203cae68a5a2f6a33dMark Wei     * Set to true to queue finished decodes in an aggregator so that we display decoded attachment
7065b6d180f50922a3393795203cae68a5a2f6a33dMark Wei     * previews in an ordered fashion. This artificially delays updating the UI with decoded images,
7165b6d180f50922a3393795203cae68a5a2f6a33dMark Wei     * since they may have to wait on another image to finish decoding first.
7265b6d180f50922a3393795203cae68a5a2f6a33dMark Wei     */
7365b6d180f50922a3393795203cae68a5a2f6a33dMark Wei    public static final boolean ENABLE_ATTACHMENT_DECODE_AGGREGATOR = true;
7479c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang
7579c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang    /**
7679c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang     * The amount of extra vertical space to decode in attachment previews so we have image data to
7779c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang     * pan within. 1.0 implies no parallax effect.
7879c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang     */
79901bf8b70ead9af21652c0f01fd9b87b2c7efc6cMark Wei    public static final float ATTACHMENT_PARALLAX_MULTIPLIER_NORMAL = 1.5f;
80901bf8b70ead9af21652c0f01fd9b87b2c7efc6cMark Wei    public static final float ATTACHMENT_PARALLAX_MULTIPLIER_ALTERNATIVE = 2.0f;
8152a61db87c487fe5bb7cc673037887a6d35b0f0fMark Wei
82866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    private ConversationSelectionSet mConvSelectionSet;
836c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    private int mSwipeAction;
846126d72ae2769bd39451872f45781cadb5b90515Mark Wei    private Account mAccount;
8506642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira    private Folder mFolder;
869365a826b46b0e274df88e92534f7d871eef2aa2mindyp    private ListItemSwipedListener mSwipedListener;
8769b440141f402669fe44dfd8924a94fd22ebccf7mindyp    private boolean mScrolling;
88866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
89e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang    private SwipeListener mSwipeListener;
90e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang
914485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal    // Instantiated through view inflation
924485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal    @SuppressWarnings("unused")
93f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public SwipeableListView(Context context) {
94f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        this(context, null);
95f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
96f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
97f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public SwipeableListView(Context context, AttributeSet attrs) {
98f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        this(context, attrs, -1);
99f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
100f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
101f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public SwipeableListView(Context context, AttributeSet attrs, int defStyle) {
102f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        super(context, attrs, defStyle);
1032229eddfba6f7517c43ef49ee67c50c24d4b961aMark Wei        setOnScrollListener(this);
104f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        float densityScale = getResources().getDisplayMetrics().density;
105f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        float pagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop();
1066f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira        mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, densityScale,
1076f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira                pagingTouchSlop);
108f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
109f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
110f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira    @Override
111f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira    protected void onConfigurationChanged(Configuration newConfig) {
112f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        super.onConfigurationChanged(newConfig);
113f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        float densityScale = getResources().getDisplayMetrics().density;
114f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        mSwipeHelper.setDensityScale(densityScale);
115f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
116f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
117f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira    }
118f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira
1197517e3b61b898a57f19be0671f70d58a82224643Andy Huang    @Override
1207517e3b61b898a57f19be0671f70d58a82224643Andy Huang    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
121bc88f16af48d9538b79cbeab88cd275cb769a67dVikram Aggarwal        LogUtils.d(Utils.VIEW_DEBUGGING_TAG,
1227517e3b61b898a57f19be0671f70d58a82224643Andy Huang                "START CLF-ListView.onFocusChanged layoutRequested=%s root.layoutRequested=%s",
1237517e3b61b898a57f19be0671f70d58a82224643Andy Huang                isLayoutRequested(), getRootView().isLayoutRequested());
1247517e3b61b898a57f19be0671f70d58a82224643Andy Huang        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
125bc88f16af48d9538b79cbeab88cd275cb769a67dVikram Aggarwal        LogUtils.d(Utils.VIEW_DEBUGGING_TAG, new Error(),
1267517e3b61b898a57f19be0671f70d58a82224643Andy Huang                "FINISH CLF-ListView.onFocusChanged layoutRequested=%s root.layoutRequested=%s",
1277517e3b61b898a57f19be0671f70d58a82224643Andy Huang                isLayoutRequested(), getRootView().isLayoutRequested());
1287517e3b61b898a57f19be0671f70d58a82224643Andy Huang    }
1297517e3b61b898a57f19be0671f70d58a82224643Andy Huang
130ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    /**
131ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira     * Enable swipe gestures.
132ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira     */
133ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    public void enableSwipe(boolean enable) {
134ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira        mEnableSwipe = enable;
135ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    }
136ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira
1376c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public void setSwipeAction(int action) {
1386c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        mSwipeAction = action;
139f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
140f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
1417c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein    public void setListItemSwipedListener(ListItemSwipedListener listener) {
1429365a826b46b0e274df88e92534f7d871eef2aa2mindyp        mSwipedListener = listener;
1439365a826b46b0e274df88e92534f7d871eef2aa2mindyp    }
1449365a826b46b0e274df88e92534f7d871eef2aa2mindyp
145de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira    public int getSwipeAction() {
146de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira        return mSwipeAction;
147de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira    }
148de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira
149866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    public void setSelectionSet(ConversationSelectionSet set) {
150866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira        mConvSelectionSet = set;
151866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
152866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
1536126d72ae2769bd39451872f45781cadb5b90515Mark Wei    public void setCurrentAccount(Account account) {
1546126d72ae2769bd39451872f45781cadb5b90515Mark Wei        mAccount = account;
1556126d72ae2769bd39451872f45781cadb5b90515Mark Wei    }
1566126d72ae2769bd39451872f45781cadb5b90515Mark Wei
15706642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira    public void setCurrentFolder(Folder folder) {
15806642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira        mFolder = folder;
15906642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira    }
16006642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira
161866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    @Override
162866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    public ConversationSelectionSet getSelectionSet() {
163866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira        return mConvSelectionSet;
164866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
165866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
166f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
167f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public boolean onInterceptTouchEvent(MotionEvent ev) {
1683432b636fbcf7d6cc551b9705ed4dd88ae2b4f49Jin Cao        if (mScrolling) {
16919bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira            return super.onInterceptTouchEvent(ev);
17069b440141f402669fe44dfd8924a94fd22ebccf7mindyp        } else {
17169b440141f402669fe44dfd8924a94fd22ebccf7mindyp            return mSwipeHelper.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev);
17219bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira        }
173f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
174f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
175f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
176f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public boolean onTouchEvent(MotionEvent ev) {
1773432b636fbcf7d6cc551b9705ed4dd88ae2b4f49Jin Cao        return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev);
178f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
179f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
180f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
181f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public View getChildAtPosition(MotionEvent ev) {
182f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        // find the view under the pointer, accounting for GONE views
183f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        final int count = getChildCount();
184f69d0394f7de5c0681b8d5d5ca0c60b55c55f815Vikram Aggarwal        final int touchY = (int) ev.getY();
185f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        int childIdx = 0;
186f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        View slidingChild;
187f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        for (; childIdx < count; childIdx++) {
188f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira            slidingChild = getChildAt(childIdx);
189f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira            if (slidingChild.getVisibility() == GONE) {
190f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira                continue;
191f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira            }
192866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira            if (touchY >= slidingChild.getTop() && touchY <= slidingChild.getBottom()) {
1931ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                if (slidingChild instanceof SwipeableConversationItemView) {
1941ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                    return ((SwipeableConversationItemView) slidingChild).getSwipeableItemView();
1951ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                }
196866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira                return slidingChild;
197866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira            }
198f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        }
199f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        return null;
200f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
201f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
202f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
2036c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public boolean canChildBeDismissed(SwipeableItemView v) {
2043432b636fbcf7d6cc551b9705ed4dd88ae2b4f49Jin Cao        return mEnableSwipe && v.canChildBeDismissed();
205f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
206f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
207f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
2086c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public void onChildDismissed(SwipeableItemView v) {
2090760bfbf8259e4161ce7737fc980b6b9297885ccmindyp        if (v != null) {
2100760bfbf8259e4161ce7737fc980b6b9297885ccmindyp            v.dismiss();
2110760bfbf8259e4161ce7737fc980b6b9297885ccmindyp        }
212f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
213f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
2148937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    // Call this whenever a new action is taken; this forces a commit of any
2158937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    // existing destructive actions.
216c6adce3cf6887c4c6dd5005724565702751843d0mindyp    public void commitDestructiveActions(boolean animate) {
2170fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira        final AnimatedAdapter adapter = getAnimatedAdapter();
2188937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira        if (adapter != null) {
219c6adce3cf6887c4c6dd5005724565702751843d0mindyp            adapter.commitLeaveBehindItems(animate);
2208937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira        }
2218937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    }
2228937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira
223a538984fcc19e7624f2650b119ede39bf1f35846mindyp    public void dismissChild(final ConversationItemView target) {
2247c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein        // Notifies the SwipeListener that a swipe has ended.
2257c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein        if (mSwipeListener != null) {
2267c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein            mSwipeListener.onEndSwipe();
2277c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein        }
2287c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein
229d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira        final ToastBarOperation undoOp;
230866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
2316a3d5ce0b18f58fcfa1af0315dc8ddc7331c2c5fScott Kennedy        undoOp = new ToastBarOperation(1, mSwipeAction, ToastBarOperation.UNDO, false /* batch */,
2326a3d5ce0b18f58fcfa1af0315dc8ddc7331c2c5fScott Kennedy                mFolder);
2336c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        Conversation conv = target.getConversation();
23413e6243683cc8cb998a43d06f25d6ff1aab9d93bMindy Pereira        target.getConversation().position = findConversation(target, conv);
2350fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira        final AnimatedAdapter adapter = getAnimatedAdapter();
23609f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira        if (adapter == null) {
23709f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira            return;
23809f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira        }
239370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang        adapter.setupLeaveBehind(conv, undoOp, conv.position, target.getHeight());
24000ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira        ConversationCursor cc = (ConversationCursor) adapter.getCursor();
2419365a826b46b0e274df88e92534f7d871eef2aa2mindyp        Collection<Conversation> convList = Conversation.listOf(conv);
2425cc0ab20009100e3ef259fe3d2e3ddc357f79285mindyp        ArrayList<Uri> folderUris;
2435cc0ab20009100e3ef259fe3d2e3ddc357f79285mindyp        ArrayList<Boolean> adds;
244042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang
2452b55549d4fbe25e91f673a0727fc89ff755d9327Andy Huang        Analytics.getInstance().sendMenuItemEvent("list_swipe", mSwipeAction, null, 0);
246042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang
2472b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy        if (mSwipeAction == R.id.remove_folder) {
2482b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            FolderOperation folderOp = new FolderOperation(mFolder, false);
2492b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            HashMap<Uri, Folder> targetFolders = Folder
2502b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                    .hashMapForFolders(conv.getRawFolders());
2512b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            targetFolders.remove(folderOp.mFolder.folderUri.fullUri);
2522b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            final FolderList folders = FolderList.copyOf(targetFolders.values());
2532b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            conv.setRawFolders(folders);
2542b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            final ContentValues values = new ContentValues();
2552b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            folderUris = new ArrayList<Uri>();
2562b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            folderUris.add(mFolder.folderUri.fullUri);
2572b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            adds = new ArrayList<Boolean>();
2582b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            adds.add(Boolean.FALSE);
2592b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            ConversationCursor.addFolderUpdates(folderUris, adds, values);
2602b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            ConversationCursor.addTargetFolders(targetFolders.values(), values);
2612b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            cc.mostlyDestructiveUpdate(Conversation.listOf(conv), values);
2622b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy        } else if (mSwipeAction == R.id.archive) {
2632b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            cc.mostlyArchive(convList);
2642b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy        } else if (mSwipeAction == R.id.delete) {
2652b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            cc.mostlyDelete(convList);
2666c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        }
2679365a826b46b0e274df88e92534f7d871eef2aa2mindyp        if (mSwipedListener != null) {
2689365a826b46b0e274df88e92534f7d871eef2aa2mindyp            mSwipedListener.onListItemSwiped(convList);
2699365a826b46b0e274df88e92534f7d871eef2aa2mindyp        }
2706c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        adapter.notifyDataSetChanged();
271a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira        if (mConvSelectionSet != null && !mConvSelectionSet.isEmpty()
272a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira                && mConvSelectionSet.contains(conv)) {
27320a97ded277fdcd3c63952a23718410c2882103fVikram Aggarwal            mConvSelectionSet.toggle(conv);
27454f120f6ada40c7191811dfff99b151e9e192c78mindyp            // Don't commit destructive actions if the item we just removed from
27554f120f6ada40c7191811dfff99b151e9e192c78mindyp            // the selection set is the item we just destroyed!
27654f120f6ada40c7191811dfff99b151e9e192c78mindyp            if (!conv.isMostlyDead() && mConvSelectionSet.isEmpty()) {
27754f120f6ada40c7191811dfff99b151e9e192c78mindyp                commitDestructiveActions(true);
27854f120f6ada40c7191811dfff99b151e9e192c78mindyp            }
279cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira        }
280f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
281f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
282f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
283f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public void onBeginDrag(View v) {
284f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        // We do this so the underlying ScrollView knows that it won't get
285f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        // the chance to intercept events anymore
286f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        requestDisallowInterceptTouchEvent(true);
2873b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp        cancelDismissCounter();
288e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang
2897c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein        // Notifies the SwipeListener that a swipe has begun.
290e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang        if (mSwipeListener != null) {
291e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang            mSwipeListener.onBeginSwipe();
292e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang        }
293f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
294f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
295f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
2966c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public void onDragCancelled(SwipeableItemView v) {
2973b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp        final AnimatedAdapter adapter = getAnimatedAdapter();
2983b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp        if (adapter != null) {
2993b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp            adapter.startDismissCounter();
3004d4531a63cff536d2ee1a2929d0820981df8516amindyp            adapter.cancelFadeOutLastLeaveBehindItemText();
3013b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp        }
3027c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein
3037c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein        // Notifies the SwipeListener that a swipe has ended.
3047c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein        if (mSwipeListener != null) {
3057c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein            mSwipeListener.onEndSwipe();
3067c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein        }
307f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
308f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
30907118a01f7183645957010779222b84930f75b4eMindy Pereira    /**
31007118a01f7183645957010779222b84930f75b4eMindy Pereira     * Archive items using the swipe away animation before shrinking them away.
31107118a01f7183645957010779222b84930f75b4eMindy Pereira     */
312cec3e0b9c90173e0bdb2d072046b38714fc9186ePaul Westbrook    public boolean destroyItems(Collection<Conversation> convs,
31384f7d32bdc79263004ed5241480988e02f8e618cmindyp            final ListItemsRemovedListener listener) {
31484f7d32bdc79263004ed5241480988e02f8e618cmindyp        if (convs == null) {
315cec3e0b9c90173e0bdb2d072046b38714fc9186ePaul Westbrook            LogUtils.e(LOG_TAG, "SwipeableListView.destroyItems: null conversations.");
316cec3e0b9c90173e0bdb2d072046b38714fc9186ePaul Westbrook            return false;
31784f7d32bdc79263004ed5241480988e02f8e618cmindyp        }
318a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwal        final AnimatedAdapter adapter = getAnimatedAdapter();
319a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwal        if (adapter == null) {
320a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwal            LogUtils.e(LOG_TAG, "SwipeableListView.destroyItems: Cannot destroy: adapter is null.");
321cec3e0b9c90173e0bdb2d072046b38714fc9186ePaul Westbrook            return false;
322067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        }
32384f7d32bdc79263004ed5241480988e02f8e618cmindyp        adapter.swipeDelete(convs, listener);
324cec3e0b9c90173e0bdb2d072046b38714fc9186ePaul Westbrook        return true;
325067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    }
326067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira
327cc2f9296ad63ed681c200feb118c5caace36e72emindyp    public int findConversation(ConversationItemView view, Conversation conv) {
328dbb587f15c723ae80edb33f65c29cc2b6c15eba0Scott Kennedy        int position = INVALID_POSITION;
329067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        long convId = conv.id;
330067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        try {
331dbb587f15c723ae80edb33f65c29cc2b6c15eba0Scott Kennedy            position = getPositionForView(view);
332067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        } catch (Exception e) {
333067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            position = INVALID_POSITION;
334599e7f8bf95d2f21a966cbff1bf72adf77a90a33Andy Huang            LogUtils.w(LOG_TAG, e, "Exception finding position; using alternate strategy");
335067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        }
336067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        if (position == INVALID_POSITION) {
337067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            // Try the other way!
338067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            Conversation foundConv;
339067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            long foundId;
340067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            for (int i = 0; i < getChildCount(); i++) {
341067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                View child = getChildAt(i);
342067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                if (child instanceof SwipeableConversationItemView) {
343067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                    foundConv = ((SwipeableConversationItemView) child).getSwipeableItemView()
344067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                            .getConversation();
345067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                    foundId = foundConv.id;
346067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                    if (foundId == convId) {
347599e7f8bf95d2f21a966cbff1bf72adf77a90a33Andy Huang                        position = i + getFirstVisiblePosition();
348067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                        break;
349067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                    }
350067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                }
351067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            }
352c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira        }
353067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        return position;
35407118a01f7183645957010779222b84930f75b4eMindy Pereira    }
35507118a01f7183645957010779222b84930f75b4eMindy Pereira
3560fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira    private AnimatedAdapter getAnimatedAdapter() {
3570fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira        return (AnimatedAdapter) getAdapter();
3580fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira    }
3590fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira
3608937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    @Override
3618937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    public boolean performItemClick(View view, int pos, long id) {
362f69d0394f7de5c0681b8d5d5ca0c60b55c55f815Vikram Aggarwal        final int previousPosition = getCheckedItemPosition();
363f69d0394f7de5c0681b8d5d5ca0c60b55c55f815Vikram Aggarwal        final boolean selectionSetEmpty = mConvSelectionSet.isEmpty();
3646126d72ae2769bd39451872f45781cadb5b90515Mark Wei
3656126d72ae2769bd39451872f45781cadb5b90515Mark Wei        // Superclass method modifies the selection set
366f69d0394f7de5c0681b8d5d5ca0c60b55c55f815Vikram Aggarwal        final boolean handled = super.performItemClick(view, pos, id);
3676126d72ae2769bd39451872f45781cadb5b90515Mark Wei
3681fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy        // If we are in CAB mode then a click shouldn't
3696126d72ae2769bd39451872f45781cadb5b90515Mark Wei        // activate the new item, it should only add it to the selection set
3701fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy        if (!selectionSetEmpty && previousPosition != -1) {
3716126d72ae2769bd39451872f45781cadb5b90515Mark Wei            setItemChecked(previousPosition, true);
3726126d72ae2769bd39451872f45781cadb5b90515Mark Wei        }
37300ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira        // Commit any existing destructive actions when the user selects a
37400ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira        // conversation to view.
375c6adce3cf6887c4c6dd5005724565702751843d0mindyp        commitDestructiveActions(true);
376dd9d3a16148b178cb95fd4db4168a67c64eb944fMindy Pereira        return handled;
3778937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    }
3785254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp
3795254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp    @Override
380d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp    public void onScroll() {
381d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp        commitDestructiveActions(true);
3825254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp    }
3839365a826b46b0e274df88e92534f7d871eef2aa2mindyp
3849365a826b46b0e274df88e92534f7d871eef2aa2mindyp    public interface ListItemsRemovedListener {
3859365a826b46b0e274df88e92534f7d871eef2aa2mindyp        public void onListItemsRemoved();
3869365a826b46b0e274df88e92534f7d871eef2aa2mindyp    }
3879365a826b46b0e274df88e92534f7d871eef2aa2mindyp
3889365a826b46b0e274df88e92534f7d871eef2aa2mindyp    public interface ListItemSwipedListener {
3899365a826b46b0e274df88e92534f7d871eef2aa2mindyp        public void onListItemSwiped(Collection<Conversation> conversations);
3909365a826b46b0e274df88e92534f7d871eef2aa2mindyp    }
39169b440141f402669fe44dfd8924a94fd22ebccf7mindyp
39269b440141f402669fe44dfd8924a94fd22ebccf7mindyp    @Override
39379c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang    public final void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
394479505d71969e26b0785d8e0e1b81108731cf827Mark Wei            int totalItemCount) {
39579c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang        if (ENABLE_ATTACHMENT_PARALLAX) {
39679c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang            for (int i = 0, len = getChildCount(); i < len; i++) {
39779c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang                final View child = getChildAt(i);
39879c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang                if (child instanceof OnScrollListener) {
39979c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang                    ((OnScrollListener) child).onScroll(view, firstVisibleItem, visibleItemCount,
40079c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang                            totalItemCount);
40179c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang                }
40279c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang            }
40379c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang        }
40469b440141f402669fe44dfd8924a94fd22ebccf7mindyp    }
40569b440141f402669fe44dfd8924a94fd22ebccf7mindyp
40669b440141f402669fe44dfd8924a94fd22ebccf7mindyp    @Override
40781aea35d45b3d0191ec595562a2fcf67009845d5Mark Wei    public void onScrollStateChanged(final AbsListView view, final int scrollState) {
408479505d71969e26b0785d8e0e1b81108731cf827Mark Wei        mScrolling = scrollState != OnScrollListener.SCROLL_STATE_IDLE;
409479505d71969e26b0785d8e0e1b81108731cf827Mark Wei
41048ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang        if (!mScrolling) {
41148ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang            final Context c = getContext();
41248ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang            if (c instanceof ControllableActivity) {
41348ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang                final ControllableActivity activity = (ControllableActivity) c;
41448ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang                activity.onAnimationEnd(null /* adapter */);
41548ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang            } else {
41648ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang                LogUtils.wtf(LOG_TAG, "unexpected context=%s", c);
41748ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang            }
41848ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang        }
419479505d71969e26b0785d8e0e1b81108731cf827Mark Wei
420479505d71969e26b0785d8e0e1b81108731cf827Mark Wei        if (SCROLL_PAUSE_ENABLE) {
421670c280136f587688d41027ce1ff1596068a35e0Mark Wei            AnimatedAdapter adapter = getAnimatedAdapter();
422670c280136f587688d41027ce1ff1596068a35e0Mark Wei            if (adapter != null) {
423670c280136f587688d41027ce1ff1596068a35e0Mark Wei                adapter.onScrollStateChanged(scrollState);
424670c280136f587688d41027ce1ff1596068a35e0Mark Wei            }
425479505d71969e26b0785d8e0e1b81108731cf827Mark Wei        }
42648ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang    }
42748ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang
42848ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang    public boolean isScrolling() {
42948ccbc53ef90bf6420f831f63e6243008e02a346Andy Huang        return mScrolling;
43069b440141f402669fe44dfd8924a94fd22ebccf7mindyp    }
4313b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp
4323b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp    @Override
4333b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp    public void cancelDismissCounter() {
4343b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp        AnimatedAdapter adapter = getAnimatedAdapter();
4353b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp        if (adapter != null) {
4363b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp            adapter.cancelDismissCounter();
4373b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp        }
4383b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp    }
4397af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp
4407af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp    @Override
4417af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp    public LeaveBehindItem getLastSwipedItem() {
4427af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp        AnimatedAdapter adapter = getAnimatedAdapter();
4437af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp        if (adapter != null) {
4447af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp            return adapter.getLastLeaveBehindItem();
4457af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp        }
4467af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp        return null;
4477af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp    }
448e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang
449e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang    public void setSwipeListener(SwipeListener swipeListener) {
450e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang        mSwipeListener = swipeListener;
451e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang    }
452e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang
453e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang    public interface SwipeListener {
454e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang        public void onBeginSwipe();
4557c411aafd9ef059f881b7532426e61d1def54a07Andrew Sapperstein        public void onEndSwipe();
456e6f4ddc19c205796cde91d58483fa39c3cc13f1aAlice Yang    }
45700ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira}
458