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

Commit 5d9eb1f8 authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Support auto-scroll roots drawer when dragging"

parents 8c222d3b ded3dc52
Loading
Loading
Loading
Loading
+35 −19
Original line number Diff line number Diff line
@@ -14,21 +14,22 @@
 * limitations under the License.
 */

package com.android.documentsui.dirlist;
package com.android.documentsui;

import android.graphics.Point;
import androidx.annotation.VisibleForTesting;
import android.view.DragEvent;
import android.view.View;
import android.view.View.OnDragListener;
import android.widget.AbsListView;

import com.android.documentsui.ItemDragListener;
import com.android.documentsui.ItemDragListener.DragHost;
import com.android.documentsui.selection.ViewAutoScroller;
import com.android.documentsui.selection.ViewAutoScroller.ScrollHost;
import com.android.documentsui.selection.ViewAutoScroller.ScrollerCallbacks;

import java.util.function.BooleanSupplier;
import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.Predicate;

@@ -36,9 +37,9 @@ import javax.annotation.Nullable;

/**
 * This class acts as a middle-man handler for potential auto-scrolling before passing the dragEvent
 * onto {@link DirectoryDragListener}.
 * onto {@link ItemDragListener}.
 */
class DragHoverListener implements OnDragListener {
public class DragHoverListener implements OnDragListener {

    private final ItemDragListener<? extends DragHost> mDragHandler;
    private final IntSupplier mHeight;
@@ -47,12 +48,12 @@ class DragHoverListener implements OnDragListener {
    private final Runnable mDragScroller;

    /**
     * Predicate to tests whether it's the scroll view ({@link DirectoryFragment#mRecView}) itself.
     * Predicate to tests whether it's the scroll view itself.
     *
     * {@link DragHoverListener} is used for both {@link DirectoryFragment#mRecView} and its
     * children. When we decide whether it's in the scroll zone we need to obtain the coordinate
     * relative to {@link DirectoryFragment#mRecView} so we need to transform the coordinate if the
     * view that gets drag and drop events is a child of {@link DirectoryFragment#mRecView}.
     * {@link DragHoverListener} is used for both the scroll view and its children.
     * When we decide whether it's in the scroll zone we need to obtain the coordinate
     * relative to container view so we need to transform the coordinate if the view
     * that gets drag and drop events is a child of scroll view.
     */
    private final Predicate<View> mIsScrollView;

@@ -94,20 +95,37 @@ class DragHoverListener implements OnDragListener {
        mDragScroller = new ViewAutoScroller(scrollHost, scrollCallbacks);
    }

    static DragHoverListener create(
    public static DragHoverListener create(
            ItemDragListener<? extends DragHost> dragHandler,
            AbsListView scrollView) {
        return create(dragHandler, scrollView, scrollView::scrollListBy);
    }

    public static DragHoverListener create(
            ItemDragListener<? extends DragHost> dragHandler,
            View scrollView) {
        return create(
                dragHandler,
                scrollView,
                (int dy) -> {
                    scrollView.scrollBy(0, dy);
                });
    }

    static DragHoverListener create(
            ItemDragListener<? extends DragHost> dragHandler,
            View scrollView,
            IntConsumer scroller) {

        ScrollerCallbacks scrollCallbacks = new ScrollerCallbacks() {
            @Override
            public void scrollBy(int dy) {
                scrollView.scrollBy(0, dy);
                scroller.accept(dy);
            }

            @Override
            public void runAtNextFrame(Runnable r) {
                scrollView.postOnAnimation(r);

            }

            @Override
@@ -116,15 +134,13 @@ class DragHoverListener implements OnDragListener {
            }
        };

        DragHoverListener listener = new DragHoverListener(
        return new DragHoverListener(
                dragHandler,
                scrollView::getHeight,
                (view) -> (scrollView == view),
                () -> scrollView.canScrollVertically(-1),
                () -> scrollView.canScrollVertically(1),
                scrollCallbacks);

        return listener;
    }

    @Override
@@ -157,9 +173,9 @@ class DragHoverListener implements OnDragListener {
    }

    private Point transformToScrollViewCoordinate(View v, float x, float y) {
        // Check if v is the RecyclerView itself. If not we need to transform the coordinate to
        // relative to the RecyclerView because we need to test the scroll zone in the coordinate
        // relative to the RecyclerView; if yes we don't need to transform coordinates.
        // Check if v is the scroll view itself. If not we need to transform the coordinate to
        // relative to the scroll view because we need to test the scroll zone in the coordinate
        // relative to the scroll view; if yes we don't need to transform coordinates.
        final boolean isScrollView = mIsScrollView.test(v);
        final float offsetX = isScrollView ? 0 : v.getX();
        final float offsetY = isScrollView ? 0 : v.getY();
+12 −0
Original line number Diff line number Diff line
@@ -63,6 +63,10 @@ public class ItemDragListener<H extends DragHost> implements OnDragListener {

    @Override
    public boolean onDrag(final View v, DragEvent event) {
        if (!mDragHost.canHandleDragEvent(v)) {
            return false;
        }

        switch (event.getAction()) {
            case DragEvent.ACTION_DRAG_STARTED:
                return true;
@@ -193,5 +197,13 @@ public class ItemDragListener<H extends DragHost> implements OnDragListener {
         * Notifies when the drag and drop has ended.
         */
        void onDragEnded();

        /**
         * Whether drag events can dispatch to the view.
         * @param v the view being to receive drag events
         */
        default boolean canHandleDragEvent(View v) {
            return true;
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import com.android.documentsui.ActionModeController;
import com.android.documentsui.BaseActivity;
import com.android.documentsui.BaseActivity.RetainedState;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.DragHoverListener;
import com.android.documentsui.FocusManager;
import com.android.documentsui.Injector;
import com.android.documentsui.Injector.ContentScoped;
+5 −0
Original line number Diff line number Diff line
@@ -55,6 +55,11 @@ class DragHost extends AbstractDragHost {
        mActivity.runOnUiThread(runnable);
    }

    @Override
    public boolean canHandleDragEvent(View v) {
        return v instanceof RootItemView;
    }

    @Override
    public void setDropTargetHighlight(View v, boolean highlight) {
        // SpacerView doesn't have DragListener so this view is guaranteed to be a RootItemView.
+4 −1
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.widget.ListView;
import com.android.documentsui.ActionHandler;
import com.android.documentsui.BaseActivity;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.DragHoverListener;
import com.android.documentsui.Injector;
import com.android.documentsui.Injector.Injected;
import com.android.documentsui.ItemDragListener;
@@ -197,7 +198,7 @@ public class RootsFragment extends Fragment {
                    DocumentsApplication.getDragAndDropManager(activity),
                    this::getItem,
                    mActionHandler);
            mDragListener = new ItemDragListener<DragHost>(host) {
            final ItemDragListener<DragHost> listener = new ItemDragListener<DragHost>(host) {
                @Override
                public boolean handleDropEventChecked(View v, DragEvent event) {
                    final Item item = getItem(v);
@@ -207,6 +208,8 @@ public class RootsFragment extends Fragment {
                    return item.dropOn(event);
                }
            };
            mDragListener = DragHoverListener.create(listener, mList);
            mList.setOnDragListener(mDragListener);
        }

        mCallbacks = new LoaderCallbacks<Collection<RootInfo>>() {
Loading