Merge "Revert "Bubble bar drag to dismiss"" into udc-qpr-dev

This commit is contained in:
Mady Mellor
2023-07-13 01:38:05 +00:00
committed by Android (Google) Code Review
11 changed files with 7 additions and 708 deletions

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2023 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.
-->
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke
android:width="2dp"
android:color="@android:color/system_accent1_600" />
<solid android:color="@android:color/system_accent1_600" />
</shape>

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
android:fillColor="@android:color/system_neutral1_50"/>
</vector>

View File

@@ -367,13 +367,6 @@
<dimen name="bubblebar_icon_spacing">3dp</dimen>
<dimen name="bubblebar_icon_elevation">1dp</dimen>
<!-- Bubble bar dismiss view -->
<dimen name="bubblebar_dismiss_target_size">96dp</dimen>
<dimen name="bubblebar_dismiss_target_small_size">60dp</dimen>
<dimen name="bubblebar_dismiss_target_icon_size">24dp</dimen>
<dimen name="bubblebar_dismiss_target_bottom_margin">50dp</dimen>
<dimen name="bubblebar_dismiss_floating_gradient_height">548dp</dimen>
<!-- Launcher splash screen -->
<!-- Note: keep this value in sync with the WindowManager/Shell dimens.xml -->
<!-- starting_surface_exit_animation_window_shift_length -->

View File

@@ -90,8 +90,6 @@ import com.android.launcher3.taskbar.bubbles.BubbleBarController;
import com.android.launcher3.taskbar.bubbles.BubbleBarView;
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
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.BubbleStashedHandleViewController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
@@ -218,9 +216,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
new BubbleBarController(this, bubbleBarView),
new BubbleBarViewController(this, bubbleBarView),
new BubbleStashController(this),
new BubbleStashedHandleViewController(this, bubbleHandleView),
new BubbleDragController(this),
new BubbleDismissController(this, mDragLayer)));
new BubbleStashedHandleViewController(this, bubbleHandleView)));
}
// Construct controllers.

View File

@@ -95,8 +95,6 @@ public class BubbleBarView extends FrameLayout {
private View.OnClickListener mOnClickListener;
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
// collapsed state and 1 to the fully expanded state.
@@ -111,9 +109,6 @@ public class BubbleBarView extends FrameLayout {
@Nullable
private Consumer<String> mUpdateSelectedBubbleAfterCollapse;
@Nullable
private BubbleView mDraggedBubbleView;
public BubbleBarView(Context context) {
this(context, null);
}
@@ -186,10 +181,9 @@ public class BubbleBarView extends FrameLayout {
mBubbleBarBounds.right = right;
mBubbleBarBounds.bottom = bottom;
// The bubble bar handle is aligned according to the relative pivot,
// by default it's aligned to the bottom edge of the screen so scale towards that
setPivotX(mRelativePivotX * getWidth());
setPivotY(mRelativePivotY * getHeight());
// The bubble bar handle is aligned to the bottom edge of the screen so scale towards that.
setPivotX(getWidth());
setPivotY(getHeight());
// Position the views
updateChildrenRenderNodeProperties();
@@ -204,32 +198,6 @@ public class BubbleBarView extends FrameLayout {
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
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
@@ -286,9 +254,9 @@ public class BubbleBarView extends FrameLayout {
// where the bubble will end up when the animation ends
final float targetX = currentWidth - expandedWidth + expandedX;
bv.setTranslationX(widthState * (targetX - collapsedX) + collapsedX);
// if we're fully expanded, set the z level to 0 or to bubble elevation if dragged
// if we're fully expanded, set the z level to 0
if (widthState == 1f) {
bv.setZ(bv == mDraggedBubbleView ? mBubbleElevation : 0);
bv.setZ(0);
}
// When we're expanded, we're not stacked so we're not behind the stack
bv.setBehindStack(false, animate);
@@ -360,14 +328,6 @@ public class BubbleBarView extends FrameLayout {
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.
*

View File

@@ -24,8 +24,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.taskbar.TaskbarActivityContext;
@@ -56,7 +54,6 @@ public class BubbleBarViewController {
// Initialized in init.
private BubbleStashController mBubbleStashController;
private BubbleBarController mBubbleBarController;
private BubbleDragController mBubbleDragController;
private TaskbarStashController mTaskbarStashController;
private TaskbarInsetsController mTaskbarInsetsController;
private View.OnClickListener mBubbleClickListener;
@@ -88,7 +85,6 @@ public class BubbleBarViewController {
public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
mBubbleStashController = bubbleControllers.bubbleStashController;
mBubbleBarController = bubbleControllers.bubbleBarController;
mBubbleDragController = bubbleControllers.bubbleDragController;
mTaskbarStashController = controllers.taskbarStashController;
mTaskbarInsetsController = controllers.taskbarInsetsController;
@@ -99,7 +95,6 @@ public class BubbleBarViewController {
mBubbleBarScale.updateValue(1f);
mBubbleClickListener = v -> onBubbleClicked(v);
mBubbleBarClickListener = v -> setExpanded(true);
mBubbleDragController.setupBubbleBarView(mBarView);
mBarView.setOnClickListener(mBubbleBarClickListener);
mBarView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
@@ -266,7 +261,6 @@ public class BubbleBarViewController {
if (b != null) {
mBarView.addView(b.getView(), 0, new FrameLayout.LayoutParams(mIconSize, mIconSize));
b.getView().setOnClickListener(mBubbleClickListener);
mBubbleDragController.setupBubbleView(b.getView());
} else {
Log.w(TAG, "addBubble, bubble was null!");
}
@@ -318,41 +312,4 @@ public class BubbleBarViewController {
mBubbleStashController.showBubbleBar(true /* expand the bubbles */);
}
}
/**
* Updates the dragged bubble view in the bubble bar view, and notifies SystemUI
* to collapse the selected bubble while it's dragged.
* @param bubbleView dragged bubble view
*/
public void onDragStart(@NonNull BubbleView bubbleView) {
mBarView.setDraggedBubble(bubbleView);
if (bubbleView.getBubble() == null) return;
mSystemUiProxy.collapseWhileDragging(bubbleView.getBubble().getKey(), true /* collapse */);
}
/**
* Removes the dragged bubble view in the bubble bar view, and notifies SystemUI
* to expand the selected bubble when dragging finished.
* @param bubbleView dragged bubble view
*/
public void onDragEnd(@NonNull BubbleView bubbleView) {
mBarView.setDraggedBubble(null);
if (bubbleView.getBubble() == null) return;
mSystemUiProxy.collapseWhileDragging(bubbleView.getBubble().getKey(), false /* collapse */);
}
/**
* 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();
}
}

View File

@@ -27,8 +27,6 @@ public class BubbleControllers {
public final BubbleBarViewController bubbleBarViewController;
public final BubbleStashController bubbleStashController;
public final BubbleStashedHandleViewController bubbleStashedHandleViewController;
public final BubbleDragController bubbleDragController;
public final BubbleDismissController bubbleDismissController;
private final RunnableList mPostInitRunnables = new RunnableList();
@@ -41,15 +39,11 @@ public class BubbleControllers {
BubbleBarController bubbleBarController,
BubbleBarViewController bubbleBarViewController,
BubbleStashController bubbleStashController,
BubbleStashedHandleViewController bubbleStashedHandleViewController,
BubbleDragController bubbleDragController,
BubbleDismissController bubbleDismissController) {
BubbleStashedHandleViewController bubbleStashedHandleViewController) {
this.bubbleBarController = bubbleBarController;
this.bubbleBarViewController = bubbleBarViewController;
this.bubbleStashController = bubbleStashController;
this.bubbleStashedHandleViewController = bubbleStashedHandleViewController;
this.bubbleDragController = bubbleDragController;
this.bubbleDismissController = bubbleDismissController;
}
/**
@@ -62,8 +56,6 @@ public class BubbleControllers {
bubbleBarViewController.init(taskbarControllers, this);
bubbleStashedHandleViewController.init(taskbarControllers, this);
bubbleStashController.init(taskbarControllers, this);
bubbleDragController.init(/* bubbleControllers = */ this);
bubbleDismissController.init(/* bubbleControllers = */ this);
mPostInitRunnables.executeAllAndDestroy();
}

View File

@@ -1,276 +0,0 @@
/*
* Copyright (C) 2023 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.launcher3.taskbar.bubbles;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.res.Resources;
import android.os.SystemProperties;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.DynamicAnimation;
import com.android.launcher3.R;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarDragLayer;
import com.android.wm.shell.common.bubbles.DismissView;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
/**
* Controls dismiss view presentation for the bubble bar dismiss functionality.
* Provides the dragged view snapping to the target dismiss area and animates it.
* When the dragged bubble/bubble stack is realised inside of the target area, it gets dismissed.
*
* @see BubbleDragController
*/
public class BubbleDismissController {
private static final float FLING_TO_DISMISS_MIN_VELOCITY = 6000f;
public static final boolean ENABLE_FLING_TO_DISMISS_BUBBLE =
SystemProperties.getBoolean("persist.wm.debug.fling_to_dismiss_bubble", true);
private final TaskbarActivityContext mActivity;
private final TaskbarDragLayer mDragLayer;
@Nullable
private BubbleBarViewController mBubbleBarViewController;
// Dismiss view that's attached to drag layer. It consists of the scrim view and the circular
// dismiss view used as a dismiss target.
@Nullable
private DismissView mDismissView;
// The currently magnetized object, which is being dragged and will be attracted to the magnetic
// dismiss target. This is either the stack itself, or an individual bubble.
@Nullable
private MagnetizedObject<View> mMagnetizedObject;
// The MagneticTarget instance for our circular dismiss view. This is added to the
// MagnetizedObject instances for the stack and any dragged-out bubbles.
@Nullable
private MagnetizedObject.MagneticTarget mMagneticTarget;
@Nullable
private ValueAnimator mDismissAnimator;
public BubbleDismissController(TaskbarActivityContext activity, TaskbarDragLayer dragLayer) {
mActivity = activity;
mDragLayer = dragLayer;
}
/**
* Initializes dependencies when bubble controllers are created.
* Should be careful to only access things that were created in constructors for now, as some
* controllers may still be waiting for init().
*/
public void init(@NonNull BubbleControllers bubbleControllers) {
mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
}
/**
* Setup the dismiss view and magnetized object that will be attracted to magnetic target.
* Should be called before handling events or showing/hiding dismiss view.
* @param magnetizedView the view to be pulled into target dismiss area
*/
public void setupDismissView(@NonNull View magnetizedView) {
setupDismissView();
setupMagnetizedObject(magnetizedView);
}
/**
* Handle the touch event and pass it to the magnetized object.
* It should be called after {@code setupDismissView}
*/
public boolean handleTouchEvent(@NonNull MotionEvent event) {
return mMagnetizedObject != null && mMagnetizedObject.maybeConsumeMotionEvent(event);
}
/**
* Show dismiss view with animation
* It should be called after {@code setupDismissView}
*/
public void showDismissView() {
if (mDismissView == null) return;
mDismissView.show();
}
/**
* Hide dismiss view with animation
* It should be called after {@code setupDismissView}
*/
public void hideDismissView() {
if (mDismissView == null) return;
mDismissView.hide();
}
/**
* Dismiss magnetized object when it's released in the dismiss target area
*/
private void dismissMagnetizedObject() {
if (mMagnetizedObject == null || mBubbleBarViewController == null) return;
if (mMagnetizedObject.getUnderlyingObject() instanceof BubbleView) {
BubbleView bubbleView = (BubbleView) mMagnetizedObject.getUnderlyingObject();
if (bubbleView.getBubble() != null) {
mBubbleBarViewController.onDismissBubbleWhileDragging(bubbleView.getBubble());
}
} else if (mMagnetizedObject.getUnderlyingObject() instanceof BubbleBarView) {
mBubbleBarViewController.onDismissAllBubblesWhileDragging();
}
cleanUpAnimatedViews();
}
/**
* Animate dismiss view when magnetized object gets stuck in the magnetic target
* @param view captured view
*/
private void animateDismissCaptured(@NonNull View view) {
cancelAnimations();
mDismissAnimator = createDismissAnimator(view);
mDismissAnimator.start();
}
/**
* Animate dismiss view when magnetized object gets unstuck from the magnetic target
*/
private void animateDismissReleased() {
if (mDismissAnimator == null) return;
mDismissAnimator.removeAllListeners();
mDismissAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
cancelAnimations();
}
@Override
public void onAnimationEnd(Animator animation) {
cancelAnimations();
}
});
mDismissAnimator.reverse();
}
/**
* Cancel and clear dismiss animations and reset view states
*/
private void cancelAnimations() {
if (mDismissAnimator == null) return;
ValueAnimator animator = mDismissAnimator;
mDismissAnimator = null;
animator.cancel();
}
/**
* Clean up views changed during animation
*/
private void cleanUpAnimatedViews() {
// Cancel animations
cancelAnimations();
// Reset dismiss view
if (mDismissView != null) {
mDismissView.getCircle().setScaleX(1f);
mDismissView.getCircle().setScaleY(1f);
}
// Reset magnetized view
if (mMagnetizedObject != null) {
mMagnetizedObject.getUnderlyingObject().setAlpha(1f);
mMagnetizedObject.getUnderlyingObject().setScaleX(1f);
mMagnetizedObject.getUnderlyingObject().setScaleY(1f);
}
}
private void setupDismissView() {
if (mDismissView != null) return;
mDismissView = new DismissView(mActivity.getApplicationContext());
BubbleDismissViewUtils.setup(mDismissView);
mDragLayer.addView(mDismissView, /* index = */ 0,
new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
setupMagneticTarget(mDismissView.getCircle());
}
private void setupMagneticTarget(@NonNull View view) {
int magneticFieldRadius = mActivity.getResources().getDimensionPixelSize(
R.dimen.bubblebar_dismiss_target_size);
mMagneticTarget = new MagnetizedObject.MagneticTarget(view, magneticFieldRadius);
}
private void setupMagnetizedObject(@NonNull View magnetizedView) {
mMagnetizedObject = new MagnetizedObject<>(mActivity.getApplicationContext(),
magnetizedView, DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y) {
@Override
public float getWidth(@NonNull View underlyingObject) {
return underlyingObject.getWidth();
}
@Override
public float getHeight(@NonNull View underlyingObject) {
return underlyingObject.getHeight();
}
@Override
public void getLocationOnScreen(@NonNull View underlyingObject, @NonNull int[] loc) {
underlyingObject.getLocationOnScreen(loc);
}
};
mMagnetizedObject.setHapticsEnabled(true);
mMagnetizedObject.setFlingToTargetEnabled(ENABLE_FLING_TO_DISMISS_BUBBLE);
mMagnetizedObject.setFlingToTargetMinVelocity(FLING_TO_DISMISS_MIN_VELOCITY);
if (mMagneticTarget != null) {
mMagnetizedObject.addTarget(mMagneticTarget);
}
mMagnetizedObject.setMagnetListener(new MagnetizedObject.MagnetListener() {
@Override
public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) {
animateDismissCaptured(magnetizedView);
}
@Override
public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
float velX, float velY, boolean wasFlungOut) {
animateDismissReleased();
}
@Override
public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
dismissMagnetizedObject();
}
});
}
private ValueAnimator createDismissAnimator(@NonNull View magnetizedView) {
Resources resources = mActivity.getResources();
int expandedSize = resources.getDimensionPixelSize(R.dimen.bubblebar_dismiss_target_size);
int collapsedSize = resources.getDimensionPixelSize(
R.dimen.bubblebar_dismiss_target_small_size);
float minScale = (float) collapsedSize / expandedSize;
ValueAnimator animator = ValueAnimator.ofFloat(1f, minScale);
animator.addUpdateListener(animation -> {
if (mDismissView == null) return;
final float animatedValue = (float) animation.getAnimatedValue();
mDismissView.getCircle().setScaleX(animatedValue);
mDismissView.getCircle().setScaleY(animatedValue);
magnetizedView.setAlpha(animatedValue);
if (magnetizedView instanceof BubbleBarView) {
magnetizedView.setScaleX(animatedValue);
magnetizedView.setScaleY(animatedValue);
}
});
return animator;
}
}

View File

@@ -1,42 +0,0 @@
/*
* Copyright (C) 2023 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.
*/
@file:JvmName("BubbleDismissViewUtils")
package com.android.launcher3.taskbar.bubbles
import com.android.launcher3.R
import com.android.wm.shell.common.bubbles.DismissView
/**
* Dismiss view is shared from WMShell. It requires setup with local resources.
*
* Usage:
* - Kotlin `dismissView.setup()`
* - Java `BubbleDismissViewUtils.setup(dismissView)`
*/
fun DismissView.setup() {
setup(
DismissView.Config(
targetSizeResId = R.dimen.bubblebar_dismiss_target_size,
iconSizeResId = R.dimen.bubblebar_dismiss_target_icon_size,
bottomMarginResId = R.dimen.bubblebar_dismiss_target_bottom_margin,
floatingGradientHeightResId = R.dimen.bubblebar_dismiss_floating_gradient_height,
floatingGradientColorResId = android.R.color.system_neutral1_900,
backgroundResId = R.drawable.bg_bubble_dismiss_circle,
iconResId = R.drawable.ic_bubble_dismiss_white
)
)
}

View File

@@ -1,189 +0,0 @@
/*
* Copyright (C) 2023 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.launcher3.taskbar.bubbles;
import android.annotation.SuppressLint;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.wm.shell.common.bubbles.RelativeTouchListener;
/**
* Controls bubble bar drag to dismiss interaction.
* Interacts with {@link BubbleDismissController}, used by {@link BubbleBarViewController}.
* Supported interactions:
* - Drag a single bubble view into dismiss target to remove it.
* - Drag the bubble stack into dismiss target to remove all.
* Restores initial position of dragged view if released outside of the dismiss target.
*/
public class BubbleDragController {
private final TaskbarActivityContext mActivity;
private BubbleBarViewController mBubbleBarViewController;
private BubbleDismissController mBubbleDismissController;
public BubbleDragController(TaskbarActivityContext activity) {
mActivity = activity;
}
/**
* Initializes dependencies when bubble controllers are created.
* Should be careful to only access things that were created in constructors for now, as some
* controllers may still be waiting for init().
*/
public void init(@NonNull BubbleControllers bubbleControllers) {
mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
mBubbleDismissController = bubbleControllers.bubbleDismissController;
}
/**
* Setup the bubble view for dragging and attach touch listener to it
*/
@SuppressLint("ClickableViewAccessibility")
public void setupBubbleView(@NonNull BubbleView bubbleView) {
// Don't setup dragging for overflow bubble view
if (bubbleView.getBubble() == null
|| !(bubbleView.getBubble() instanceof BubbleBarBubble)) return;
bubbleView.setOnTouchListener(new BaseDragListener() {
@Override
protected void onDragStart() {
super.onDragStart();
mBubbleBarViewController.onDragStart(bubbleView);
}
@Override
protected void onDragEnd() {
super.onDragEnd();
mBubbleBarViewController.onDragEnd(bubbleView);
}
});
}
/**
* Setup the bubble bar view for dragging and attach touch listener to it
*/
@SuppressLint("ClickableViewAccessibility")
public void setupBubbleBarView(@NonNull BubbleBarView bubbleBarView) {
PointF initialRelativePivot = new PointF();
bubbleBarView.setOnTouchListener(new BaseDragListener() {
@Override
public boolean onDown(@NonNull View view, @NonNull MotionEvent event) {
if (bubbleBarView.isExpanded()) return false;
// Setup dragging only when bubble bar is collapsed
return super.onDown(view, event);
}
@Override
protected void onDragStart() {
super.onDragStart();
initialRelativePivot.set(bubbleBarView.getRelativePivotX(),
bubbleBarView.getRelativePivotY());
bubbleBarView.setRelativePivot(/* x = */ 0.5f, /* y = */ 0.5f);
}
@Override
protected void onDragEnd() {
super.onDragEnd();
bubbleBarView.setRelativePivot(initialRelativePivot.x, initialRelativePivot.y);
}
});
}
/**
* Base drag listener for handling a single bubble view or bubble bar view dragging.
* Controls dragging interaction and interacts with {@link BubbleDismissController}
* to coordinate dismiss view presentation.
* Lifecycle methods can be overridden do add extra setup/clean up steps
*/
private class BaseDragListener extends RelativeTouchListener {
private boolean mHandling;
private boolean mDragging;
@Override
public boolean onDown(@NonNull View view, @NonNull MotionEvent event) {
mHandling = true;
mActivity.setTaskbarWindowFullscreen(true);
mBubbleDismissController.setupDismissView(view);
mBubbleDismissController.handleTouchEvent(event);
return true;
}
@Override
public void onMove(@NonNull View view, @NonNull MotionEvent event, float viewInitialX,
float viewInitialY, float dx, float dy) {
if (!mHandling) return;
if (!mDragging) {
// Start dragging
mDragging = true;
onDragStart();
}
if (!mBubbleDismissController.handleTouchEvent(event)) {
// Drag the view if not processed by dismiss controller
view.setTranslationX(viewInitialX + dx);
view.setTranslationY(viewInitialY + dy);
}
}
@Override
public void onUp(@NonNull View view, @NonNull MotionEvent event, float viewInitialX,
float viewInitialY, float dx, float dy, float velX, float velY) {
onComplete(view, event, viewInitialX, viewInitialY);
}
@Override
public void onCancel(@NonNull View view, @NonNull MotionEvent event, float viewInitialX,
float viewInitialY, float dx, float dy) {
onComplete(view, event, viewInitialX, viewInitialY);
}
/**
* Prepares dismiss view for dragging.
* This method can be overridden to add extra setup on drag start
*/
protected void onDragStart() {
mBubbleDismissController.showDismissView();
}
/**
* Cleans up dismiss view after dragging.
* This method can be overridden to add extra setup on drag end
*/
protected void onDragEnd() {
mBubbleDismissController.hideDismissView();
}
/**
* Complete drag handling and clean up dependencies
*/
private void onComplete(@NonNull View view, @NonNull MotionEvent event,
float viewInitialX, float viewInitialY) {
if (!mHandling) return;
if (mDragging) {
// Stop dragging
mDragging = false;
view.setTranslationX(viewInitialX);
view.setTranslationY(viewInitialY);
onDragEnd();
}
mBubbleDismissController.handleTouchEvent(event);
mActivity.setTaskbarWindowFullscreen(false);
mHandling = false;
}
}
}

View File

@@ -661,31 +661,6 @@ public class SystemUiProxy implements ISystemUiProxy {
}
}
/**
* Tells SysUI to remove the bubble with the provided key.
* @param key the key of the bubble to show.
*/
public void removeBubble(String key) {
if (mBubbles == null) return;
try {
mBubbles.removeBubble(key);
} catch (RemoteException e) {
Log.w(TAG, "Failed call removeBubble");
}
}
/**
* Tells SysUI to remove all bubbles.
*/
public void removeAllBubbles() {
if (mBubbles == null) return;
try {
mBubbles.removeAllBubbles();
} catch (RemoteException e) {
Log.w(TAG, "Failed call removeAllBubbles");
}
}
/**
* Tells SysUI to collapse the bubbles.
*/
@@ -699,21 +674,6 @@ public class SystemUiProxy implements ISystemUiProxy {
}
}
/**
* Tells SysUI to collapse/expand selected bubble view while it's dragged.
* Should be called only when the bubble bar is expanded.
* @param bubbleKey the key of the bubble to collapse/expand
* @param collapse whether to collapse/expand selected bubble
*/
public void collapseWhileDragging(@Nullable String bubbleKey, boolean collapse) {
if (mBubbles == null) return;
try {
mBubbles.collapseWhileDragging(bubbleKey, collapse);
} catch (RemoteException e) {
Log.w(TAG, "Failed call collapseWhileDragging");
}
}
//
// Splitscreen
//