mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-19 02:38:20 +00:00
Merge "adding the new Material U App Shortcut Popup design" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
9af03389d6
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3.taskbar;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
|
||||
import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
|
||||
|
||||
import android.content.Intent;
|
||||
@@ -56,6 +57,7 @@ import com.android.quickstep.util.LogUtils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -152,9 +154,28 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba
|
||||
return null;
|
||||
}
|
||||
|
||||
final PopupContainerWithArrow<BaseTaskbarContext> container =
|
||||
(PopupContainerWithArrow<BaseTaskbarContext>) context.getLayoutInflater().inflate(
|
||||
R.layout.popup_container, context.getDragLayer(), false);
|
||||
PopupContainerWithArrow<BaseTaskbarContext> container;
|
||||
int deepShortcutCount = mPopupDataProvider.getShortcutCountForItem(item);
|
||||
// TODO(b/198438631): add support for INSTALL shortcut factory
|
||||
List<SystemShortcut> systemShortcuts = getSystemShortcuts()
|
||||
.map(s -> s.getShortcut(context, item, icon))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (ENABLE_MATERIAL_U_POPUP.get()) {
|
||||
container = (PopupContainerWithArrow) context.getLayoutInflater().inflate(
|
||||
R.layout.popup_container_material_u, context.getDragLayer(), false);
|
||||
container.populateAndShowRowsMaterialU(icon, deepShortcutCount, systemShortcuts);
|
||||
} else {
|
||||
container = (PopupContainerWithArrow) context.getLayoutInflater().inflate(
|
||||
R.layout.popup_container, context.getDragLayer(), false);
|
||||
container.populateAndShow(
|
||||
icon,
|
||||
deepShortcutCount,
|
||||
mPopupDataProvider.getNotificationKeysForItem(item),
|
||||
systemShortcuts);
|
||||
}
|
||||
|
||||
container.addOnAttachStateChangeListener(
|
||||
new PopupLiveUpdateHandler<BaseTaskbarContext>(context, container) {
|
||||
@Override
|
||||
@@ -165,15 +186,6 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba
|
||||
// TODO (b/198438631): configure for taskbar/context
|
||||
container.setPopupItemDragHandler(new TaskbarPopupItemDragHandler());
|
||||
mControllers.taskbarDragController.addDragListener(container);
|
||||
|
||||
container.populateAndShow(icon,
|
||||
mPopupDataProvider.getShortcutCountForItem(item),
|
||||
mPopupDataProvider.getNotificationKeysForItem(item),
|
||||
// TODO (b/198438631): add support for INSTALL shortcut factory
|
||||
getSystemShortcuts()
|
||||
.map(s -> s.getShortcut(context, item, icon))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList()));
|
||||
container.requestFocus();
|
||||
|
||||
// Make focusable to receive back events
|
||||
|
||||
20
res/drawable/popup_background_material_u.xml
Normal file
20
res/drawable/popup_background_material_u.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?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="rectangle">
|
||||
<solid android:color="?attr/popupColorPrimary"/>
|
||||
<corners android:radius="@dimen/dialogCornerRadius"/>
|
||||
</shape>
|
||||
24
res/layout/deep_shortcut_container.xml
Normal file
24
res/layout/deep_shortcut_container.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/deep_shortcuts_container"
|
||||
android:background="@drawable/popup_background_material_u"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:tag="@string/popup_container_iterate_children"
|
||||
android:elevation="@dimen/deep_shortcuts_elevation"
|
||||
android:orientation="vertical"/>
|
||||
50
res/layout/deep_shortcut_material_u.xml
Normal file
50
res/layout/deep_shortcut_material_u.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?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.
|
||||
-->
|
||||
<com.android.launcher3.shortcuts.DeepShortcutView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/deep_shortcut_material"
|
||||
android:layout_width="@dimen/bg_popup_item_width"
|
||||
android:layout_height="@dimen/bg_popup_item_height"
|
||||
android:elevation="@dimen/deep_shortcuts_elevation"
|
||||
android:background="@drawable/middle_item_primary"
|
||||
android:theme="@style/PopupItem" >
|
||||
|
||||
<com.android.launcher3.shortcuts.DeepShortcutTextView
|
||||
style="@style/BaseIcon"
|
||||
android:id="@+id/bubble_text"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="viewStart"
|
||||
android:paddingStart="@dimen/deep_shortcuts_text_padding_start"
|
||||
android:paddingEnd="@dimen/popup_padding_end"
|
||||
android:drawablePadding="@dimen/deep_shortcut_drawable_padding"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
launcher:layoutHorizontal="true"
|
||||
launcher:iconDisplay="shortcut_popup"
|
||||
launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/deep_shortcut_icon_size"
|
||||
android:layout_height="@dimen/deep_shortcut_icon_size"
|
||||
android:layout_marginStart="@dimen/popup_padding_start"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:background="@drawable/ic_deepshortcut_placeholder"/>
|
||||
</com.android.launcher3.shortcuts.DeepShortcutView>
|
||||
21
res/layout/popup_container_material_u.xml
Normal file
21
res/layout/popup_container_material_u.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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.
|
||||
-->
|
||||
<com.android.launcher3.popup.PopupContainerWithArrow
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/popup_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"/>
|
||||
@@ -18,6 +18,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="@dimen/bg_popup_item_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/system_shortcut"
|
||||
android:minHeight="@dimen/bg_popup_item_height"
|
||||
android:elevation="@dimen/deep_shortcuts_elevation"
|
||||
android:background="@drawable/middle_item_primary"
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
android:clipToPadding="true">
|
||||
|
||||
<Space android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/separator"/>
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/separator"/>
|
||||
</LinearLayout>
|
||||
32
res/layout/system_shortcut_icons_container_material_u.xml
Normal file
32
res/layout/system_shortcut_icons_container_material_u.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/system_shortcut_icons"
|
||||
android:tag="@string/popup_container_iterate_children"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/system_shortcut_header_height"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end|center_vertical"
|
||||
android:background="@drawable/popup_background_material_u"
|
||||
android:elevation="@dimen/deep_shortcuts_elevation">
|
||||
|
||||
<Space android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/separator"/>
|
||||
</LinearLayout>
|
||||
25
res/layout/system_shortcut_rows_container_material_u.xml
Normal file
25
res/layout/system_shortcut_rows_container_material_u.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/system_shortcuts_container"
|
||||
android:background="@drawable/popup_background_material_u"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:tag="@string/popup_container_iterate_children"
|
||||
android:elevation="@dimen/deep_shortcuts_elevation"
|
||||
android:orientation="vertical"/>
|
||||
27
res/layout/widget_shortcut_container_material_u.xml
Normal file
27
res/layout/widget_shortcut_container_material_u.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/widget_shortcut_container"
|
||||
android:background="@drawable/popup_background_material_u"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/system_shortcut_header_height"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end|center_vertical"
|
||||
android:elevation="@dimen/deep_shortcuts_elevation"
|
||||
android:tag="@string/popup_container_iterate_children"
|
||||
android:clipToPadding="true"/>
|
||||
@@ -348,7 +348,7 @@
|
||||
<dimen name="developer_options_filter_margins">10dp</dimen>
|
||||
|
||||
<!-- Theming related -->
|
||||
<dimen name="default_dialog_corner_radius">8dp</dimen>
|
||||
<dimen name="default_dialog_corner_radius">26dp</dimen>
|
||||
<dimen name="dialogCornerRadius">@dimen/default_dialog_corner_radius</dimen>
|
||||
|
||||
<!-- Onboarding bottomsheet related -->
|
||||
|
||||
@@ -3211,7 +3211,7 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUseColorExtractionForPopup() {
|
||||
public boolean canUseMultipleShadesForPopup() {
|
||||
return getTopOpenViewWithType(this, TYPE_FOLDER) == null
|
||||
&& getStateManager().getState() != LauncherState.ALL_APPS;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static androidx.core.content.ContextCompat.getColorStateList;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCELERATED_EASE;
|
||||
import static com.android.launcher3.anim.Interpolators.DECELERATED_EASE;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -116,7 +117,7 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
|
||||
|
||||
private final String mIterateChildrenTag;
|
||||
|
||||
private final int[] mColorIds;
|
||||
protected final int[] mColorIds;
|
||||
|
||||
public ArrowPopup(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
@@ -125,8 +126,8 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
|
||||
mActivityContext = ActivityContext.lookupContext(context);
|
||||
mIsRtl = Utilities.isRtl(getResources());
|
||||
|
||||
int backgroundColor = Themes.getAttrColor(context, R.attr.popupColorPrimary);
|
||||
mArrowColor = backgroundColor;
|
||||
int popupPrimaryColor = Themes.getAttrColor(context, R.attr.popupColorPrimary);
|
||||
mArrowColor = popupPrimaryColor;
|
||||
mElevation = getResources().getDimension(R.dimen.deep_shortcuts_elevation);
|
||||
|
||||
// Initialize arrow view
|
||||
@@ -143,18 +144,18 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
|
||||
|
||||
int smallerRadius = resources.getDimensionPixelSize(R.dimen.popup_smaller_radius);
|
||||
mRoundedTop = new GradientDrawable();
|
||||
mRoundedTop.setColor(backgroundColor);
|
||||
mRoundedTop.setColor(popupPrimaryColor);
|
||||
mRoundedTop.setCornerRadii(new float[] { mOutlineRadius, mOutlineRadius, mOutlineRadius,
|
||||
mOutlineRadius, smallerRadius, smallerRadius, smallerRadius, smallerRadius});
|
||||
|
||||
mRoundedBottom = new GradientDrawable();
|
||||
mRoundedBottom.setColor(backgroundColor);
|
||||
mRoundedBottom.setColor(popupPrimaryColor);
|
||||
mRoundedBottom.setCornerRadii(new float[] { smallerRadius, smallerRadius, smallerRadius,
|
||||
smallerRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius});
|
||||
|
||||
mIterateChildrenTag = getContext().getString(R.string.popup_container_iterate_children);
|
||||
|
||||
if (mActivityContext.shouldUseColorExtractionForPopup()) {
|
||||
if (!ENABLE_MATERIAL_U_POPUP.get() && mActivityContext.canUseMultipleShadesForPopup()) {
|
||||
mColorIds = new int[]{R.color.popup_shade_first, R.color.popup_shade_second,
|
||||
R.color.popup_shade_third};
|
||||
} else {
|
||||
@@ -241,15 +242,23 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
|
||||
mlp.bottomMargin = 0;
|
||||
|
||||
if (colors != null) {
|
||||
backgroundColor = colors[numVisibleChild % colors.length];
|
||||
if (!ENABLE_MATERIAL_U_POPUP.get()) {
|
||||
backgroundColor = colors[numVisibleChild % colors.length];
|
||||
}
|
||||
|
||||
if (ENABLE_MATERIAL_U_POPUP.get() && isShortcutContainer(view)) {
|
||||
setChildColor(view, colors[0], colorAnimator);
|
||||
mArrowColor = colors[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Arrow color matches the first child or the last child.
|
||||
if (mIsAboveIcon || (numVisibleChild == 0 && viewGroup == this)) {
|
||||
if (!ENABLE_MATERIAL_U_POPUP.get()
|
||||
&& (mIsAboveIcon || (numVisibleChild == 0 && viewGroup == this))) {
|
||||
mArrowColor = backgroundColor;
|
||||
}
|
||||
|
||||
if (view instanceof ViewGroup && mIterateChildrenTag.equals(view.getTag())) {
|
||||
if (view instanceof ViewGroup && isShortcutContainer(view)) {
|
||||
assignMarginsAndBackgrounds((ViewGroup) view, backgroundColor);
|
||||
numVisibleChild++;
|
||||
continue;
|
||||
@@ -286,6 +295,13 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
|
||||
return view instanceof DeepShortcutView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if view is a layout container of shortcuts
|
||||
*/
|
||||
boolean isShortcutContainer(View view) {
|
||||
return mIterateChildrenTag.equals(view.getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the background color of the child.
|
||||
*/
|
||||
@@ -308,7 +324,7 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
|
||||
*/
|
||||
protected void reorderAndShow(int viewsToFlip) {
|
||||
setupForDisplay();
|
||||
boolean reverseOrder = mIsAboveIcon;
|
||||
boolean reverseOrder = !ENABLE_MATERIAL_U_POPUP.get() && mIsAboveIcon;
|
||||
if (reverseOrder) {
|
||||
reverseOrder(viewsToFlip);
|
||||
}
|
||||
@@ -634,7 +650,7 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
|
||||
for (int i = group.getChildCount() - 1; i >= 0; --i) {
|
||||
View view = group.getChildAt(i);
|
||||
if (view.getVisibility() == VISIBLE && view instanceof ViewGroup) {
|
||||
if (mIterateChildrenTag.equals(view.getTag())) {
|
||||
if (isShortcutContainer(view)) {
|
||||
fadeInChildViews((ViewGroup) view, alphaValues, startDelay, duration, out);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -17,12 +17,16 @@
|
||||
package com.android.launcher3.popup;
|
||||
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS;
|
||||
import static com.android.launcher3.Utilities.ATLEAST_P;
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.Utilities.squaredTouchSlop;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
|
||||
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS;
|
||||
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.LayoutTransition;
|
||||
import android.annotation.TargetApi;
|
||||
@@ -39,6 +43,8 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
@@ -82,20 +88,20 @@ import java.util.stream.Collectors;
|
||||
public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
extends ArrowPopup<T> implements DragSource, DragController.DragListener {
|
||||
|
||||
private final List<DeepShortcutView> mShortcuts = new ArrayList<>();
|
||||
private final List<DeepShortcutView> mDeepShortcuts = new ArrayList<>();
|
||||
private final PointF mInterceptTouchDown = new PointF();
|
||||
|
||||
private final int mStartDragThreshold;
|
||||
|
||||
private static final int SHORTCUT_COLLAPSE_THRESHOLD = 6;
|
||||
|
||||
private BubbleTextView mOriginalIcon;
|
||||
private int mNumNotifications;
|
||||
private NotificationContainer mNotificationContainer;
|
||||
private int mContainerWidth;
|
||||
|
||||
private ViewGroup mWidgetContainer;
|
||||
|
||||
private ViewGroup mDeepShortcutContainer;
|
||||
|
||||
private ViewGroup mSystemShortcutContainer;
|
||||
|
||||
protected PopupItemDragHandler mPopupItemDragHandler;
|
||||
@@ -211,19 +217,27 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
return null;
|
||||
}
|
||||
|
||||
final PopupContainerWithArrow<Launcher> container =
|
||||
(PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
|
||||
R.layout.popup_container, launcher.getDragLayer(), false);
|
||||
container.configureForLauncher(launcher);
|
||||
|
||||
PopupContainerWithArrow<Launcher> container;
|
||||
PopupDataProvider popupDataProvider = launcher.getPopupDataProvider();
|
||||
container.populateAndShow(icon,
|
||||
popupDataProvider.getShortcutCountForItem(item),
|
||||
popupDataProvider.getNotificationKeysForItem(item),
|
||||
launcher.getSupportedShortcuts()
|
||||
.map(s -> s.getShortcut(launcher, item, icon))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList()));
|
||||
int deepShortcutCount = popupDataProvider.getShortcutCountForItem(item);
|
||||
List<SystemShortcut> systemShortcuts = launcher.getSupportedShortcuts()
|
||||
.map(s -> s.getShortcut(launcher, item, icon))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
if (ENABLE_MATERIAL_U_POPUP.get()) {
|
||||
container = (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
|
||||
R.layout.popup_container_material_u, launcher.getDragLayer(), false);
|
||||
container.populateAndShowRowsMaterialU(icon, deepShortcutCount, systemShortcuts);
|
||||
} else {
|
||||
container = (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
|
||||
R.layout.popup_container, launcher.getDragLayer(), false);
|
||||
container.populateAndShow(
|
||||
icon,
|
||||
deepShortcutCount,
|
||||
popupDataProvider.getNotificationKeysForItem(item),
|
||||
systemShortcuts);
|
||||
}
|
||||
container.configureForLauncher(launcher);
|
||||
launcher.refreshAndBindWidgetsForPackageUser(PackageUserKey.fromItemInfo(item));
|
||||
container.requestFocus();
|
||||
return container;
|
||||
@@ -246,7 +260,7 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
initializeSystemShortcut(R.layout.system_shortcut, this, shortcuts.get(0));
|
||||
return;
|
||||
}
|
||||
mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons, this);
|
||||
mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons_container, this);
|
||||
for (SystemShortcut shortcut : shortcuts) {
|
||||
initializeSystemShortcut(
|
||||
R.layout.system_shortcut_icon_only, mSystemShortcutContainer,
|
||||
@@ -281,17 +295,7 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
mDeepShortcutContainer = findViewById(R.id.deep_shortcuts_container);
|
||||
}
|
||||
if (hasDeepShortcuts) {
|
||||
// Remove the widget shortcut fom the list
|
||||
List<SystemShortcut> systemShortcuts = shortcuts
|
||||
.stream()
|
||||
.filter(shortcut -> !(shortcut instanceof SystemShortcut.Widgets))
|
||||
.collect(Collectors.toList());
|
||||
Optional<SystemShortcut.Widgets> widgetShortcutOpt = shortcuts
|
||||
.stream()
|
||||
.filter(shortcut -> shortcut instanceof SystemShortcut.Widgets)
|
||||
.map(SystemShortcut.Widgets.class::cast)
|
||||
.findFirst();
|
||||
|
||||
List<SystemShortcut> systemShortcuts = getNonWidgetSystemShortcuts(shortcuts);
|
||||
// if there are deep shortcuts, we might want to increase the width of shortcuts to fit
|
||||
// horizontally laid out system shortcuts.
|
||||
mContainerWidth = Math.max(mContainerWidth,
|
||||
@@ -304,10 +308,10 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
for (int i = shortcutCount; i > 0; i--) {
|
||||
DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut, mDeepShortcutContainer);
|
||||
v.getLayoutParams().width = mContainerWidth;
|
||||
mShortcuts.add(v);
|
||||
mDeepShortcuts.add(v);
|
||||
}
|
||||
updateHiddenShortcuts();
|
||||
|
||||
Optional<SystemShortcut.Widgets> widgetShortcutOpt = getWidgetShortcut(shortcuts);
|
||||
if (widgetShortcutOpt.isPresent()) {
|
||||
if (mWidgetContainer == null) {
|
||||
mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container,
|
||||
@@ -327,21 +331,151 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
}
|
||||
|
||||
reorderAndShow(viewsToFlip);
|
||||
showPopupContainer((ItemInfo) originalIcon.getTag(), notificationKeys);
|
||||
}
|
||||
|
||||
ItemInfo originalItemInfo = (ItemInfo) originalIcon.getTag();
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
setAccessibilityPaneTitle(getTitleForAccessibility());
|
||||
/**
|
||||
* Populate and show shortcuts for the Launcher U app shortcut design.
|
||||
* Will inflate the container and shortcut View instances for the popup container.
|
||||
* @param originalIcon App icon that the popup is shown for
|
||||
* @param deepShortcutCount Number of DeepShortcutView instances to add to container
|
||||
* @param systemShortcuts List of SystemShortcuts to add to container
|
||||
*/
|
||||
public void populateAndShowRowsMaterialU(final BubbleTextView originalIcon,
|
||||
int deepShortcutCount, List<SystemShortcut> systemShortcuts) {
|
||||
|
||||
mOriginalIcon = originalIcon;
|
||||
mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width);
|
||||
|
||||
if (deepShortcutCount > 0) {
|
||||
addAllShortcutsMaterialU(deepShortcutCount, systemShortcuts);
|
||||
} else if (!systemShortcuts.isEmpty()) {
|
||||
addSystemShortcutsMaterialU(systemShortcuts,
|
||||
R.layout.system_shortcut_rows_container_material_u,
|
||||
R.layout.system_shortcut);
|
||||
}
|
||||
|
||||
mOriginalIcon.setForceHideDot(true);
|
||||
// no reversing needed for U design
|
||||
reorderAndShow(0);
|
||||
showPopupContainer((ItemInfo) originalIcon.getTag(), /* notificationKeys= */ emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates and loads shortcuts on background thread for this popup container
|
||||
*/
|
||||
private void showPopupContainer(ItemInfo originalItemInfo,
|
||||
List<NotificationKeyData> notificationKeys) {
|
||||
|
||||
if (ATLEAST_P) {
|
||||
setAccessibilityPaneTitle(getTitleForAccessibility());
|
||||
}
|
||||
mOriginalIcon.setForceHideDot(true);
|
||||
// All views are added. Animate layout from now on.
|
||||
setLayoutTransition(new LayoutTransition());
|
||||
|
||||
// Load the shortcuts on a background thread and update the container as it animates.
|
||||
MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(PopupPopulator.createUpdateRunnable(
|
||||
mActivityContext, originalItemInfo, new Handler(Looper.getMainLooper()),
|
||||
this, mShortcuts, notificationKeys));
|
||||
this, mDeepShortcuts, notificationKeys));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds any Deep Shortcuts, System Shortcuts and the Widget Shortcut to their respective
|
||||
* containers
|
||||
* @param deepShortcutCount number of DeepShortcutView instances
|
||||
* @param systemShortcuts List of SystemShortcuts
|
||||
*/
|
||||
private void addAllShortcutsMaterialU(int deepShortcutCount,
|
||||
List<SystemShortcut> systemShortcuts) {
|
||||
|
||||
if (deepShortcutCount + systemShortcuts.size() <= SHORTCUT_COLLAPSE_THRESHOLD) {
|
||||
// add all system shortcuts including widgets shortcut to same container
|
||||
addSystemShortcutsMaterialU(systemShortcuts,
|
||||
R.layout.system_shortcut_rows_container_material_u,
|
||||
R.layout.system_shortcut);
|
||||
addDeepShortcutsMaterialU(deepShortcutCount);
|
||||
return;
|
||||
}
|
||||
|
||||
List<SystemShortcut> nonWidgetSystemShortcuts =
|
||||
getNonWidgetSystemShortcuts(systemShortcuts);
|
||||
// If total shortcuts over threshold, collapse system shortcuts to single row
|
||||
addSystemShortcutsMaterialU(nonWidgetSystemShortcuts,
|
||||
R.layout.system_shortcut_icons_container_material_u,
|
||||
R.layout.system_shortcut_icon_only);
|
||||
// May need to recalculate row width
|
||||
mContainerWidth = Math.max(mContainerWidth,
|
||||
nonWidgetSystemShortcuts.size() * getResources()
|
||||
.getDimensionPixelSize(R.dimen.system_shortcut_header_icon_touch_size));
|
||||
// Add widget shortcut to separate container
|
||||
Optional<SystemShortcut.Widgets> widgetShortcutOpt = getWidgetShortcut(systemShortcuts);
|
||||
if (widgetShortcutOpt.isPresent()) {
|
||||
mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container_material_u,
|
||||
this);
|
||||
initializeWidgetShortcut(mWidgetContainer, widgetShortcutOpt.get());
|
||||
}
|
||||
addDeepShortcutsMaterialU(deepShortcutCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first instance of the Widgets Shortcut from the SystemShortcut List
|
||||
* @param systemShortcuts List of SystemShortcut instances to search
|
||||
* @return Optional Widgets SystemShortcut
|
||||
*/
|
||||
private static Optional<SystemShortcut.Widgets> getWidgetShortcut(
|
||||
List<SystemShortcut> systemShortcuts) {
|
||||
return systemShortcuts
|
||||
.stream()
|
||||
.filter(shortcut -> shortcut instanceof SystemShortcut.Widgets)
|
||||
.map(SystemShortcut.Widgets.class::cast)
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of [systemShortcuts] without the Widgets shortcut instance if found
|
||||
* @param systemShortcuts list of SystemShortcuts to filter from
|
||||
* @return systemShortcuts without the Widgets Shortcut
|
||||
*/
|
||||
private static List<SystemShortcut> getNonWidgetSystemShortcuts(
|
||||
List<SystemShortcut> systemShortcuts) {
|
||||
|
||||
return systemShortcuts
|
||||
.stream()
|
||||
.filter(shortcut -> !(shortcut instanceof SystemShortcut.Widgets))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Inflates the given systemShortcutContainerLayout as a container, and populates with
|
||||
* the systemShortcuts as views using the systemShortcutLayout
|
||||
* @param systemShortcuts List of SystemShortcut to inflate as Views
|
||||
* @param systemShortcutContainerLayout Layout Resource for the Container of shortcut Views
|
||||
* @param systemShortcutLayout Layout Resource for the individual shortcut Views
|
||||
*/
|
||||
private void addSystemShortcutsMaterialU(List<SystemShortcut> systemShortcuts,
|
||||
@LayoutRes int systemShortcutContainerLayout, @LayoutRes int systemShortcutLayout) {
|
||||
|
||||
if (systemShortcuts.size() == 0) {
|
||||
return;
|
||||
}
|
||||
mSystemShortcutContainer = inflateAndAdd(systemShortcutContainerLayout, this);
|
||||
for (SystemShortcut shortcut : systemShortcuts) {
|
||||
initializeSystemShortcut(systemShortcutLayout, mSystemShortcutContainer, shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inflates and adds [deepShortcutCount] number of DeepShortcutView for the to a new container
|
||||
* @param deepShortcutCount number of DeepShortcutView instances to add
|
||||
*/
|
||||
private void addDeepShortcutsMaterialU(int deepShortcutCount) {
|
||||
mDeepShortcutContainer = inflateAndAdd(R.layout.deep_shortcut_container, this);
|
||||
for (int i = deepShortcutCount; i > 0; i--) {
|
||||
DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut_material_u,
|
||||
mDeepShortcutContainer);
|
||||
v.getLayoutParams().width = mContainerWidth;
|
||||
mDeepShortcuts.add(v);
|
||||
}
|
||||
updateHiddenShortcuts();
|
||||
}
|
||||
|
||||
protected NotificationContainer getNotificationContainer() {
|
||||
@@ -391,9 +525,9 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
int allowedCount = mNotificationContainer != null
|
||||
? MAX_SHORTCUTS_IF_NOTIFICATIONS : MAX_SHORTCUTS;
|
||||
|
||||
int total = mShortcuts.size();
|
||||
int total = mDeepShortcuts.size();
|
||||
for (int i = 0; i < total; i++) {
|
||||
DeepShortcutView view = mShortcuts.get(i);
|
||||
DeepShortcutView view = mDeepShortcuts.get(i);
|
||||
view.setVisibility(i >= allowedCount ? GONE : VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.launcher3.secondarydisplay;
|
||||
import static android.view.View.MeasureSpec.EXACTLY;
|
||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
|
||||
import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -203,14 +204,22 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
|
||||
systemShortcuts.add(mPinnedAppsAdapter.getSystemShortcut(item, v));
|
||||
}
|
||||
systemShortcuts.add(APP_INFO.getShortcut(mActivity, item, v));
|
||||
|
||||
final PopupContainerWithArrow container =
|
||||
(PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
|
||||
R.layout.popup_container, mActivity.getDragLayer(), false);
|
||||
|
||||
container.populateAndShow((BubbleTextView) v,
|
||||
popupDataProvider.getShortcutCountForItem(item),
|
||||
Collections.emptyList(), systemShortcuts);
|
||||
int deepShortcutCount = popupDataProvider.getShortcutCountForItem(item);
|
||||
final PopupContainerWithArrow<SecondaryDisplayLauncher> container;
|
||||
if (ENABLE_MATERIAL_U_POPUP.get()) {
|
||||
container = (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
|
||||
R.layout.popup_container_material_u, mActivity.getDragLayer(), false);
|
||||
container.populateAndShowRowsMaterialU((BubbleTextView) v, deepShortcutCount,
|
||||
systemShortcuts);
|
||||
} else {
|
||||
container = (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
|
||||
R.layout.popup_container, mActivity.getDragLayer(), false);
|
||||
container.populateAndShow(
|
||||
(BubbleTextView) v,
|
||||
deepShortcutCount,
|
||||
Collections.emptyList(),
|
||||
systemShortcuts);
|
||||
}
|
||||
container.requestFocus();
|
||||
|
||||
if (!FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.get() || !mActivity.isAppDrawerShown()) {
|
||||
|
||||
@@ -199,9 +199,9 @@ public interface ActivityContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if popups should use color extraction.
|
||||
* Returns {@code true} if popups can use a range of color shades instead of a singular color.
|
||||
*/
|
||||
default boolean shouldUseColorExtractionForPopup() {
|
||||
default boolean canUseMultipleShadesForPopup() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
*/
|
||||
package com.android.launcher3.views;
|
||||
|
||||
import static androidx.core.content.ContextCompat.getColorStateList;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_BUTTON_TAP_OR_LONGPRESS;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -31,6 +35,7 @@ import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnLongClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -139,6 +144,16 @@ public class OptionsPopupView extends ArrowPopup<Launcher>
|
||||
mTargetRect.roundOut(outPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assignMarginsAndBackgrounds(ViewGroup viewGroup) {
|
||||
if (ENABLE_MATERIAL_U_POPUP.get()) {
|
||||
assignMarginsAndBackgrounds(viewGroup,
|
||||
getColorStateList(getContext(), mColorIds[0]).getDefaultColor());
|
||||
} else {
|
||||
assignMarginsAndBackgrounds(viewGroup, Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
public static OptionsPopupView show(ActivityContext launcher, RectF targetRect,
|
||||
List<OptionItem> items, boolean shouldAddArrow) {
|
||||
return show(launcher, targetRect, items, shouldAddArrow, 0 /* width */);
|
||||
|
||||
Reference in New Issue
Block a user