Merge "Hide overview and app icon split option when appropriate" into sc-v2-dev
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index f06447b..494b953 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1124,6 +1124,7 @@
if (target.mode == mode && target.taskInfo != null
// Compare component name instead of task-id because transitions will promote
// the target up to the root task while getTaskId returns the leaf.
+ && target.taskInfo.topActivity != null
&& target.taskInfo.topActivity.equals(mLauncher.getComponentName())) {
return true;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 5144d9a..59393d7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -243,7 +243,19 @@
if (!mTouchEnabled) {
return true;
}
- mControllerCallbacks.onTouchEvent(event);
+ if (mIconLayoutBounds.contains((int) event.getX(), (int) event.getY())) {
+ // Don't allow long pressing between icons.
+ return true;
+ }
+ if (mControllerCallbacks.onTouchEvent(event)) {
+ int oldAction = event.getAction();
+ try {
+ event.setAction(MotionEvent.ACTION_CANCEL);
+ return super.onTouchEvent(event);
+ } finally {
+ event.setAction(oldAction);
+ }
+ }
return super.onTouchEvent(event);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 40b0e18..f1748af 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -223,7 +223,11 @@
return view -> mControllers.taskbarStashController.updateAndAnimateIsStashedInApp(true);
}
- public void onTouchEvent(MotionEvent motionEvent) {
+ /**
+ * Get the first chance to handle TaskbarView#onTouchEvent, and return whether we want to
+ * consume the touch so TaskbarView treats it as an ACTION_CANCEL.
+ */
+ public boolean onTouchEvent(MotionEvent motionEvent) {
final float x = motionEvent.getRawX();
final float y = motionEvent.getRawY();
switch (motionEvent.getAction()) {
@@ -239,6 +243,7 @@
mControllers.taskbarStashController.startStashHint(
/* animateForward= */ false);
mCanceledStashHint = true;
+ return true;
}
break;
case MotionEvent.ACTION_UP:
@@ -249,6 +254,7 @@
}
break;
}
+ return false;
}
}
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 6e90a3a..4c46683 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -805,7 +805,9 @@
mActivityInitListener.unregister();
mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
- TaskViewUtils.setDividerBarShown(mRecentsAnimationTargets.nonApps, true);
+ if (mRecentsAnimationTargets != null) {
+ TaskViewUtils.setDividerBarShown(mRecentsAnimationTargets.nonApps, true);
+ }
// Defer clearing the controller and the targets until after we've updated the state
mRecentsAnimationController = null;
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index 780032e..0efe666 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -33,11 +33,8 @@
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.SystemClock;
-import android.util.Log;
import android.util.SparseIntArray;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.tracing.OverviewComponentObserverProto;
import com.android.launcher3.tracing.TouchInteractionServiceProto;
import com.android.launcher3.util.SimpleBroadcastReceiver;
@@ -132,16 +129,6 @@
private void updateOverviewTargets() {
ComponentName defaultHome = PackageManagerWrapper.getInstance()
.getHomeActivities(new ArrayList<>());
- if (TestProtocol.sDebugTracing && defaultHome == null) {
- Log.d(TestProtocol.THIRD_PARTY_LAUNCHER_NOT_SET, "getHomeActivities returned null");
- while ((defaultHome =
- PackageManagerWrapper.getInstance().getHomeActivities(new ArrayList<>()))
- == null) {
- SystemClock.sleep(10);
- }
- Log.d(TestProtocol.THIRD_PARTY_LAUNCHER_NOT_SET,
- "getHomeActivities returned non-null: " + defaultHome);
- }
mIsHomeDisabled = mDeviceState.isHomeDisabled();
mIsDefaultHome = Objects.equals(mMyHomeIntent.getComponent(), defaultHome);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 6947fc5..4420b53 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1351,23 +1351,29 @@
}
Log.d(TASK_VIEW_ID_CRASH, "taskViewCount: " + getTaskViewCount()
+ " " + sb.toString());
+ mRunningTaskViewId = -1;
+ } else {
+ mRunningTaskViewId = newRunningTaskView.getTaskViewId();
}
- mRunningTaskViewId = newRunningTaskView.getTaskViewId();
}
+ int targetPage = -1;
if (mNextPage == INVALID_PAGE) {
// Set the current page to the running task, but not if settling on new task.
if (runningTaskId != -1) {
- setCurrentPage(indexOfChild(newRunningTaskView));
+ targetPage = indexOfChild(newRunningTaskView);
} else if (getTaskViewCount() > 0) {
- setCurrentPage(indexOfChild(getTaskViewAt(0)));
+ targetPage = indexOfChild(getTaskViewAt(0));
}
} else if (currentTaskId != -1) {
currentTaskView = getTaskViewByTaskId(currentTaskId);
if (currentTaskView != null) {
- setCurrentPage(indexOfChild(currentTaskView));
+ targetPage = indexOfChild(currentTaskView);
}
}
+ if (targetPage != -1 && mCurrentPage != targetPage) {
+ setCurrentPage(targetPage);
+ }
if (mIgnoreResetTaskId != -1 &&
getTaskViewByTaskId(mIgnoreResetTaskId) != ignoreResetTaskView) {
diff --git a/res/drawable/padded_rounded_action_button.xml b/res/drawable/padded_rounded_action_button.xml
index 6432efd..6863f92 100644
--- a/res/drawable/padded_rounded_action_button.xml
+++ b/res/drawable/padded_rounded_action_button.xml
@@ -14,18 +14,11 @@
~ limitations under the License.
-->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
+ android:drawable="@drawable/rounded_action_button"
android:left="@dimen/padded_rounded_button_padding"
android:top="@dimen/padded_rounded_button_padding"
android:right="@dimen/padded_rounded_button_padding"
- android:bottom="@dimen/padded_rounded_button_padding">
- <shape android:shape="rectangle">
- <corners android:radius="@dimen/rounded_button_radius" />
- <stroke android:width="1dp"
- android:color="?androidprv:attr/colorAccentPrimaryVariant" />
- </shape>
- </item>
+ android:bottom="@dimen/padded_rounded_button_padding" />
</layer-list>
-
diff --git a/res/drawable/rounded_action_button.xml b/res/drawable/rounded_action_button.xml
index f043893..b9942c0 100644
--- a/res/drawable/rounded_action_button.xml
+++ b/res/drawable/rounded_action_button.xml
@@ -19,7 +19,9 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
<corners android:radius="@dimen/rounded_button_radius" />
- <stroke android:width="1dp" android:color="@color/all_apps_tab_background_selected" />
+ <stroke
+ android:width="1dp"
+ android:color="?androidprv:attr/colorAccentPrimaryVariant" />
<padding
android:left="@dimen/rounded_button_padding"
android:right="@dimen/rounded_button_padding" />
diff --git a/res/layout/arrow_toast.xml b/res/layout/arrow_toast.xml
index 9a6f8c3..88a92eb 100644
--- a/res/layout/arrow_toast.xml
+++ b/res/layout/arrow_toast.xml
@@ -27,15 +27,13 @@
android:gravity="center"
android:padding="16dp"
android:background="@drawable/arrow_toast_rounded_background"
- android:elevation="2dp"
- android:outlineProvider="none"
+ android:elevation="@dimen/arrow_toast_elevation"
android:textColor="@color/arrow_tip_view_content"
android:textSize="14sp"/>
<View
android:id="@+id/arrow"
- android:elevation="2dp"
- android:outlineProvider="none"
+ android:elevation="@dimen/arrow_toast_elevation"
android:layout_width="@dimen/arrow_toast_arrow_width"
android:layout_height="10dp"/>
</merge>
diff --git a/res/layout/notification_content.xml b/res/layout/notification_content.xml
index 84822a6..91897e9 100644
--- a/res/layout/notification_content.xml
+++ b/res/layout/notification_content.xml
@@ -14,10 +14,11 @@
limitations under the License.
-->
-<merge
+<com.android.launcher3.notification.NotificationMainView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
<!-- header -->
<FrameLayout
@@ -49,7 +50,7 @@
</FrameLayout>
<!-- Main view -->
- <com.android.launcher3.notification.NotificationMainView
+ <FrameLayout
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -59,7 +60,6 @@
android:id="@+id/text_and_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="?attr/popupColorPrimary"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingTop="@dimen/notification_padding"
@@ -95,5 +95,5 @@
android:layout_marginTop="@dimen/notification_padding"
android:layout_marginStart="@dimen/notification_icon_padding" />
- </com.android.launcher3.notification.NotificationMainView>
-</merge>
\ No newline at end of file
+ </FrameLayout>
+</com.android.launcher3.notification.NotificationMainView>
\ No newline at end of file
diff --git a/res/layout/popup_container.xml b/res/layout/popup_container.xml
index 18014bb..9327287 100644
--- a/res/layout/popup_container.xml
+++ b/res/layout/popup_container.xml
@@ -31,12 +31,9 @@
android:elevation="@dimen/deep_shortcuts_elevation"
android:orientation="vertical"/>
- <LinearLayout
+ <com.android.launcher3.notification.NotificationContainer
android:id="@+id/notification_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:visibility="gone"
- android:background="?attr/popupColorPrimary"
- android:elevation="@dimen/deep_shortcuts_elevation"
- android:orientation="vertical"/>
+ android:visibility="gone"/>
</com.android.launcher3.popup.PopupContainerWithArrow>
\ No newline at end of file
diff --git a/res/layout/system_shortcut.xml b/res/layout/system_shortcut.xml
index 89895e5..21d532e 100644
--- a/res/layout/system_shortcut.xml
+++ b/res/layout/system_shortcut.xml
@@ -17,7 +17,8 @@
<com.android.launcher3.shortcuts.DeepShortcutView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/bg_popup_item_width"
- android:layout_height="@dimen/bg_popup_item_height"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/bg_popup_item_height"
android:elevation="@dimen/deep_shortcuts_elevation"
android:background="@drawable/middle_item_primary"
android:theme="@style/PopupItem" >
diff --git a/res/layout/system_shortcut_content.xml b/res/layout/system_shortcut_content.xml
index 8b39202..3ef0b94 100644
--- a/res/layout/system_shortcut_content.xml
+++ b/res/layout/system_shortcut_content.xml
@@ -22,6 +22,9 @@
android:id="@+id/bubble_text"
android:background="?android:attr/selectableItemBackground"
android:gravity="start|center_vertical"
+ android:paddingTop="@dimen/bg_popup_item_vertical_padding"
+ android:paddingBottom="@dimen/bg_popup_item_vertical_padding"
+ android:minHeight="@dimen/bg_popup_item_height"
android:textAlignment="viewStart"
android:paddingStart="@dimen/deep_shortcuts_text_padding_start"
android:paddingEnd="@dimen/popup_padding_end"
diff --git a/res/layout/work_apps_paused.xml b/res/layout/work_apps_paused.xml
index ec34b47..79bce70 100644
--- a/res/layout/work_apps_paused.xml
+++ b/res/layout/work_apps_paused.xml
@@ -28,7 +28,7 @@
android:layout_marginTop="40dp"
android:text="@string/work_apps_paused_title"
android:textAlignment="center"
- android:textSize="22sp" />
+ android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
diff --git a/res/values/config.xml b/res/values/config.xml
index 04c359e..72959b2 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -34,6 +34,9 @@
<!-- View tag key used to determine if we should fade in the child views.. -->
<string name="popup_container_iterate_children" translatable="false">popup_container_iterate_children</string>
+ <!-- config used to determine if header protection is supported in AllApps -->
+ <bool name="config_header_protection_supported">false</bool>
+
<!-- Workspace -->
<!-- The duration (in ms) of the fade animation on the object outlines, used when
we are dragging objects around on the home screen. -->
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 86b4e71..5fc0480 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -110,6 +110,7 @@
<dimen name="all_apps_tip_bottom_margin">8dp</dimen>
<!-- The size of corner radius of the arrow in the arrow toast. -->
<dimen name="arrow_toast_corner_radius">2dp</dimen>
+ <dimen name="arrow_toast_elevation">2dp</dimen>
<dimen name="arrow_toast_arrow_width">10dp</dimen>
<!-- Search bar in All Apps -->
@@ -240,6 +241,7 @@
<dimen name="bg_popup_padding">2dp</dimen>
<dimen name="bg_popup_item_width">216dp</dimen>
<dimen name="bg_popup_item_height">56dp</dimen>
+ <dimen name="bg_popup_item_vertical_padding">12dp</dimen>
<dimen name="pre_drag_view_scale">6dp</dimen>
<!-- an icon with shortcuts must be dragged this far before the container is removed. -->
<dimen name="deep_shortcuts_start_drag_threshold">16dp</dimen>
@@ -270,6 +272,8 @@
<!-- Notifications -->
<dimen name="bg_round_rect_radius">8dp</dimen>
+ <dimen name="notification_max_trans">8dp</dimen>
+ <dimen name="notification_space">8dp</dimen>
<dimen name="notification_padding">16dp</dimen>
<dimen name="notification_padding_top">18dp</dimen>
<dimen name="notification_header_text_size">14sp</dimen>
@@ -346,4 +350,5 @@
<dimen name="search_row_icon_size">48dp</dimen>
<dimen name="search_row_small_icon_size">32dp</dimen>
<dimen name="padded_rounded_button_padding">8dp</dimen>
+
</resources>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 02ec5e8..e52d1be 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -409,6 +409,10 @@
* Returns true if the touch down at the provided position be ignored
*/
protected boolean shouldIgnoreTouchDown(float x, float y) {
+ if (mDisplay == DISPLAY_TASKBAR) {
+ // Allow touching within padding on taskbar, given icon sizes are smaller.
+ return false;
+ }
return y < getPaddingTop()
|| x < getPaddingLeft()
|| y > getHeight() - getPaddingBottom()
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 88f6c49..eb42a65 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
@@ -32,10 +33,13 @@
import android.view.ViewPropertyAnimator;
import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragController.DragListener;
import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.testing.TestProtocol;
/*
* The top bar containing various drop targets: Delete/App Info/Uninstall.
@@ -212,6 +216,9 @@
}
public void animateToVisibility(boolean isVisible) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_DROP_TARGET, "8");
+ }
if (mVisible != isVisible) {
mVisible = isVisible;
@@ -238,6 +245,9 @@
*/
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_DROP_TARGET, "7");
+ }
animateToVisibility(true);
}
@@ -261,4 +271,12 @@
public ButtonDropTarget[] getDropTargets() {
return mDropTargets;
}
+
+ @Override
+ protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ if (TestProtocol.sDebugTracing && visibility == VISIBLE) {
+ Log.d(TestProtocol.NO_DROP_TARGET, "9");
+ }
+ }
}
diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java
index a4e1af6..21bc479 100644
--- a/src/com/android/launcher3/ExtendedEditText.java
+++ b/src/com/android/launcher3/ExtendedEditText.java
@@ -99,8 +99,18 @@
}
}
- // inherited class can override to change the appearance of the edit text.
- public void show() {}
+ /**
+ * Sets whether EditText background should be visible
+ * @param maxAlpha defines the maximum alpha the background should animates to
+ */
+ public void setBackgroundVisibility(boolean visible, float maxAlpha) {}
+
+ /**
+ * Returns whether a visible background is set on EditText
+ */
+ public boolean getBackgroundVisibility() {
+ return getBackground() != null;
+ }
public void showKeyboard() {
mShowImeAfterFirstLayout = !showSoftInput();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3754dc1..94dbe00 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -555,6 +555,14 @@
}
@Override
+ public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
+ super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ // Always update device profile when multi window mode changed.
+ initDeviceProfile(mDeviceProfile.inv);
+ dispatchDeviceProfileChanged();
+ }
+
+ @Override
public void onConfigurationChanged(Configuration newConfig) {
int diff = newConfig.diff(mOldConfig);
if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
@@ -592,11 +600,9 @@
private void initDeviceProfile(InvariantDeviceProfile idp) {
// Load configuration-specific DeviceProfile
- mDeviceProfile = idp.getDeviceProfile(this);
- if (isInMultiWindowMode()) {
- mDeviceProfile = mDeviceProfile.getMultiWindowProfile(
- this, getMultiWindowDisplaySize());
- }
+ mDeviceProfile = isInMultiWindowMode()
+ ? mDeviceProfile.getMultiWindowProfile(this, getMultiWindowDisplaySize())
+ : idp.getDeviceProfile(this);
onDeviceProfileInitiated();
mModelWriter = mModel.getWriter(getDeviceProfile().isVerticalBarLayout(), true, this);
@@ -1195,7 +1201,7 @@
// Until the workspace is bound, ensure that we keep the wallpaper offset locked to the
// default state, otherwise we will update to the wrong offsets in RTL
mWorkspace.lockWallpaperToDefaultPage();
- mWorkspace.bindAndInitFirstWorkspaceScreen(null /* recycled qsb */);
+ mWorkspace.bindAndInitFirstWorkspaceScreen();
mDragController.addDragListener(mWorkspace);
// Get the search/delete/uninstall bar
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 696e897..2f9b5af 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -1046,7 +1046,7 @@
/**
* If being flinged and user touches the screen, initiate drag; otherwise don't.
*/
- private void updateIsBeingDraggedOnTouchDown(MotionEvent ev) {
+ protected void updateIsBeingDraggedOnTouchDown(MotionEvent ev) {
// mScroller.isFinished should be false when being flinged.
final int xDist = Math.abs(mScroller.getFinalX() - mScroller.getCurrX());
final boolean finishedScrolling = (mScroller.isFinished() || xDist < mPageSlop / 3);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 94ec903..b197e1c 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -223,6 +223,9 @@
// Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget)
private float mXDown;
private float mYDown;
+ private View mQsb;
+ private boolean mIsEventOverQsb;
+
final static float START_DAMPING_TOUCH_SLOP_ANGLE = (float) Math.PI / 6;
final static float MAX_SWIPE_ANGLE = (float) Math.PI / 3;
final static float TOUCH_SLOP_DAMPING_FACTOR = 4;
@@ -548,9 +551,8 @@
/**
* Initializes and binds the first page
- * @param qsb an existing qsb to recycle or null.
*/
- public void bindAndInitFirstWorkspaceScreen(View qsb) {
+ public void bindAndInitFirstWorkspaceScreen() {
if (!FeatureFlags.QSB_ON_FIRST_SCREEN) {
return;
}
@@ -558,10 +560,10 @@
// Add the first page
CellLayout firstPage = insertNewWorkspaceScreen(Workspace.FIRST_SCREEN_ID, getChildCount());
// Always add a QSB on the first screen.
- if (qsb == null) {
+ if (mQsb == null) {
// In transposed layout, we add the QSB in the Grid. As workspace does not touch the
// edges, we do not need a full width QSB.
- qsb = LayoutInflater.from(getContext())
+ mQsb = LayoutInflater.from(getContext())
.inflate(R.layout.search_container_workspace, firstPage, false);
}
@@ -570,8 +572,9 @@
CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, firstPage.getCountX(),
cellVSpan);
lp.canReorder = false;
- if (!firstPage.addViewToCellLayout(qsb, 0, R.id.search_container_workspace, lp, true)) {
+ if (!firstPage.addViewToCellLayout(mQsb, 0, R.id.search_container_workspace, lp, true)) {
Log.e(TAG, "Failed to add to item at (0, 0) to CellLayout");
+ mQsb = null;
}
}
@@ -581,9 +584,8 @@
disableLayoutTransitions();
// Recycle the QSB widget
- View qsb = findViewById(R.id.search_container_workspace);
- if (qsb != null) {
- ((ViewGroup) qsb.getParent()).removeView(qsb);
+ if (mQsb != null) {
+ ((ViewGroup) mQsb.getParent()).removeView(mQsb);
}
// Remove the pages and clear the screen models
@@ -596,7 +598,7 @@
mLauncher.mHandler.removeCallbacksAndMessages(DeferredWidgetRefresh.class);
// Ensure that the first page is always present
- bindAndInitFirstWorkspaceScreen(qsb);
+ bindAndInitFirstWorkspaceScreen();
// Re-enable the layout transitions
enableLayoutTransitions();
@@ -922,17 +924,25 @@
}
@Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
- mXDown = ev.getX();
- mYDown = ev.getY();
+ protected void updateIsBeingDraggedOnTouchDown(MotionEvent ev) {
+ super.updateIsBeingDraggedOnTouchDown(ev);
+
+ mXDown = ev.getX();
+ mYDown = ev.getY();
+ if (mQsb != null) {
+ mTempFXY[0] = mXDown + getScrollX();
+ mTempFXY[1] = mYDown + getScrollY();
+ Utilities.mapCoordInSelfToDescendant(mQsb, this, mTempFXY);
+ mIsEventOverQsb = mQsb.getLeft() <= mTempFXY[0] && mQsb.getRight() >= mTempFXY[0]
+ && mQsb.getTop() <= mTempFXY[1] && mQsb.getBottom() >= mTempFXY[1];
+ } else {
+ mIsEventOverQsb = false;
}
- return super.onInterceptTouchEvent(ev);
}
@Override
protected void determineScrollingStart(MotionEvent ev) {
- if (!isFinishedSwitchingState()) return;
+ if (!isFinishedSwitchingState() || mIsEventOverQsb) return;
float deltaX = ev.getX() - mXDown;
float absDeltaX = Math.abs(deltaX);
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 9c61c1b..57a3e1c 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -59,6 +59,7 @@
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.Insettable;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.R;
@@ -118,7 +119,7 @@
private SpannableStringBuilder mSearchQueryBuilder = null;
protected boolean mUsingTabs;
- private boolean mSearchModeWhileUsingTabs = false;
+ private boolean mIsSearching;
protected RecyclerViewFastScroller mTouchHandler;
protected final Point mFastScrollerOffset = new Point();
@@ -132,6 +133,7 @@
private final float mHeaderThreshold;
private ScrimView mScrimView;
private int mHeaderColor;
+ private int mTabsProtectionAlpha;
public AllAppsContainerView(Context context) {
this(context, null);
@@ -625,18 +627,19 @@
for (int i = 0; i < mAH.length; i++) {
mAH[i].adapter.setLastSearchQuery(query);
}
+ mIsSearching = true;
if (mUsingTabs) {
- mSearchModeWhileUsingTabs = true;
rebindAdapters(false); // hide tabs
}
mHeader.setCollapsed(true);
}
public void onClearSearchResult() {
- if (mSearchModeWhileUsingTabs) {
+ if (mUsingTabs) {
rebindAdapters(true); // show tabs
- mSearchModeWhileUsingTabs = false;
}
+ mIsSearching = false;
+ getActiveRecyclerView().scrollToTop();
}
public void onSearchResultsChanged() {
@@ -710,13 +713,12 @@
mHeaderPaint.setColor(mHeaderColor);
mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
- int bottom = mUsingTabs && mHeader.mHeaderCollapsed ? mHeader.getVisibleBottomBound()
- : mSearchContainer.getBottom();
- canvas.drawRect(0, 0, canvas.getWidth(), bottom + getTranslationY(),
- mHeaderPaint);
-
- if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && getTranslationY() == 0) {
- mSearchUiManager.getEditText().setBackground(null);
+ int bottom = (int) (mSearchContainer.getBottom() + getTranslationY());
+ canvas.drawRect(0, 0, canvas.getWidth(), bottom, mHeaderPaint);
+ int tabsHeight = getFloatingHeaderView().getPeripheralProtectionHeight();
+ if (mTabsProtectionAlpha > 0 && tabsHeight != 0) {
+ mHeaderPaint.setAlpha((int) (getAlpha() * mTabsProtectionAlpha));
+ canvas.drawRect(0, bottom, canvas.getWidth(), bottom + tabsHeight, mHeaderPaint);
}
}
}
@@ -796,18 +798,29 @@
protected void updateHeaderScroll(int scrolledOffset) {
- float prog = Math.max(0, Math.min(1, (float) scrolledOffset / mHeaderThreshold));
+
+ float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
int viewBG = ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, prog);
int headerColor = ColorUtils.setAlphaComponent(viewBG,
(int) (getSearchView().getAlpha() * 255));
- if (headerColor != mHeaderColor) {
+ int tabsAlpha = mHeader.getPeripheralProtectionHeight() == 0 ? 0
+ : (int) (Utilities.boundToRange(
+ (scrolledOffset + mHeader.mSnappedScrolledY) / mHeaderThreshold, 0f, 1f)
+ * 255);
+ if (headerColor != mHeaderColor || mTabsProtectionAlpha != tabsAlpha) {
mHeaderColor = headerColor;
- getSearchView().setBackgroundColor(viewBG);
- getFloatingHeaderView().setHeaderColor(viewBG);
+ mTabsProtectionAlpha = tabsAlpha;
invalidateHeader();
- if (scrolledOffset == 0 && mSearchUiManager.getEditText() != null) {
- mSearchUiManager.getEditText().show();
+ }
+ if (mSearchUiManager.getEditText() != null) {
+ ExtendedEditText editText = mSearchUiManager.getEditText();
+ boolean bgVisible = editText.getBackgroundVisibility();
+ if (scrolledOffset == 0 && !mIsSearching) {
+ bgVisible = true;
+ } else if (scrolledOffset > mHeaderThreshold) {
+ bgVisible = false;
}
+ editText.setBackgroundVisibility(bgVisible, 1 - prog);
}
}
@@ -815,7 +828,7 @@
* redraws header protection
*/
public void invalidateHeader() {
- if (mScrimView != null && FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ if (mScrimView != null && mHeader.isHeaderProtectionSupported()) {
mScrimView.invalidate();
}
}
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 8ea83d5..debb5b2 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -17,9 +17,6 @@
import android.animation.ValueAnimator;
import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.ArrayMap;
@@ -50,11 +47,10 @@
ValueAnimator.AnimatorUpdateListener, PluginListener<AllAppsRow>, Insettable,
OnHeightUpdatedListener {
- private final Rect mClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ private final Rect mRVClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ private final Rect mHeaderClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
- private final ValueAnimator mHeaderAnimator = ValueAnimator.ofInt(0, 1).setDuration(100);
private final Point mTempOffset = new Point();
- private final Paint mBGPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final RecyclerView.OnScrollListener mOnScrollListener =
new RecyclerView.OnScrollListener() {
@Override
@@ -82,19 +78,19 @@
}
};
- private final int mHeaderTopPadding;
-
protected final Map<AllAppsRow, PluginHeaderRow> mPluginRows = new ArrayMap<>();
+ private final int mHeaderTopPadding;
+ private final boolean mHeaderProtectionSupported;
+
protected ViewGroup mTabLayout;
private AllAppsRecyclerView mMainRV;
private AllAppsRecyclerView mWorkRV;
private AllAppsRecyclerView mCurrentRV;
private ViewGroup mParent;
public boolean mHeaderCollapsed;
- private int mSnappedScrolledY;
+ protected int mSnappedScrolledY;
private int mTranslationY;
- private int mHeaderColor;
private boolean mForwardToRecyclerView;
@@ -120,6 +116,8 @@
super(context, attrs);
mHeaderTopPadding = context.getResources()
.getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
+ mHeaderProtectionSupported = context.getResources().getBoolean(
+ R.bool.config_header_protection_supported);
}
@Override
@@ -138,7 +136,6 @@
}
mFixedRows = rows.toArray(new FloatingHeaderRow[rows.size()]);
mAllRows = mFixedRows;
- mHeaderAnimator.addUpdateListener(valueAnimator -> invalidate());
}
@Override
@@ -285,7 +282,7 @@
mHeaderCollapsed = false;
}
mTranslationY = currentScrollY;
- } else if (!mHeaderCollapsed) {
+ } else {
mTranslationY = currentScrollY - mSnappedScrolledY - mMaxTranslation;
// update state vars
@@ -295,31 +292,10 @@
} else if (mTranslationY <= -mMaxTranslation) { // hide or stay hidden
mHeaderCollapsed = true;
mSnappedScrolledY = -mMaxTranslation;
- mHeaderAnimator.setCurrentFraction(0);
- mHeaderAnimator.start();
}
}
}
- /**
- * Set current header protection background color
- */
- public void setHeaderColor(int color) {
- mHeaderColor = color;
- invalidate();
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- if (mHeaderCollapsed && !mCollapsed && mTabLayout.getVisibility() == VISIBLE
- && mHeaderColor != Color.TRANSPARENT && FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
- mBGPaint.setColor(mHeaderColor);
- mBGPaint.setAlpha((int) (255 * mHeaderAnimator.getAnimatedFraction()));
- canvas.drawRect(0, 0, getWidth(), getHeight() + mTranslationY, mBGPaint);
- }
- super.dispatchDraw(canvas);
- }
-
protected void applyVerticalMove() {
int uncappedTranslationY = mTranslationY;
mTranslationY = Math.max(mTranslationY, -mMaxTranslation);
@@ -336,11 +312,15 @@
}
mTabLayout.setTranslationY(mTranslationY);
- mClip.top = mMaxTranslation + mTranslationY;
+
+ int clipHeight = mHeaderTopPadding - getPaddingBottom();
+ mRVClip.top = mTabsHidden ? clipHeight : 0;
+ mHeaderClip.top = clipHeight;
// clipping on a draw might cause additional redraw
- mMainRV.setClipBounds(mClip);
+ setClipBounds(mHeaderClip);
+ mMainRV.setClipBounds(mRVClip);
if (mWorkRV != null) {
- mWorkRV.setClipBounds(mClip);
+ mWorkRV.setClipBounds(mRVClip);
}
}
@@ -421,6 +401,10 @@
return false;
}
+ public boolean isHeaderProtectionSupported() {
+ return mHeaderProtectionSupported;
+ }
+
@Override
public boolean hasOverlappingRendering() {
return false;
@@ -444,10 +428,19 @@
}
/**
- * Returns visible height of FloatingHeaderView contents
+ * Returns visible height of FloatingHeaderView contents requiring header protection
*/
- public int getVisibleBottomBound() {
- return getBottom() + mTranslationY;
+ public int getPeripheralProtectionHeight() {
+ if (!mHeaderProtectionSupported) {
+ return 0;
+ }
+
+ // we only want to show protection when work tab is available and header is either
+ // collapsed or animating to/from collapsed state
+ if (mTabsHidden || !mHeaderCollapsed) {
+ return 0;
+ }
+ return Math.max(getHeight() - getPaddingTop() + mTranslationY, 0);
}
}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 1e0edac..fdb2799 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -22,6 +22,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.util.Log;
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -34,6 +35,7 @@
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.ActivityContext;
@@ -146,6 +148,9 @@
float initialDragViewScale,
float dragViewScaleOnDrop,
DragOptions options) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_DROP_TARGET, "4");
+ }
return startDrag(drawable, /* view= */ null, originalView, dragLayerX, dragLayerY,
source, dragInfo, dragOffset, dragRegion, initialDragViewScale, dragViewScaleOnDrop,
options);
@@ -203,6 +208,9 @@
DragOptions options);
protected void callOnDragStart() {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_DROP_TARGET, "6");
+ }
if (mOptions.preDragCondition != null) {
mOptions.preDragCondition.onPreDragEnd(mDragObject, true /* dragStarted*/);
}
diff --git a/src/com/android/launcher3/dragndrop/LauncherDragController.java b/src/com/android/launcher3/dragndrop/LauncherDragController.java
index 0e8b0a5..dcbfa50 100644
--- a/src/com/android/launcher3/dragndrop/LauncherDragController.java
+++ b/src/com/android/launcher3/dragndrop/LauncherDragController.java
@@ -24,6 +24,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.View;
@@ -36,6 +37,7 @@
import com.android.launcher3.R;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.testing.TestProtocol;
/**
* Drag controller for Launcher activity
@@ -65,6 +67,9 @@
float initialDragViewScale,
float dragViewScaleOnDrop,
DragOptions options) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_DROP_TARGET, "5");
+ }
if (PROFILE_DRAWING_DURING_DRAG) {
android.os.Debug.startMethodTracing("Launcher");
}
diff --git a/src/com/android/launcher3/notification/NotificationContainer.java b/src/com/android/launcher3/notification/NotificationContainer.java
new file mode 100644
index 0000000..9eb05cd
--- /dev/null
+++ b/src/com/android/launcher3/notification/NotificationContainer.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2021 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.notification;
+
+import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.FloatProperty;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.R;
+import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.popup.PopupContainerWithArrow;
+import com.android.launcher3.touch.BaseSwipeDetector;
+import com.android.launcher3.touch.OverScroll;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Class to manage the notification UI in a {@link PopupContainerWithArrow}.
+ *
+ * - Has two {@link NotificationMainView} that represent the top two notifications
+ * - Handles dismissing a notification
+ */
+public class NotificationContainer extends FrameLayout implements SingleAxisSwipeDetector.Listener {
+
+ private static final FloatProperty<NotificationContainer> DRAG_TRANSLATION_X =
+ new FloatProperty<NotificationContainer>("notificationProgress") {
+ @Override
+ public void setValue(NotificationContainer view, float transX) {
+ view.setDragTranslationX(transX);
+ }
+
+ @Override
+ public Float get(NotificationContainer view) {
+ return view.mDragTranslationX;
+ }
+ };
+
+ private static final Rect sTempRect = new Rect();
+
+ private final SingleAxisSwipeDetector mSwipeDetector;
+ private final List<NotificationInfo> mNotificationInfos = new ArrayList<>();
+ private boolean mIgnoreTouch = false;
+
+ private final ObjectAnimator mContentTranslateAnimator;
+ private float mDragTranslationX = 0;
+
+ private final NotificationMainView mPrimaryView;
+ private final NotificationMainView mSecondaryView;
+ private PopupContainerWithArrow mPopupContainer;
+
+ public NotificationContainer(Context context) {
+ this(context, null, 0);
+ }
+
+ public NotificationContainer(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public NotificationContainer(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mSwipeDetector = new SingleAxisSwipeDetector(getContext(), this, HORIZONTAL);
+ mSwipeDetector.setDetectableScrollConditions(SingleAxisSwipeDetector.DIRECTION_BOTH, false);
+ mContentTranslateAnimator = ObjectAnimator.ofFloat(this, DRAG_TRANSLATION_X, 0);
+
+ mPrimaryView = (NotificationMainView) View.inflate(getContext(),
+ R.layout.notification_content, null);
+ mSecondaryView = (NotificationMainView) View.inflate(getContext(),
+ R.layout.notification_content, null);
+ mSecondaryView.setAlpha(0);
+
+ addView(mSecondaryView);
+ addView(mPrimaryView);
+
+ }
+
+ public void setPopupView(PopupContainerWithArrow popupView) {
+ mPopupContainer = popupView;
+ }
+
+ /**
+ * Returns true if we should intercept the swipe.
+ */
+ public boolean onInterceptSwipeEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ sTempRect.set(getLeft(), getTop(), getRight(), getBottom());
+ mIgnoreTouch = !sTempRect.contains((int) ev.getX(), (int) ev.getY());
+ if (!mIgnoreTouch) {
+ mPopupContainer.getParent().requestDisallowInterceptTouchEvent(true);
+ }
+ }
+ if (mIgnoreTouch) {
+ return false;
+ }
+ if (mPrimaryView.getNotificationInfo() == null) {
+ // The notification hasn't been populated yet.
+ return false;
+ }
+
+ mSwipeDetector.onTouchEvent(ev);
+ return mSwipeDetector.isDraggingOrSettling();
+ }
+
+ /**
+ * Returns true when we should handle the swipe.
+ */
+ public boolean onSwipeEvent(MotionEvent ev) {
+ if (mIgnoreTouch) {
+ return false;
+ }
+ if (mPrimaryView.getNotificationInfo() == null) {
+ // The notification hasn't been populated yet.
+ return false;
+ }
+ return mSwipeDetector.onTouchEvent(ev);
+ }
+
+ /**
+ * Applies the list of @param notificationInfos to this container.
+ */
+ public void applyNotificationInfos(final List<NotificationInfo> notificationInfos) {
+ mNotificationInfos.clear();
+ if (notificationInfos.isEmpty()) {
+ mPrimaryView.applyNotificationInfo(null);
+ mSecondaryView.applyNotificationInfo(null);
+ return;
+ }
+ mNotificationInfos.addAll(notificationInfos);
+
+ NotificationInfo mainNotification = notificationInfos.get(0);
+ mPrimaryView.applyNotificationInfo(mainNotification);
+ mSecondaryView.applyNotificationInfo(notificationInfos.size() > 1
+ ? notificationInfos.get(1)
+ : null);
+ }
+
+ /**
+ * Trims the notifications.
+ * @param notificationKeys List of all valid notification keys.
+ */
+ public void trimNotifications(final List<String> notificationKeys) {
+ Iterator<NotificationInfo> iterator = mNotificationInfos.iterator();
+ while (iterator.hasNext()) {
+ if (!notificationKeys.contains(iterator.next().notificationKey)) {
+ iterator.remove();
+ }
+ }
+
+ NotificationInfo primaryInfo = mNotificationInfos.size() > 0
+ ? mNotificationInfos.get(0)
+ : null;
+ NotificationInfo secondaryInfo = mNotificationInfos.size() > 1
+ ? mNotificationInfos.get(1)
+ : null;
+
+ mPrimaryView.applyNotificationInfo(primaryInfo);
+ mSecondaryView.applyNotificationInfo(secondaryInfo);
+
+ mPrimaryView.onPrimaryDrag(0);
+ mSecondaryView.onSecondaryDrag(0);
+ }
+
+ private void setDragTranslationX(float translationX) {
+ mDragTranslationX = translationX;
+
+ float progress = translationX / getWidth();
+ mPrimaryView.onPrimaryDrag(progress);
+ if (mSecondaryView.getNotificationInfo() == null) {
+ mSecondaryView.setAlpha(0f);
+ } else {
+ mSecondaryView.onSecondaryDrag(progress);
+ }
+ }
+
+ // SingleAxisSwipeDetector.Listener's
+ @Override
+ public void onDragStart(boolean start, float startDisplacement) {
+ mPopupContainer.showArrow(false);
+ }
+
+ @Override
+ public boolean onDrag(float displacement) {
+ if (!mPrimaryView.canChildBeDismissed()) {
+ displacement = OverScroll.dampedScroll(displacement, getWidth());
+ }
+
+ float progress = displacement / getWidth();
+ mPrimaryView.onPrimaryDrag(progress);
+ if (mSecondaryView.getNotificationInfo() == null) {
+ mSecondaryView.setAlpha(0f);
+ } else {
+ mSecondaryView.onSecondaryDrag(progress);
+ }
+ mContentTranslateAnimator.cancel();
+ return true;
+ }
+
+ @Override
+ public void onDragEnd(float velocity) {
+ final boolean willExit;
+ final float endTranslation;
+ final float startTranslation = mPrimaryView.getTranslationX();
+ final float width = getWidth();
+
+ if (!mPrimaryView.canChildBeDismissed()) {
+ willExit = false;
+ endTranslation = 0;
+ } else if (mSwipeDetector.isFling(velocity)) {
+ willExit = true;
+ endTranslation = velocity < 0 ? -width : width;
+ } else if (Math.abs(startTranslation) > width / 2f) {
+ willExit = true;
+ endTranslation = (startTranslation < 0 ? -width : width);
+ } else {
+ willExit = false;
+ endTranslation = 0;
+ }
+
+ long duration = BaseSwipeDetector.calculateDuration(velocity,
+ (endTranslation - startTranslation) / width);
+
+ mContentTranslateAnimator.removeAllListeners();
+ mContentTranslateAnimator.setDuration(duration)
+ .setInterpolator(scrollInterpolatorForVelocity(velocity));
+ mContentTranslateAnimator.setFloatValues(startTranslation, endTranslation);
+
+ NotificationMainView current = mPrimaryView;
+ mContentTranslateAnimator.addListener(new AnimationSuccessListener() {
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ mSwipeDetector.finishedScrolling();
+ if (willExit) {
+ current.onChildDismissed();
+ }
+ mPopupContainer.showArrow(true);
+ }
+ });
+ mContentTranslateAnimator.start();
+ }
+
+ /**
+ * Animates the background color to a new color.
+ * @param color The color to change to.
+ * @param animatorSetOut The AnimatorSet where we add the color animator to.
+ */
+ public void updateBackgroundColor(int color, AnimatorSet animatorSetOut) {
+ mPrimaryView.updateBackgroundColor(color, animatorSetOut);
+ mSecondaryView.updateBackgroundColor(color, animatorSetOut);
+ }
+
+ /**
+ * Updates the header with a new @param notificationCount.
+ */
+ public void updateHeader(int notificationCount) {
+ mPrimaryView.updateHeader(notificationCount);
+ mSecondaryView.updateHeader(notificationCount - 1);
+ }
+}
diff --git a/src/com/android/launcher3/notification/NotificationItemView.java b/src/com/android/launcher3/notification/NotificationItemView.java
deleted file mode 100644
index af943a6..0000000
--- a/src/com/android/launcher3/notification/NotificationItemView.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2017 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.notification;
-
-import android.animation.AnimatorSet;
-import android.content.Context;
-import android.graphics.Outline;
-import android.graphics.Rect;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.MarginLayoutParams;
-import android.view.ViewOutlineProvider;
-import android.widget.TextView;
-
-import com.android.launcher3.R;
-import com.android.launcher3.popup.PopupContainerWithArrow;
-import com.android.launcher3.util.Themes;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Utility class to manage notification UI
- */
-public class NotificationItemView {
-
- private static final Rect sTempRect = new Rect();
-
- private final Context mContext;
- private final PopupContainerWithArrow mPopupContainer;
- private final ViewGroup mRootView;
-
- private final TextView mHeaderCount;
- private final NotificationMainView mMainView;
-
- private final View mHeader;
-
- private View mGutter;
-
- private boolean mIgnoreTouch = false;
- private List<NotificationInfo> mNotificationInfos = new ArrayList<>();
-
- public NotificationItemView(PopupContainerWithArrow container, ViewGroup rootView) {
- mPopupContainer = container;
- mRootView = rootView;
- mContext = container.getContext();
-
- mHeaderCount = container.findViewById(R.id.notification_count);
- mMainView = container.findViewById(R.id.main_view);
-
- mHeader = container.findViewById(R.id.header);
-
- float radius = Themes.getDialogCornerRadius(mContext);
- rootView.setClipToOutline(true);
- rootView.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), radius);
- }
- });
- }
-
- /**
- * Animates the background color to a new color.
- * @param color The color to change to.
- * @param animatorSetOut The AnimatorSet where we add the color animator to.
- */
- public void updateBackgroundColor(int color, AnimatorSet animatorSetOut) {
- mMainView.updateBackgroundColor(color, animatorSetOut);
- }
-
- public void addGutter() {
- if (mGutter == null) {
- mGutter = mPopupContainer.inflateAndAdd(R.layout.notification_gutter, mRootView);
- }
- }
-
- public void inverseGutterMargin() {
- MarginLayoutParams lp = (MarginLayoutParams) mGutter.getLayoutParams();
- int top = lp.topMargin;
- lp.topMargin = lp.bottomMargin;
- lp.bottomMargin = top;
- }
-
- public void removeAllViews() {
- mRootView.removeView(mMainView);
- mRootView.removeView(mHeader);
- if (mGutter != null) {
- mRootView.removeView(mGutter);
- }
- }
-
- /**
- * Updates the header text.
- * @param notificationCount The number of notifications.
- */
- public void updateHeader(int notificationCount) {
- final String text;
- final int visibility;
- if (notificationCount <= 1) {
- text = "";
- visibility = View.INVISIBLE;
- } else {
- text = String.valueOf(notificationCount);
- visibility = View.VISIBLE;
-
- }
- mHeaderCount.setText(text);
- mHeaderCount.setVisibility(visibility);
- }
-
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- sTempRect.set(mRootView.getLeft(), mRootView.getTop(),
- mRootView.getRight(), mRootView.getBottom());
- mIgnoreTouch = !sTempRect.contains((int) ev.getX(), (int) ev.getY());
- if (!mIgnoreTouch) {
- mPopupContainer.getParent().requestDisallowInterceptTouchEvent(true);
- }
- }
- if (mIgnoreTouch) {
- return false;
- }
- if (mMainView.getNotificationInfo() == null) {
- // The notification hasn't been populated yet.
- return false;
- }
-
- return false;
- }
-
- public void applyNotificationInfos(final List<NotificationInfo> notificationInfos) {
- mNotificationInfos.clear();
- if (notificationInfos.isEmpty()) {
- return;
- }
- mNotificationInfos.addAll(notificationInfos);
-
- NotificationInfo mainNotification = notificationInfos.get(0);
- mMainView.applyNotificationInfo(mainNotification, false);
- }
-
- public void trimNotifications(final List<String> notificationKeys) {
- NotificationInfo currentMainNotificationInfo = mMainView.getNotificationInfo();
- boolean shouldUpdateMainNotification = !notificationKeys.contains(
- currentMainNotificationInfo.notificationKey);
-
- if (shouldUpdateMainNotification) {
- int size = notificationKeys.size();
- NotificationInfo nextNotification = null;
- // We get the latest notification by finding the notification after the one that was
- // just dismissed.
- for (int i = 0; i < size; ++i) {
- if (currentMainNotificationInfo == mNotificationInfos.get(i) && i + 1 < size) {
- nextNotification = mNotificationInfos.get(i + 1);
- break;
- }
- }
- if (nextNotification != null) {
- mMainView.applyNotificationInfo(nextNotification, true);
- }
- }
- }
-}
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index b8aa824..f9ff8a6 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -16,62 +16,70 @@
package com.android.launcher3.notification;
+import static com.android.launcher3.Utilities.mapToRange;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DISMISSED;
import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.FloatProperty;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.FrameLayout;
+import android.view.ViewOutlineProvider;
+import android.widget.LinearLayout;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.touch.SingleAxisSwipeDetector;
+import com.android.launcher3.util.Themes;
/**
* A {@link android.widget.FrameLayout} that contains a single notification,
* e.g. icon + title + text.
*/
@TargetApi(Build.VERSION_CODES.N)
-public class NotificationMainView extends FrameLayout {
-
- private static final FloatProperty<NotificationMainView> CONTENT_TRANSLATION =
- new FloatProperty<NotificationMainView>("contentTranslation") {
- @Override
- public void setValue(NotificationMainView view, float v) {
- view.setContentTranslation(v);
- }
-
- @Override
- public Float get(NotificationMainView view) {
- return view.mTextAndBackground.getTranslationX();
- }
- };
+public class NotificationMainView extends LinearLayout {
// This is used only to track the notification view, so that it can be properly logged.
public static final ItemInfo NOTIFICATION_ITEM_INFO = new ItemInfo();
+ // Value when the primary notification main view will be gone (zero alpha).
+ private static final float PRIMARY_GONE_PROGRESS = 0.7f;
+ private static final float PRIMARY_MIN_PROGRESS = 0.40f;
+ private static final float PRIMARY_MAX_PROGRESS = 0.60f;
+ private static final float SECONDARY_MIN_PROGRESS = 0.30f;
+ private static final float SECONDARY_MAX_PROGRESS = 0.50f;
+ private static final float SECONDARY_CONTENT_MAX_PROGRESS = 0.6f;
+
private NotificationInfo mNotificationInfo;
- private ViewGroup mTextAndBackground;
private int mBackgroundColor;
private TextView mTitleView;
private TextView mTextView;
private View mIconView;
- private SingleAxisSwipeDetector mSwipeDetector;
+ private View mHeader;
+ private View mMainView;
- private final ColorDrawable mColorDrawable;
+ private TextView mHeaderCount;
+ private final Rect mOutline = new Rect();
+
+ // Space between notifications during swipe
+ private final int mNotificationSpace;
+ private final int mMaxTransX;
+ private final int mMaxElevation;
+
+ private final GradientDrawable mBackground;
public NotificationMainView(Context context) {
this(context, null, 0);
@@ -82,28 +90,77 @@
}
public NotificationMainView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
+ this(context, attrs, defStyle, 0);
+ }
- mColorDrawable = new ColorDrawable(Color.TRANSPARENT);
+ public NotificationMainView(Context context, AttributeSet attrs, int defStyle, int defStylRes) {
+ super(context, attrs, defStyle, defStylRes);
+
+ float outlineRadius = Themes.getDialogCornerRadius(context);
+
+ mBackground = new GradientDrawable();
+ mBackground.setColor(Themes.getAttrColor(context, R.attr.popupColorPrimary));
+ mBackground.setCornerRadius(outlineRadius);
+ setBackground(mBackground);
+
+ mMaxElevation = getResources().getDimensionPixelSize(R.dimen.deep_shortcuts_elevation);
+ setElevation(mMaxElevation);
+
+ mMaxTransX = getResources().getDimensionPixelSize(R.dimen.notification_max_trans);
+ mNotificationSpace = getResources().getDimensionPixelSize(R.dimen.notification_space);
+
+ setClipToOutline(true);
+ setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(mOutline, outlineRadius);
+ }
+ });
+ }
+
+ /**
+ * Updates the header text.
+ * @param notificationCount The number of notifications.
+ */
+ public void updateHeader(int notificationCount) {
+ final String text;
+ final int visibility;
+ if (notificationCount <= 1) {
+ text = "";
+ visibility = View.INVISIBLE;
+ } else {
+ text = String.valueOf(notificationCount);
+ visibility = View.VISIBLE;
+
+ }
+ mHeaderCount.setText(text);
+ mHeaderCount.setVisibility(visibility);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mTextAndBackground = findViewById(R.id.text_and_background);
- mTitleView = mTextAndBackground.findViewById(R.id.title);
- mTextView = mTextAndBackground.findViewById(R.id.text);
+ ViewGroup textAndBackground = findViewById(R.id.text_and_background);
+ mTitleView = textAndBackground.findViewById(R.id.title);
+ mTextView = textAndBackground.findViewById(R.id.text);
mIconView = findViewById(R.id.popup_item_icon);
+ mHeaderCount = findViewById(R.id.notification_count);
- ColorDrawable colorBackground = (ColorDrawable) mTextAndBackground.getBackground();
- updateBackgroundColor(colorBackground.getColor());
+ mHeader = findViewById(R.id.header);
+ mMainView = findViewById(R.id.main_view);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ mOutline.set(0, 0, getWidth(), getHeight());
+ invalidateOutline();
}
private void updateBackgroundColor(int color) {
mBackgroundColor = color;
- mColorDrawable.setColor(color);
- mTextAndBackground.setBackground(mColorDrawable);
+ mBackground.setColor(color);
if (mNotificationInfo != null) {
mIconView.setBackground(mNotificationInfo.getIconForBackground(getContext(),
mBackgroundColor));
@@ -128,8 +185,11 @@
/**
* Sets the content of this view, animating it after a new icon shifts up if necessary.
*/
- public void applyNotificationInfo(NotificationInfo mainNotification, boolean animate) {
- mNotificationInfo = mainNotification;
+ public void applyNotificationInfo(NotificationInfo notificationInfo) {
+ mNotificationInfo = notificationInfo;
+ if (notificationInfo == null) {
+ return;
+ }
NotificationListener listener = NotificationListener.getInstanceIfConnected();
if (listener != null) {
listener.setNotificationsShown(new String[] {mNotificationInfo.notificationKey});
@@ -149,25 +209,112 @@
if (mNotificationInfo.intent != null) {
setOnClickListener(mNotificationInfo);
}
- setContentTranslation(0);
+
// Add a stub ItemInfo so that logging populates the correct container and item types
// instead of DEFAULT_CONTAINERTYPE and DEFAULT_ITEMTYPE, respectively.
setTag(NOTIFICATION_ITEM_INFO);
- if (animate) {
- ObjectAnimator.ofFloat(mTextAndBackground, ALPHA, 0, 1).setDuration(150).start();
+ }
+
+ /**
+ * Sets the alpha of only the child views.
+ */
+ public void setContentAlpha(float alpha) {
+ mHeader.setAlpha(alpha);
+ mMainView.setAlpha(alpha);
+ }
+
+ /**
+ * Sets the translation of only the child views.
+ */
+ public void setContentTranslationX(float transX) {
+ mHeader.setTranslationX(transX);
+ mMainView.setTranslationX(transX);
+ }
+
+ /**
+ * Updates the alpha, content alpha, and elevation of this view.
+ *
+ * @param progress Range from [0, 1] or [-1, 0]
+ * When 0: Full alpha
+ * When 1/-1: zero alpha
+ */
+ public void onPrimaryDrag(float progress) {
+ float absProgress = Math.abs(progress);
+ final int width = getWidth();
+
+ float min = PRIMARY_MIN_PROGRESS;
+ float max = PRIMARY_MAX_PROGRESS;
+
+ if (absProgress < min) {
+ setAlpha(1f);
+ setContentAlpha(1);
+ setElevation(mMaxElevation);
+ } else if (absProgress < max) {
+ setAlpha(1f);
+ setContentAlpha(mapToRange(absProgress, min, max, 1f, 0f, LINEAR));
+ setElevation(Utilities.mapToRange(absProgress, min, max, mMaxElevation, 0, LINEAR));
+ } else {
+ setAlpha(mapToRange(absProgress, max, PRIMARY_GONE_PROGRESS, 1f, 0f, LINEAR));
+ setContentAlpha(0f);
+ setElevation(0f);
}
+
+ setTranslationX(width * progress);
}
- public void setContentTranslation(float translation) {
- mTextAndBackground.setTranslationX(translation);
- mIconView.setTranslationX(translation);
+ /**
+ * Updates the alpha, content alpha, elevation, and clipping of this view.
+ * @param progress Range from [0, 1] or [-1, 0]
+ * When 0: Smallest clipping, zero alpha
+ * When 1/-1: Full clip, full alpha
+ */
+ public void onSecondaryDrag(float progress) {
+ final float absProgress = Math.abs(progress);
+
+ float min = SECONDARY_MIN_PROGRESS;
+ float max = SECONDARY_MAX_PROGRESS;
+ float contentMax = SECONDARY_CONTENT_MAX_PROGRESS;
+
+ if (absProgress < min) {
+ setAlpha(0f);
+ setContentAlpha(0);
+ setElevation(0f);
+ } else if (absProgress < max) {
+ setAlpha(mapToRange(absProgress, min, max, 0, 1f, LINEAR));
+ setContentAlpha(0f);
+ setElevation(0f);
+ } else {
+ setAlpha(1f);
+ setContentAlpha(absProgress > contentMax
+ ? 1f
+ : mapToRange(absProgress, max, contentMax, 0, 1f, LINEAR));
+ setElevation(Utilities.mapToRange(absProgress, max, 1, 0, mMaxElevation, LINEAR));
+ }
+
+ final int width = getWidth();
+ int crop = (int) (width * absProgress);
+ int space = (int) (absProgress > PRIMARY_GONE_PROGRESS
+ ? mapToRange(absProgress, PRIMARY_GONE_PROGRESS, 1f, mNotificationSpace, 0, LINEAR)
+ : mNotificationSpace);
+ if (progress < 0) {
+ mOutline.left = Math.max(0, getWidth() - crop + space);
+ mOutline.right = getWidth();
+ } else {
+ mOutline.right = Math.min(getWidth(), crop - space);
+ mOutline.left = 0;
+ }
+
+ float contentTransX = mMaxTransX * (1f - absProgress);
+ setContentTranslationX(progress < 0
+ ? contentTransX
+ : -contentTransX);
+ invalidateOutline();
}
- public NotificationInfo getNotificationInfo() {
+ public @Nullable NotificationInfo getNotificationInfo() {
return mNotificationInfo;
}
-
public boolean canChildBeDismissed() {
return mNotificationInfo != null && mNotificationInfo.dismissable;
}
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 3bb49f5..112a24e 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -467,6 +467,13 @@
return getMeasuredWidth() - mArrowOffsetHorizontal - mArrowWidth;
}
+ /**
+ * @param show If true, shows arrow (when applicable), otherwise hides arrow.
+ */
+ public void showArrow(boolean show) {
+ mArrow.setVisibility(show && shouldAddArrow() ? VISIBLE : INVISIBLE);
+ }
+
private void addArrow() {
getPopupContainer().addView(mArrow);
mArrow.setX(getX() + getArrowLeft());
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 18f263a..bc3419a 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -58,8 +58,8 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.notification.NotificationContainer;
import com.android.launcher3.notification.NotificationInfo;
-import com.android.launcher3.notification.NotificationItemView;
import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.popup.PopupDataProvider.PopupDataChangeListener;
import com.android.launcher3.shortcuts.DeepShortcutView;
@@ -92,9 +92,8 @@
private final int mStartDragThreshold;
private BubbleTextView mOriginalIcon;
- private NotificationItemView mNotificationItemView;
private int mNumNotifications;
- private ViewGroup mNotificationContainer;
+ private NotificationContainer mNotificationContainer;
private ViewGroup mWidgetContainer;
@@ -128,8 +127,8 @@
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mInterceptTouchDown.set(ev.getX(), ev.getY());
}
- if (mNotificationItemView != null
- && mNotificationItemView.onInterceptTouchEvent(ev)) {
+ if (mNotificationContainer != null
+ && mNotificationContainer.onInterceptSwipeEvent(ev)) {
return true;
}
// Stop sending touch events to deep shortcut views if user moved beyond touch slop.
@@ -138,6 +137,14 @@
}
@Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (mNotificationContainer != null) {
+ return mNotificationContainer.onSwipeEvent(ev) || super.onTouchEvent(ev);
+ }
+ return super.onTouchEvent(ev);
+ }
+
+ @Override
protected boolean isOfType(int type) {
return (type & TYPE_ACTION_POPUP) != 0;
}
@@ -172,8 +179,8 @@
@Override
protected void setChildColor(View view, int color, AnimatorSet animatorSetOut) {
super.setChildColor(view, color, animatorSetOut);
- if (view.getId() == R.id.notification_container && mNotificationItemView != null) {
- mNotificationItemView.updateBackgroundColor(color, animatorSetOut);
+ if (view.getId() == R.id.notification_container && mNotificationContainer != null) {
+ mNotificationContainer.updateBackgroundColor(color, animatorSetOut);
}
}
@@ -232,13 +239,6 @@
mNotificationContainer);
}
- @Override
- protected void onInflationComplete(boolean isReversed) {
- if (isReversed && mNotificationItemView != null) {
- mNotificationItemView.inverseGutterMargin();
- }
- }
-
@TargetApi(Build.VERSION_CODES.P)
public void populateAndShow(final BubbleTextView originalIcon, int shortcutCount,
final List<NotificationKeyData> notificationKeys, List<SystemShortcut> systemShortcuts) {
@@ -261,9 +261,10 @@
if (mNotificationContainer == null) {
mNotificationContainer = findViewById(R.id.notification_container);
mNotificationContainer.setVisibility(VISIBLE);
+ mNotificationContainer.setPopupView(this);
+ } else {
+ mNotificationContainer.setVisibility(GONE);
}
- View.inflate(getContext(), R.layout.notification_content, mNotificationContainer);
- mNotificationItemView = new NotificationItemView(this, mNotificationContainer);
updateNotificationHeader();
}
int viewsToFlip = getChildCount();
@@ -274,10 +275,6 @@
if (hasDeepShortcuts) {
mDeepShortcutContainer.setVisibility(View.VISIBLE);
- if (mNotificationItemView != null) {
- mNotificationItemView.addGutter();
- }
-
for (int i = shortcutCount; i > 0; i--) {
DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut, mDeepShortcutContainer);
v.getLayoutParams().width = containerWidth;
@@ -309,10 +306,6 @@
} else {
mDeepShortcutContainer.setVisibility(View.GONE);
if (!systemShortcuts.isEmpty()) {
- if (mNotificationItemView != null) {
- mNotificationItemView.addGutter();
- }
-
for (SystemShortcut shortcut : systemShortcuts) {
initializeSystemShortcut(R.layout.system_shortcut, this, shortcut);
}
@@ -355,13 +348,13 @@
}
public void applyNotificationInfos(List<NotificationInfo> notificationInfos) {
- if (mNotificationItemView != null) {
- mNotificationItemView.applyNotificationInfos(notificationInfos);
+ if (mNotificationContainer != null) {
+ mNotificationContainer.applyNotificationInfos(notificationInfos);
}
}
private void updateHiddenShortcuts() {
- int allowedCount = mNotificationItemView != null
+ int allowedCount = mNotificationContainer != null
? MAX_SHORTCUTS_IF_NOTIFICATIONS : MAX_SHORTCUTS;
int total = mShortcuts.size();
@@ -447,8 +440,8 @@
private void updateNotificationHeader() {
ItemInfoWithIcon itemInfo = (ItemInfoWithIcon) mOriginalIcon.getTag();
DotInfo dotInfo = mLauncher.getDotInfoForItem(itemInfo);
- if (mNotificationItemView != null && dotInfo != null) {
- mNotificationItemView.updateHeader(dotInfo.getNotificationCount());
+ if (mNotificationContainer != null && dotInfo != null) {
+ mNotificationContainer.updateHeader(dotInfo.getNotificationCount());
}
}
@@ -590,20 +583,18 @@
@Override
public void trimNotifications(Map<PackageUserKey, DotInfo> updatedDots) {
- if (mNotificationItemView == null) {
+ if (mNotificationContainer == null) {
return;
}
ItemInfo originalInfo = (ItemInfo) mOriginalIcon.getTag();
DotInfo dotInfo = updatedDots.get(PackageUserKey.fromItemInfo(originalInfo));
if (dotInfo == null || dotInfo.getNotificationKeys().size() == 0) {
// No more notifications, remove the notification views and expand all shortcuts.
- mNotificationItemView.removeAllViews();
- mNotificationItemView = null;
mNotificationContainer.setVisibility(GONE);
updateHiddenShortcuts();
assignMarginsAndBackgrounds(PopupContainerWithArrow.this);
} else {
- mNotificationItemView.trimNotifications(
+ mNotificationContainer.trimNotifications(
NotificationKeyData.extractKeysOnly(dotInfo.getNotificationKeys()));
}
}
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index c484811..ed52e20 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -117,7 +117,7 @@
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
public static final String WORK_PROFILE_REMOVED = "b/159671700";
public static final String FALLBACK_ACTIVITY_NO_SET = "b/181019015";
- public static final String THIRD_PARTY_LAUNCHER_NOT_SET = "b/187080582";
public static final String TASK_VIEW_ID_CRASH = "b/195430732";
public static final String L3_SWIPE_TO_HOME = "b/192018189";
+ public static final String NO_DROP_TARGET = "b/195031154";
}
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index b6cec12..00a0050 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -19,6 +19,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
@@ -108,6 +109,9 @@
@Override
public boolean onLongClick(View v) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_DROP_TARGET, "1");
+ }
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "Widgets.onLongClick");
v.cancelLongPress();
if (!ItemLongClickListener.canStartDrag(mActivityContext)) return false;
@@ -178,6 +182,9 @@
}
private boolean beginDraggingWidget(WidgetCell v) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_DROP_TARGET, "2");
+ }
// Get the widget preview as the drag representation
WidgetImageView image = v.getWidgetView();
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index 2347d28..463f4ac 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -22,6 +22,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.util.Log;
import android.util.Size;
import android.view.View;
import android.view.View.MeasureSpec;
@@ -41,6 +42,7 @@
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.RoundDrawableWrapper;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
import com.android.launcher3.widget.util.WidgetSizes;
@@ -94,6 +96,9 @@
*/
public void startDrag(Rect previewBounds, int previewBitmapWidth, int previewViewWidth,
Point screenPos, DragSource source, DragOptions options) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_DROP_TARGET, "3");
+ }
final Launcher launcher = Launcher.getLauncher(mView.getContext());
LauncherAppState app = LauncherAppState.getInstance(launcher);