Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2131091c authored by Hongwei Wang's avatar Hongwei Wang Committed by Android (Google) Code Review
Browse files

Merge "Refactor the D-N-D, let list view handle all the events" into klp-dev

parents d9e9634e 7639fe9a
Loading
Loading
Loading
Loading
+0 −132
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.dialer.list;

import android.graphics.Rect;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.view.View.OnDragListener;

import com.android.dialer.list.PhoneFavoritesTileAdapter.ContactTileRow;

/**
 * Implements the OnLongClickListener and OnDragListener for phone's favorite tiles and rows.
 */
public class PhoneFavoriteDragAndDropListeners {

    private static final String TAG = PhoneFavoriteDragAndDropListeners.class.getSimpleName();
    private static final boolean DEBUG = false;

    /**
     * Implements the OnDragListener to handle drag events.
     */
    public static class PhoneFavoriteDragListener implements OnDragListener {
        /** Location of the drag event. */
        private float mX = 0;
        private float mY = 0;
        private final ContactTileRow mContactTileRow;
        private final PhoneFavoritesTileAdapter mTileAdapter;

        public PhoneFavoriteDragListener(ContactTileRow contactTileRow,
                PhoneFavoritesTileAdapter tileAdapter) {
            super();
            mContactTileRow = contactTileRow;
            mTileAdapter = tileAdapter;
        }

        /**
         * @return The item index in {@link #mTileAdapter} for the given {@link DragEvent}.
         *     Returns -1 if {@link #mTileAdapter} is not in dragging or index can not be found.
         */
        private int getDragItemIndex(DragEvent event) {
            int itemIndex = -1;
            if (mTileAdapter != null && mContactTileRow != null
                    && !mTileAdapter.getInDragging()) {
                mX = event.getX();
                mY = event.getY();
                if (DEBUG) {
                    Log.v(TAG, String.valueOf(mX) + "; " + String.valueOf(mY));
                }

                final int[] rowLocation = new int[2];
                mContactTileRow.getLocationOnScreen(rowLocation);

                final Rect locationRect = new Rect(rowLocation[0], rowLocation[1],
                        rowLocation[0] + mContactTileRow.getWidth(),
                        rowLocation[1] + mContactTileRow.getHeight());

                if (locationRect.contains((int) mX, (int) mY)) {
                    // Finds out which item is being dragged.
                    // Computes relative coordinates as we get absolute coordinates.
                    itemIndex = mContactTileRow.getItemIndex(
                            mX - rowLocation[0], mY - rowLocation[1]);
                    if (DEBUG) {
                        Log.v(TAG, "Start dragging " + String.valueOf(itemIndex));
                    }
                }
            }
            return itemIndex;
        }

        @Override
        public boolean onDrag(View v, DragEvent event) {
            if (DEBUG) {
                Log.v(TAG, event.toString());
            }
            // Handles drag events.
            switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:
                    final int itemIndex = getDragItemIndex(event);
                    if (itemIndex != -1) {
                        // Indicates a drag has started.
                        mTileAdapter.setInDragging(true);

                        // Temporarily pops out the Contact entry.
                        mTileAdapter.popContactEntry(itemIndex);
                    }
                    break;
                case DragEvent.ACTION_DRAG_ENTERED:
                    break;
                case DragEvent.ACTION_DRAG_EXITED:
                    break;
                case DragEvent.ACTION_DROP:
                    // Indicates a drag has finished.
                    if (mTileAdapter != null && mContactTileRow != null) {
                        mTileAdapter.setInDragging(false);
                        // The drop to position has been reported to the adapter
                        // via {@link DragEvent#ACTION_DRAG_LOCATION} events in ListView.
                        mTileAdapter.handleDrop();
                    }
                    break;
                case DragEvent.ACTION_DRAG_ENDED:
                    if (mTileAdapter != null && mTileAdapter.getInDragging()) {
                        // If the drag and drop ends when the drop happens outside of any rows,
                        // we will end the drag here and put the item back to where it was dragged
                        // from before.
                        mTileAdapter.setInDragging(false);
                        mTileAdapter.handleDrop();
                    }
                    break;
                case DragEvent.ACTION_DRAG_LOCATION:
                    break;
                default:
                    break;
            }
            return true;
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -211,6 +211,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
        mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT);
        mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
        mListView.setOnItemSwipeListener(mContactTileAdapter);
        mListView.setOnDragDropListener(mContactTileAdapter);

        mEmptyView = inflater.inflate(R.layout.phone_no_favorites, mListView, false);

+69 −42
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
    private boolean mEnableSwipe = true;

    private OnItemGestureListener mOnItemGestureListener;
    private OnDragDropListener mOnDragDropListener;

    private float mDensityScale;
    private float mTouchSlop;
@@ -60,6 +61,7 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
    private final int DRAG_SCROLL_PX_UNIT = 10;

    private boolean mIsDragScrollerRunning = false;
    private int mTouchDownForDragStartX;
    private int mTouchDownForDragStartY;

    /**
@@ -121,9 +123,14 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
        mOnItemGestureListener = listener;
    }

    public void setOnDragDropListener(OnDragDropListener listener) {
        mOnDragDropListener = listener;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            mTouchDownForDragStartX = (int) ev.getX();
            mTouchDownForDragStartY = (int) ev.getY();
        }
        if (isSwipeEnabled()) {
@@ -147,24 +154,13 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba

    @Override
    public View getChildAtPosition(MotionEvent ev) {
        // find the view under the pointer, accounting for GONE views
        final int count = getChildCount();
        final int touchY = (int) ev.getY();
        View slidingChild;
        for (int childIdx = 0; childIdx < count; childIdx++) {
            slidingChild = getChildAt(childIdx);
            if (slidingChild.getVisibility() == GONE) {
                continue;
            }
            if (touchY >= slidingChild.getTop() && touchY <= slidingChild.getBottom()) {
                if (SwipeHelper.isSwipeable(slidingChild)) {
        final View view = getViewAtPosition((int) ev.getX(), (int) ev.getY());
        if (view != null &&
                SwipeHelper.isSwipeable(view) &&
                view.getVisibility() != GONE) {
            // If this view is swipable in this listview, then return it. Otherwise
            // return a null view, which will simply be ignored by the swipe helper.
                    return slidingChild;
                } else {
                    return null;
                }
            }
            return view;
        }
        return null;
    }
@@ -205,10 +201,16 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba

    @Override
    public boolean dispatchDragEvent(DragEvent event) {
        switch (event.getAction()) {
        final int action = event.getAction();
        final int eX = (int) event.getX();
        final int eY = (int) event.getY();
        switch (action) {
            case DragEvent.ACTION_DRAG_STARTED:
                handleDragStarted(mTouchDownForDragStartX, mTouchDownForDragStartY);
                break;
            case DragEvent.ACTION_DRAG_LOCATION:
                mLastDragY = (int) event.getY();
                handleDrag((int) event.getX(), mLastDragY);
                mLastDragY = eY;
                handleDragHovered(eX, eY);
                // Kick off {@link #mScrollHandler} if it's not started yet.
                if (!mIsDragScrollerRunning &&
                        // And if the distance traveled while dragging exceeds the touch slop
@@ -229,13 +231,30 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
                ensureScrollHandler();
                mScrollHandler.removeCallbacks(mDragScroller);
                mIsDragScrollerRunning = false;
                if (action != DragEvent.ACTION_DRAG_EXITED) {
                    handleDragFinished();
                }
                break;
            case DragEvent.ACTION_DRAG_STARTED:
                // Not a receiver
            default:
                break;
        }
        return super.dispatchDragEvent(event);
        // This ListView will consumer the drag events on behalf of its children.
        return true;
    }

    /**
     * Find the view under the pointer.
     */
    private View getViewAtPosition(int x, int y) {
        final int count = getChildCount();
        View child;
        for (int childIdx = 0; childIdx < count; childIdx++) {
            child = getChildAt(childIdx);
            if (y >= child.getTop() && y <= child.getBottom()) {
                return child;
            }
        }
        return null;
    }

    private void ensureScrollHandler() {
@@ -244,29 +263,37 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
        }
    }

    private void handleDrag(int x, int y) {
        // find the view under the pointer, accounting for GONE views
        final int count = getChildCount();
        View slidingChild;
        for (int childIdx = 0; childIdx < count; childIdx++) {
            slidingChild = getChildAt(childIdx);
            if (slidingChild.getVisibility() == GONE) {
                continue;
    private void handleDragStarted(int x, int y) {
        final View child = getViewAtPosition(x, y);
        if (child instanceof ContactTileRow) {
            final ContactTileRow tile = (ContactTileRow) child;
            final int itemIndex = tile.getItemIndex(x, y);
            if (itemIndex != -1 && mOnDragDropListener != null) {
                mOnDragDropListener.onDragStarted(itemIndex);
            }
            if (y >= slidingChild.getTop() &&
                    y <= slidingChild.getBottom() &&
                    slidingChild instanceof ContactTileRow) {
                final ContactTileRow tile = (ContactTileRow) slidingChild;
                reportDragEnteredItemIndex(tile.getItemIndex(x, y));
        }
    }

    private void handleDragHovered(int x, int y) {
        final View child = getViewAtPosition(x, y);
        if (child instanceof ContactTileRow) {
            final ContactTileRow tile = (ContactTileRow) child;
            final int itemIndex = tile.getItemIndex(x, y);
            if (itemIndex != -1 && mOnDragDropListener != null) {
                mOnDragDropListener.onDragHovered(itemIndex);
            }
        }
    }

    private void reportDragEnteredItemIndex(int itemIndex) {
        final PhoneFavoriteMergedAdapter adapter =
                (PhoneFavoriteMergedAdapter) getAdapter();
        if (adapter != null) {
            adapter.reportDragEnteredItemIndex(itemIndex);
    private void handleDragFinished() {
        if (mOnDragDropListener != null) {
            mOnDragDropListener.onDragFinished();
        }
    }

    public interface OnDragDropListener {
        public void onDragStarted(int itemIndex);
        public void onDragHovered(int itemIndex);
        public void onDragFinished();
    }
}
+0 −6
Original line number Diff line number Diff line
@@ -346,10 +346,4 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter {
            mOnItemSwipeListener = listener;
        }
    }

    public void reportDragEnteredItemIndex(int itemIndex) {
        if (mContactTileAdapter != null) {
            mContactTileAdapter.reportDragEnteredItemIndex(itemIndex);
        }
    }
}
+0 −1
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.view.View;

import com.android.contacts.common.util.ViewUtil;
import com.android.dialer.R;
import com.android.dialer.list.PhoneFavoriteDragAndDropListeners.PhoneFavoriteDragListener;

import com.android.dialer.list.PhoneFavoritesTileAdapter.ContactTileRow;

Loading