SwipeableListView.java revision c6adce3cf6887c4c6dd5005724565702751843d0
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
20f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.content.Context;
21f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereiraimport android.content.res.Configuration;
228db7e407109532557718c6b8064792f2df7a073dMindy Pereiraimport android.net.Uri;
23f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.util.AttributeSet;
24f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.MotionEvent;
25f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.View;
26f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereiraimport android.view.ViewConfiguration;
275254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindypimport android.widget.AbsListView;
285254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindypimport android.widget.AbsListView.OnScrollListener;
29f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.widget.ListView;
30f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
31f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.R;
32bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport com.android.mail.browse.ConversationCursor;
33f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.browse.ConversationItemView;
341ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereiraimport com.android.mail.browse.SwipeableConversationItemView;
35f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.providers.Conversation;
3606642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereiraimport com.android.mail.providers.Folder;
37f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.ui.SwipeHelper.Callback;
38b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag;
39b0219eb7b77212902a38821c050922ac73a68250Mindy Pereiraimport com.android.mail.utils.LogUtils;
40f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
41866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereiraimport java.util.ArrayList;
42f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport java.util.Collection;
438db7e407109532557718c6b8064792f2df7a073dMindy Pereiraimport java.util.HashMap;
44f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
455254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyppublic class SwipeableListView extends ListView implements Callback, OnScrollListener {
46f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    private SwipeHelper mSwipeHelper;
47ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    private boolean mEnableSwipe = false;
48489dd22c64c718b6953b4bd6acef925e82c53c87Andy Huang
49b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook    public static final String LOG_TAG = LogTag.getLogTag();
50f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
51866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    private ConversationSelectionSet mConvSelectionSet;
526c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    private int mSwipeAction;
5306642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira    private Folder mFolder;
54866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
55f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public SwipeableListView(Context context) {
56f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        this(context, null);
57f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
58f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
59f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public SwipeableListView(Context context, AttributeSet attrs) {
60f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        this(context, attrs, -1);
61f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
62f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
63f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public SwipeableListView(Context context, AttributeSet attrs, int defStyle) {
64f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        super(context, attrs, defStyle);
65f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        float densityScale = getResources().getDisplayMetrics().density;
66f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        float pagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop();
676f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira        mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, densityScale,
686f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira                pagingTouchSlop);
695254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        setOnScrollListener(this);
70f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
71f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
72f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira    @Override
73f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira    protected void onConfigurationChanged(Configuration newConfig) {
74f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        super.onConfigurationChanged(newConfig);
75f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        float densityScale = getResources().getDisplayMetrics().density;
76f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        mSwipeHelper.setDensityScale(densityScale);
77f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
78f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
79f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira    }
80f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira
81ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    /**
82ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira     * Enable swipe gestures.
83ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira     */
84ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    public void enableSwipe(boolean enable) {
85ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira        mEnableSwipe = enable;
86ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    }
87ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira
88f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira    public boolean isSwipeEnabled() {
89f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira        return mEnableSwipe;
90f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira    }
91f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira
926c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public void setSwipeAction(int action) {
936c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        mSwipeAction = action;
94f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
95f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
96de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira    public int getSwipeAction() {
97de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira        return mSwipeAction;
98de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira    }
99de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira
100866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    public void setSelectionSet(ConversationSelectionSet set) {
101866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira        mConvSelectionSet = set;
102866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
103866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
10406642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira    public void setCurrentFolder(Folder folder) {
10506642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira        mFolder = folder;
10606642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira    }
10706642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira
108866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    @Override
109866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    public ConversationSelectionSet getSelectionSet() {
110866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira        return mConvSelectionSet;
111866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
112866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
113f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
114f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public boolean onInterceptTouchEvent(MotionEvent ev) {
115ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira        if (mEnableSwipe) {
11600ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira            return mSwipeHelper.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev);
11719bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira        } else {
11819bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira            return super.onInterceptTouchEvent(ev);
11919bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira        }
120f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
121f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
122f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
123f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public boolean onTouchEvent(MotionEvent ev) {
124ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira        if (mEnableSwipe) {
12519bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira            return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev);
12619bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira        } else {
12719bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira            return super.onTouchEvent(ev);
12819bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira        }
129f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
130f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
131f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
132f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public View getChildAtPosition(MotionEvent ev) {
133f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        // find the view under the pointer, accounting for GONE views
134f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        final int count = getChildCount();
135f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        int touchY = (int) ev.getY();
136f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        int childIdx = 0;
137f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        View slidingChild;
138f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        for (; childIdx < count; childIdx++) {
139f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira            slidingChild = getChildAt(childIdx);
140f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira            if (slidingChild.getVisibility() == GONE) {
141f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira                continue;
142f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira            }
143866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira            if (touchY >= slidingChild.getTop() && touchY <= slidingChild.getBottom()) {
1441ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                if (slidingChild instanceof SwipeableConversationItemView) {
1451ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                    return ((SwipeableConversationItemView) slidingChild).getSwipeableItemView();
1461ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                }
147866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira                return slidingChild;
148866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira            }
149f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        }
150f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        return null;
151f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
152f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
153f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
1546c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public boolean canChildBeDismissed(SwipeableItemView v) {
155a538984fcc19e7624f2650b119ede39bf1f35846mindyp        return v.canChildBeDismissed();
156f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
157f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
158f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
1596c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public void onChildDismissed(SwipeableItemView v) {
160a538984fcc19e7624f2650b119ede39bf1f35846mindyp        v.dismiss();
161f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
162f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
1638937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    // Call this whenever a new action is taken; this forces a commit of any
1648937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    // existing destructive actions.
165c6adce3cf6887c4c6dd5005724565702751843d0mindyp    public void commitDestructiveActions(boolean animate) {
1660fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira        final AnimatedAdapter adapter = getAnimatedAdapter();
1678937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira        if (adapter != null) {
168c6adce3cf6887c4c6dd5005724565702751843d0mindyp            adapter.commitLeaveBehindItems(animate);
1698937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira        }
1708937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    }
1718937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira
172a538984fcc19e7624f2650b119ede39bf1f35846mindyp    public void dismissChild(final ConversationItemView target) {
1736c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        final Context context = getContext();
174d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira        final ToastBarOperation undoOp;
175866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
176c6e22c76be15b86df66770c08edc5f9e5b844280Mindy Pereira        undoOp = new ToastBarOperation(1, mSwipeAction, ToastBarOperation.UNDO);
1776c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        Conversation conv = target.getConversation();
17813e6243683cc8cb998a43d06f25d6ff1aab9d93bMindy Pereira        target.getConversation().position = findConversation(target, conv);
1790fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira        final AnimatedAdapter adapter = getAnimatedAdapter();
18009f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira        if (adapter == null) {
18109f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira            return;
18209f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira        }
1836c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        adapter.setupLeaveBehind(conv, undoOp, conv.position);
18400ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira        ConversationCursor cc = (ConversationCursor) adapter.getCursor();
1856c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        switch (mSwipeAction) {
18601f30509c4c8ad0d13b7635447b7f023c7a0cab7Mindy Pereira            case R.id.remove_folder:
1878db7e407109532557718c6b8064792f2df7a073dMindy Pereira                FolderOperation folderOp = new FolderOperation(mFolder, false);
1888db7e407109532557718c6b8064792f2df7a073dMindy Pereira                HashMap<Uri, Folder> targetFolders = Folder
18968f83843e821d9627a53f68244dbc4cb26662edcMindy Pereira                        .hashMapForFolders(conv.getRawFolders());
1908db7e407109532557718c6b8064792f2df7a073dMindy Pereira                targetFolders.remove(folderOp.mFolder.uri);
19185c4a77abd849f5f3f0236d51554bb1bb99fe8f6Mindy Pereira                conv.setRawFolders(Folder.getSerializedFolderString(targetFolders.values()));
1928db7e407109532557718c6b8064792f2df7a073dMindy Pereira                cc.mostlyDestructiveUpdate(context, Conversation.listOf(conv),
19385c4a77abd849f5f3f0236d51554bb1bb99fe8f6Mindy Pereira                        Conversation.UPDATE_FOLDER_COLUMN, conv.getRawFoldersString());
19406642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira                break;
1956c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            case R.id.archive:
196a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira                cc.mostlyArchive(context, Conversation.listOf(conv));
1976c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                break;
1986c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            case R.id.delete:
199a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira                cc.mostlyDelete(context, Conversation.listOf(conv));
2006c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                break;
2016c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        }
2026c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        adapter.notifyDataSetChanged();
203a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira        if (mConvSelectionSet != null && !mConvSelectionSet.isEmpty()
204a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira                && mConvSelectionSet.contains(conv)) {
205a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira            mConvSelectionSet.toggle(null, conv);
206cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira        }
207f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
208f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
209f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
210f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public void onBeginDrag(View v) {
211f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        // We do this so the underlying ScrollView knows that it won't get
212f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        // the chance to intercept events anymore
213f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        requestDisallowInterceptTouchEvent(true);
2141ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        SwipeableConversationItemView view = null;
2151ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        if (v instanceof ConversationItemView) {
21600ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira            view = (SwipeableConversationItemView) v.getParent();
2171ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        }
2181ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        if (view != null) {
21984f9b5c60dc023570202859ba1d30cf9cb5e6e7aMindy Pereira            view.addBackground(getContext());
2201ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira            view.setBackgroundVisibility(View.VISIBLE);
2211ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        }
222f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
223f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
224f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
2256c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public void onDragCancelled(SwipeableItemView v) {
226709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira        SwipeableConversationItemView view = null;
227709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira        if (v instanceof ConversationItemView) {
22800ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira            view = (SwipeableConversationItemView) ((View) v).getParent();
229709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira        }
230709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira        if (view != null) {
231709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira            view.removeBackground();
232709a174a40ec296c40368d723c2f51e3fc48ed50Mindy Pereira        }
233f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
234f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
23507118a01f7183645957010779222b84930f75b4eMindy Pereira    /**
23607118a01f7183645957010779222b84930f75b4eMindy Pereira     * Archive items using the swipe away animation before shrinking them away.
23707118a01f7183645957010779222b84930f75b4eMindy Pereira     */
238c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira    public void destroyItems(final ArrayList<ConversationItemView> views,
23968f83843e821d9627a53f68244dbc4cb26662edcMindy Pereira            final DestructiveAction listener) {
24007118a01f7183645957010779222b84930f75b4eMindy Pereira        if (views == null || views.size() == 0) {
24107118a01f7183645957010779222b84930f75b4eMindy Pereira            return;
24207118a01f7183645957010779222b84930f75b4eMindy Pereira        }
243c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira        // Need to find the items in the LIST!
24407118a01f7183645957010779222b84930f75b4eMindy Pereira        final ArrayList<Conversation> conversations = new ArrayList<Conversation>();
24507118a01f7183645957010779222b84930f75b4eMindy Pereira        for (ConversationItemView view : views) {
246de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira            Conversation conv = view.getConversation();
247067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            conv.position = findConversation(view, conv);
248de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira            conversations.add(conv);
24907118a01f7183645957010779222b84930f75b4eMindy Pereira        }
250c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira        AnimatedAdapter adapter = getAnimatedAdapter();
251c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira        if (adapter != null) {
252067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            adapter.swipeDelete(conversations, listener);
253067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        }
254067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    }
255067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira
256067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    private int findConversation(ConversationItemView view, Conversation conv) {
257067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        int position = conv.position;
258067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        long convId = conv.id;
259067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        try {
260067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            if (position == INVALID_POSITION) {
261067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                position = getPositionForView(view);
262067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            }
263067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        } catch (Exception e) {
264067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            position = INVALID_POSITION;
265067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            LogUtils.w(LOG_TAG, "Exception finding position; using alternate strategy");
266067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        }
267067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        if (position == INVALID_POSITION) {
268067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            // Try the other way!
269067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            Conversation foundConv;
270067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            long foundId;
271067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            for (int i = 0; i < getChildCount(); i++) {
272067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                View child = getChildAt(i);
273067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                if (child instanceof SwipeableConversationItemView) {
274067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                    foundConv = ((SwipeableConversationItemView) child).getSwipeableItemView()
275067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                            .getConversation();
276067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                    foundId = foundConv.id;
277067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                    if (foundId == convId) {
278067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                        position = i;
279067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                        break;
280067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                    }
281067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                }
282067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            }
283c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira        }
284067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        return position;
28507118a01f7183645957010779222b84930f75b4eMindy Pereira    }
28607118a01f7183645957010779222b84930f75b4eMindy Pereira
2870fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira    private AnimatedAdapter getAnimatedAdapter() {
2880fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira        return (AnimatedAdapter) getAdapter();
2890fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira    }
2900fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira
291f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public interface SwipeCompleteListener {
292f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        public void onSwipeComplete(Collection<Conversation> conversations);
293f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
2948937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira
2958937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    @Override
2968937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    public boolean performItemClick(View view, int pos, long id) {
297dd9d3a16148b178cb95fd4db4168a67c64eb944fMindy Pereira        boolean handled = super.performItemClick(view, pos, id);
29800ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira        // Commit any existing destructive actions when the user selects a
29900ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira        // conversation to view.
300c6adce3cf6887c4c6dd5005724565702751843d0mindyp        commitDestructiveActions(true);
301dd9d3a16148b178cb95fd4db4168a67c64eb944fMindy Pereira        return handled;
3028937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    }
3035254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp
3045254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp    @Override
3055254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp    public void onScroll(AbsListView view, int arg1, int arg2, int arg3) {
3065254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        // Do nothing; we only care about going from not scrolling to scrolling.
3075254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp    }
3085254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp
3095254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp    @Override
3105254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp    public void onScrollStateChanged(AbsListView view, int state) {
3115254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        if (state == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL
3125254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp                || state == OnScrollListener.SCROLL_STATE_FLING) {
313c6adce3cf6887c4c6dd5005724565702751843d0mindyp            commitDestructiveActions(true);
3145254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        }
3155254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp    }
31600ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira}
317