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

Commit ebe1734a authored by Hyunyoung Song's avatar Hyunyoung Song
Browse files

Make drag and drop also work when the widget tray is still in scroll mode.

b/20698514

Change-Id: Ic075f0016d5e00bbdec193bbcd2e311da1957388
parent eede5c03
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@
        android:clipChildren="false"
        android:orientation="vertical">

        <android.support.v7.widget.RecyclerView
        <com.android.launcher3.widget.WidgetsContainerRecyclerView
                android:id="@+id/widgets_list_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
+16 −1
Original line number Diff line number Diff line
@@ -40,6 +40,11 @@ public class AppsContainerRecyclerView extends RecyclerView
        implements RecyclerView.OnItemTouchListener {

    private static final float FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR = 1.5f;
    private static final int SCROLL_DELTA_THRESHOLD = 6;

    /** Keeps the last known scrolling delta/velocity along y-axis. */
    private int mDy = 0;
    private float mDeltaThreshold;

    private AlphabeticalAppsList mApps;
    private int mNumAppsPerRow;
@@ -92,6 +97,7 @@ public class AppsContainerRecyclerView extends RecyclerView
        mScrollbarInset =
                res.getDimensionPixelSize(R.dimen.apps_view_fast_scroll_scrubber_touch_inset);
        setFastScrollerAlpha(getFastScrollerAlpha());
        mDeltaThreshold = getResources().getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD;
    }

    /**
@@ -132,6 +138,7 @@ public class AppsContainerRecyclerView extends RecyclerView

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        addOnItemTouchListener(this);
    }

@@ -142,6 +149,11 @@ public class AppsContainerRecyclerView extends RecyclerView
        drawFastScrollerPopup(canvas);
    }

    @Override
    public void onScrolled(int dx, int dy) {
        mDy = dy;
    }

    /**
     * We intercept the touch handling only to support fast scrolling when initiated from the
     * scroll bar.  Otherwise, we fall back to the default RecyclerView touch handling.
@@ -175,7 +187,10 @@ public class AppsContainerRecyclerView extends RecyclerView
                // Keep track of the down positions
                mDownX = mLastX = x;
                mDownY = mLastY = y;
                if ((Math.abs(mDy) < mDeltaThreshold &&
                        getScrollState() != RecyclerView.SCROLL_STATE_IDLE)) {
                    stopScroll();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                // Check if we are scrolling
+80 −0
Original line number Diff line number Diff line
@@ -17,74 +17,64 @@
package com.android.launcher3.widget;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.TextView;

import com.android.launcher3.R;

/**
 * Layout used for widget tray rows for each app. For performance, this view can be replaced with
 * a {@link RecyclerView} in the future if we settle on scrollable single row for the widgets.
 * If we decide on collapsable grid, then HorizontalScrollView can be replaced with a
 * {@link GridLayout}.
 * The widgets recycler view container.
 * <p>
 * Overwritten to NOT intercept a touch sequence that started when the {@link RecycleView}
 * scrolling slowing down below the internally defined threshold.
 */
public class WidgetsRowView extends HorizontalScrollView {
    static final String TAG = "WidgetsRow";
public class WidgetsContainerRecyclerView extends RecyclerView
        implements RecyclerView.OnItemTouchListener {

    private Runnable mOnLayoutListener;
    private String mAppName;
    private static final int SCROLL_DELTA_THRESHOLD = 6;

    public WidgetsRowView(Context context, String appName) {
        super(context, null, 0);
        mAppName = appName;
    }
    /** Keeps the last known scrolling delta/velocity along y-axis. */
    private int mDy = 0;
    private float mDeltaThreshold;

    /**
     * Clears all the key listeners for the individual widgets.
     */
    public void resetChildrenOnKeyListeners() {
        int childCount = getChildCount();
        for (int j = 0; j < childCount; ++j) {
            getChildAt(j).setOnKeyListener(null);
    public WidgetsContainerRecyclerView(Context context) {
        this(context, null);
    }

    public WidgetsContainerRecyclerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        TextView tv = (TextView) findViewById(R.id.widget_name);
        tv.setText(mAppName);
    public WidgetsContainerRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mDeltaThreshold = getResources().getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mOnLayoutListener = null;
    protected void onFinishInflate() {
        super.onFinishInflate();
        addOnItemTouchListener(this);
    }

    public void setOnLayoutListener(Runnable r) {
        mOnLayoutListener = r;
    @Override
    public void onScrolled(int dx, int dy) {
        mDy = dy;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (mOnLayoutListener != null) {
            mOnLayoutListener.run();
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            if ((Math.abs(mDy) < mDeltaThreshold &&
                    getScrollState() != RecyclerView.SCROLL_STATE_IDLE)) {
                // now the touch events are being passed to the {@link WidgetCell} until the
                // touch sequence goes over the touch slop.
                stopScroll();
            }
        }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean result = super.onTouchEvent(event);
        return result;
        return false;
    }

    public static class LayoutParams extends FrameLayout.LayoutParams {
        public LayoutParams(int width, int height) {
            super(width, height);
        }
    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent ev) {
        // Do nothing.
    }
}
 No newline at end of file