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

Commit 90a769d1 authored by Ivan Tkachenko's avatar Ivan Tkachenko
Browse files

Bubble bar dismiss interaction

A single bubble and the bubble stack dismiss functionality is implemented using `BubbleDragController`. It attaches a touch listener to the corresponding views and handles gesture interactions.
* When the view is long clicked the dragging to dismiss interaction starts. It scales up the dragged view and presents the dismiss view in the bottom of the window.
* When the bubble or the bubble stack is dragged close to the dismiss target area, it gets pulled towards it and sticks to it. The `MagnetizedObject` and `MagneticTarget` classes are used for it.
* When the dragged view is released outside of the dismiss area, it moves back to the initial position with animation.
* When the dragged bubble is released inside of the dismiss area, it will dismiss the bubble with animation and remove it from the stack.
* When the dragged bubble bar stack is released inside the dismiss area, all the bubbles will get dismissed and the bubble bar will dissapear.

Bug: 271466616
Test: manual, TBD
Flag: WM_BUBBLE_BAR
Change-Id: I83393898be61ec522db92688ac2e111ef7d72fe6
parent 18373d2a
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -49,6 +49,7 @@
        android:visibility="gone"
        android:visibility="gone"
        android:gravity="center"
        android:gravity="center"
        android:clipChildren="false"
        android:clipChildren="false"
        android:elevation="@dimen/bubblebar_elevation"
        />
        />


    <FrameLayout
    <FrameLayout
+1 −0
Original line number Original line Diff line number Diff line
@@ -361,6 +361,7 @@
    <dimen name="bubblebar_stashed_size">@dimen/transient_taskbar_stashed_height</dimen>
    <dimen name="bubblebar_stashed_size">@dimen/transient_taskbar_stashed_height</dimen>
    <dimen name="bubblebar_stashed_handle_height">@dimen/taskbar_stashed_handle_height</dimen>
    <dimen name="bubblebar_stashed_handle_height">@dimen/taskbar_stashed_handle_height</dimen>
    <dimen name="bubblebar_pointer_size">8dp</dimen>
    <dimen name="bubblebar_pointer_size">8dp</dimen>
    <dimen name="bubblebar_elevation">1dp</dimen>


    <dimen name="bubblebar_icon_size">50dp</dimen>
    <dimen name="bubblebar_icon_size">50dp</dimen>
    <dimen name="bubblebar_badge_size">24dp</dimen>
    <dimen name="bubblebar_badge_size">24dp</dimen>
+5 −1
Original line number Original line Diff line number Diff line
@@ -90,6 +90,8 @@ import com.android.launcher3.taskbar.bubbles.BubbleBarController;
import com.android.launcher3.taskbar.bubbles.BubbleBarView;
import com.android.launcher3.taskbar.bubbles.BubbleBarView;
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
import com.android.launcher3.taskbar.bubbles.BubbleControllers;
import com.android.launcher3.taskbar.bubbles.BubbleControllers;
import com.android.launcher3.taskbar.bubbles.BubbleDismissController;
import com.android.launcher3.taskbar.bubbles.BubbleDragController;
import com.android.launcher3.taskbar.bubbles.BubbleStashController;
import com.android.launcher3.taskbar.bubbles.BubbleStashController;
import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController;
import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
@@ -216,7 +218,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
                    new BubbleBarController(this, bubbleBarView),
                    new BubbleBarController(this, bubbleBarView),
                    new BubbleBarViewController(this, bubbleBarView),
                    new BubbleBarViewController(this, bubbleBarView),
                    new BubbleStashController(this),
                    new BubbleStashController(this),
                    new BubbleStashedHandleViewController(this, bubbleHandleView)));
                    new BubbleStashedHandleViewController(this, bubbleHandleView),
                    new BubbleDragController(this),
                    new BubbleDismissController(this, mDragLayer)));
        }
        }


        // Construct controllers.
        // Construct controllers.
+45 −5
Original line number Original line Diff line number Diff line
@@ -95,6 +95,8 @@ public class BubbleBarView extends FrameLayout {
    private View.OnClickListener mOnClickListener;
    private View.OnClickListener mOnClickListener;


    private final Rect mTempRect = new Rect();
    private final Rect mTempRect = new Rect();
    private float mRelativePivotX = 1f;
    private float mRelativePivotY = 1f;


    // An animator that represents the expansion state of the bubble bar, where 0 corresponds to the
    // An animator that represents the expansion state of the bubble bar, where 0 corresponds to the
    // collapsed state and 1 to the fully expanded state.
    // collapsed state and 1 to the fully expanded state.
@@ -109,6 +111,9 @@ public class BubbleBarView extends FrameLayout {
    @Nullable
    @Nullable
    private Consumer<String> mUpdateSelectedBubbleAfterCollapse;
    private Consumer<String> mUpdateSelectedBubbleAfterCollapse;


    @Nullable
    private BubbleView mDraggedBubbleView;

    public BubbleBarView(Context context) {
    public BubbleBarView(Context context) {
        this(context, null);
        this(context, null);
    }
    }
@@ -181,9 +186,10 @@ public class BubbleBarView extends FrameLayout {
        mBubbleBarBounds.right = right;
        mBubbleBarBounds.right = right;
        mBubbleBarBounds.bottom = bottom;
        mBubbleBarBounds.bottom = bottom;


        // The bubble bar handle is aligned to the bottom edge of the screen so scale towards that.
        // The bubble bar handle is aligned according to the relative pivot,
        setPivotX(getWidth());
        // by default it's aligned to the bottom edge of the screen so scale towards that
        setPivotY(getHeight());
        setPivotX(mRelativePivotX * getWidth());
        setPivotY(mRelativePivotY * getHeight());


        // Position the views
        // Position the views
        updateChildrenRenderNodeProperties();
        updateChildrenRenderNodeProperties();
@@ -198,6 +204,32 @@ public class BubbleBarView extends FrameLayout {
        return mBubbleBarBounds;
        return mBubbleBarBounds;
    }
    }


    /**
     * Set bubble bar relative pivot value for X and Y, applied as a fraction of view width/height
     * respectively. If the value is not in range of 0 to 1 it will be normalized.
     * @param x relative X pivot value in range 0..1
     * @param y relative Y pivot value in range 0..1
     */
    public void setRelativePivot(float x, float y) {
        mRelativePivotX = Float.max(Float.min(x, 1), 0);
        mRelativePivotY = Float.max(Float.min(y, 1), 0);
        requestLayout();
    }

    /**
     * Get current relative pivot for X axis
     */
    public float getRelativePivotX() {
        return mRelativePivotX;
    }

    /**
     * Get current relative pivot for Y axis
     */
    public float getRelativePivotY() {
        return mRelativePivotY;
    }

    // TODO: (b/280605790) animate it
    // TODO: (b/280605790) animate it
    @Override
    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
@@ -254,9 +286,9 @@ public class BubbleBarView extends FrameLayout {
                // where the bubble will end up when the animation ends
                // where the bubble will end up when the animation ends
                final float targetX = currentWidth - expandedWidth + expandedX;
                final float targetX = currentWidth - expandedWidth + expandedX;
                bv.setTranslationX(widthState * (targetX - collapsedX) + collapsedX);
                bv.setTranslationX(widthState * (targetX - collapsedX) + collapsedX);
                // if we're fully expanded, set the z level to 0
                // if we're fully expanded, set the z level to 0 or to bubble elevation if dragged
                if (widthState == 1f) {
                if (widthState == 1f) {
                    bv.setZ(0);
                    bv.setZ(bv == mDraggedBubbleView ? mBubbleElevation : 0);
                }
                }
                // When we're expanded, we're not stacked so we're not behind the stack
                // When we're expanded, we're not stacked so we're not behind the stack
                bv.setBehindStack(false, animate);
                bv.setBehindStack(false, animate);
@@ -331,6 +363,14 @@ public class BubbleBarView extends FrameLayout {
        updateArrowForSelected(/* shouldAnimate= */ true);
        updateArrowForSelected(/* shouldAnimate= */ true);
    }
    }


    /**
     * Sets the dragged bubble view to correctly apply Z order. Dragged view should appear on top
     */
    public void setDraggedBubble(@Nullable BubbleView view) {
        mDraggedBubbleView = view;
        requestLayout();
    }

    /**
    /**
     * Update the arrow position to match the selected bubble.
     * Update the arrow position to match the selected bubble.
     *
     *
+48 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,8 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.FrameLayout;


import androidx.annotation.NonNull;

import com.android.launcher3.R;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarActivityContext;
@@ -54,6 +56,7 @@ public class BubbleBarViewController {
    // Initialized in init.
    // Initialized in init.
    private BubbleStashController mBubbleStashController;
    private BubbleStashController mBubbleStashController;
    private BubbleBarController mBubbleBarController;
    private BubbleBarController mBubbleBarController;
    private BubbleDragController mBubbleDragController;
    private TaskbarStashController mTaskbarStashController;
    private TaskbarStashController mTaskbarStashController;
    private TaskbarInsetsController mTaskbarInsetsController;
    private TaskbarInsetsController mTaskbarInsetsController;
    private View.OnClickListener mBubbleClickListener;
    private View.OnClickListener mBubbleClickListener;
@@ -85,6 +88,7 @@ public class BubbleBarViewController {
    public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
    public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
        mBubbleStashController = bubbleControllers.bubbleStashController;
        mBubbleStashController = bubbleControllers.bubbleStashController;
        mBubbleBarController = bubbleControllers.bubbleBarController;
        mBubbleBarController = bubbleControllers.bubbleBarController;
        mBubbleDragController = bubbleControllers.bubbleDragController;
        mTaskbarStashController = controllers.taskbarStashController;
        mTaskbarStashController = controllers.taskbarStashController;
        mTaskbarInsetsController = controllers.taskbarInsetsController;
        mTaskbarInsetsController = controllers.taskbarInsetsController;


@@ -95,6 +99,7 @@ public class BubbleBarViewController {
        mBubbleBarScale.updateValue(1f);
        mBubbleBarScale.updateValue(1f);
        mBubbleClickListener = v -> onBubbleClicked(v);
        mBubbleClickListener = v -> onBubbleClicked(v);
        mBubbleBarClickListener = v -> setExpanded(true);
        mBubbleBarClickListener = v -> setExpanded(true);
        mBubbleDragController.setupBubbleBarView(mBarView);
        mBarView.setOnClickListener(mBubbleBarClickListener);
        mBarView.setOnClickListener(mBubbleBarClickListener);
        mBarView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
        mBarView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
                mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
                mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
@@ -263,6 +268,7 @@ public class BubbleBarViewController {
        if (b != null) {
        if (b != null) {
            mBarView.addView(b.getView(), 0, new FrameLayout.LayoutParams(mIconSize, mIconSize));
            mBarView.addView(b.getView(), 0, new FrameLayout.LayoutParams(mIconSize, mIconSize));
            b.getView().setOnClickListener(mBubbleClickListener);
            b.getView().setOnClickListener(mBubbleClickListener);
            mBubbleDragController.setupBubbleView(b.getView());
        } else {
        } else {
            Log.w(TAG, "addBubble, bubble was null!");
            Log.w(TAG, "addBubble, bubble was null!");
        }
        }
@@ -314,4 +320,46 @@ public class BubbleBarViewController {
            mBubbleStashController.showBubbleBar(true /* expand the bubbles */);
            mBubbleStashController.showBubbleBar(true /* expand the bubbles */);
        }
        }
    }
    }

    /**
     * Updates the dragged bubble view in the bubble bar view, and notifies SystemUI
     * that a bubble is being dragged to dismiss.
     * @param bubbleView dragged bubble view
     */
    public void onDragStart(@NonNull BubbleView bubbleView) {
        if (bubbleView.getBubble() == null) return;
        mSystemUiProxy.onBubbleDrag(bubbleView.getBubble().getKey(), /* isBeingDragged = */ true);
        mBarView.setDraggedBubble(bubbleView);
    }

    /**
     * Notifies SystemUI to expand the selected bubble when the bubble is released.
     * @param bubbleView dragged bubble view
     */
    public void onDragRelease(@NonNull BubbleView bubbleView) {
        if (bubbleView.getBubble() == null) return;
        mSystemUiProxy.onBubbleDrag(bubbleView.getBubble().getKey(), /* isBeingDragged = */ false);
    }

    /**
     * Removes the dragged bubble view in the bubble bar view
     */
    public void onDragEnd() {
        mBarView.setDraggedBubble(null);
    }

    /**
     * Called when bubble was dragged into the dismiss target. Notifies System
     * @param bubble dismissed bubble item
     */
    public void onDismissBubbleWhileDragging(@NonNull BubbleBarItem bubble) {
        mSystemUiProxy.removeBubble(bubble.getKey());
    }

    /**
     * Called when bubble stack was dragged into the dismiss target
     */
    public void onDismissAllBubblesWhileDragging() {
        mSystemUiProxy.removeAllBubbles();
    }
}
}
Loading