diff options
author | Miranda Kephart <mkephart@google.com> | 2019-02-11 13:07:04 -0500 |
---|---|---|
committer | Miranda Kephart <mkephart@google.com> | 2019-02-20 15:17:03 -0500 |
commit | 1a359a261d031630747417239eca658c243b4996 (patch) | |
tree | bea099478782e20d7c4d05c9b93412f4b3b4d610 | |
parent | 7b4215d633f12794cebf1cfc9a390e0c7f520fd7 (diff) | |
download | packages_apps_Trebuchet-1a359a261d031630747417239eca658c243b4996.tar.gz packages_apps_Trebuchet-1a359a261d031630747417239eca658c243b4996.tar.bz2 packages_apps_Trebuchet-1a359a261d031630747417239eca658c243b4996.zip |
Add hints in Overview
If the ENABLE_HINTS_IN_OVERVIEW flag is enabled, pulls chip hint
data (currently from the NavBarHint plugin; eventually from AiAi)
and shows the chips between the task view screenshot and the QSB.
Screenshot: https://screenshot.googleplex.com/Ww05W13XjBv
BUG:124390101
Change-Id: I7686673b705257eca31f2fa40e2744e197153c7c
19 files changed, 647 insertions, 3 deletions
diff --git a/quickstep/recents_ui_overrides/res/drawable/chip_hint_background_light.xml b/quickstep/recents_ui_overrides/res/drawable/chip_hint_background_light.xml new file mode 100644 index 000000000..7b4da8398 --- /dev/null +++ b/quickstep/recents_ui_overrides/res/drawable/chip_hint_background_light.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 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"> + <stroke + android:color="@color/chip_hint_foreground_color" + android:width="@dimen/chip_hint_border_width"/> + <corners android:radius="@dimen/chip_hint_corner_radius"/> + <padding + android:left="@dimen/chip_hint_outer_padding" + android:top="@dimen/chip_hint_outer_padding" + android:right="@dimen/chip_hint_outer_padding" + android:bottom="@dimen/chip_hint_outer_padding"/> +</shape>
\ No newline at end of file diff --git a/quickstep/recents_ui_overrides/res/layout/hint.xml b/quickstep/recents_ui_overrides/res/layout/hint.xml new file mode 100644 index 000000000..7e2d6af81 --- /dev/null +++ b/quickstep/recents_ui_overrides/res/layout/hint.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 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.quickstep.hints.HintView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="@dimen/chip_hint_height" + android:layout_gravity="center_horizontal|bottom" + android:paddingStart="@dimen/chip_hint_start_padding" + android:paddingEnd="@dimen/chip_hint_end_padding" + android:background="@drawable/chip_hint_background_light" + android:gravity="center" + android:layout_marginHorizontal="@dimen/chip_hint_horizontal_margin" + android:orientation="horizontal" + android:elevation="@dimen/chip_hint_elevation" + android:layoutDirection="ltr"> + + <ImageView + android:id="@+id/icon" + android:layout_width="@dimen/chip_icon_size" + android:layout_height="@dimen/chip_icon_size" + android:visibility="gone" + android:scaleType="fitCenter" + android:adjustViewBounds="true" + android:contentDescription="@null"/> + + <TextView + android:id="@+id/label" + android:layout_width="wrap_content" + android:layout_height="@dimen/chip_text_height" + android:paddingTop="@dimen/chip_text_top_padding" + android:paddingStart="@dimen/chip_text_start_padding" + android:fontFamily="google-sans-medium" + android:textAlignment="textStart" + android:singleLine="true" + android:textColor="@color/chip_hint_foreground_color" + android:textSize="@dimen/chip_text_size" + android:ellipsize="none" + android:includeFontPadding="true"/> + + +</com.android.quickstep.hints.HintView>
\ No newline at end of file diff --git a/quickstep/recents_ui_overrides/res/layout/hint_container.xml b/quickstep/recents_ui_overrides/res/layout/hint_container.xml new file mode 100644 index 000000000..336f63e3f --- /dev/null +++ b/quickstep/recents_ui_overrides/res/layout/hint_container.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 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.quickstep.hints.HintsContainer + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center_horizontal" + android:orientation="horizontal"/>
\ No newline at end of file diff --git a/quickstep/recents_ui_overrides/res/values/colors.xml b/quickstep/recents_ui_overrides/res/values/colors.xml new file mode 100644 index 000000000..1e8d0cc30 --- /dev/null +++ b/quickstep/recents_ui_overrides/res/values/colors.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="chip_hint_foreground_color">#fff</color> +</resources>
\ No newline at end of file diff --git a/quickstep/recents_ui_overrides/res/values/dimens.xml b/quickstep/recents_ui_overrides/res/values/dimens.xml new file mode 100644 index 000000000..b654d5c90 --- /dev/null +++ b/quickstep/recents_ui_overrides/res/values/dimens.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <dimen name="chip_hint_border_width">1dp</dimen> + <dimen name="chip_hint_corner_radius">20dp</dimen> + <dimen name="chip_hint_outer_padding">20dp</dimen> + <dimen name="chip_hint_start_padding">10dp</dimen> + <dimen name="chip_hint_end_padding">12dp</dimen> + <dimen name="chip_hint_horizontal_margin">20dp</dimen> + <dimen name="chip_hint_elevation">2dp</dimen> + <dimen name="chip_icon_size">16dp</dimen> + <dimen name="chip_text_height">26dp</dimen> + <dimen name="chip_text_top_padding">4dp</dimen> + <dimen name="chip_text_start_padding">10dp</dimen> + <dimen name="chip_text_size">14sp</dimen> +</resources>
\ No newline at end of file diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 1a61be604..0b3bd6c79 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -23,6 +23,8 @@ import android.annotation.TargetApi; import android.os.Build; import android.util.FloatProperty; +import androidx.annotation.NonNull; + import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherStateManager.AnimationConfig; @@ -30,8 +32,6 @@ import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.quickstep.views.LauncherRecentsView; import com.android.quickstep.views.RecentsView; -import androidx.annotation.NonNull; - /** * State handler for handling UI changes for {@link LauncherRecentsView}. In addition to managing * the basic view properties, this class also manages changes in the task visuals. @@ -50,6 +50,9 @@ public final class RecentsViewStateController extends if (state.overviewUi) { mRecentsView.updateEmptyMessage(); mRecentsView.resetTaskVisuals(); + mRecentsView.setHintVisibility(1); + } else { + mRecentsView.setHintVisibility(0); } } @@ -60,6 +63,7 @@ public final class RecentsViewStateController extends if (!toState.overviewUi) { builder.addOnFinishRunnable(mRecentsView::resetTaskVisuals); + mRecentsView.setHintVisibility(0); } if (toState.overviewUi) { @@ -71,6 +75,7 @@ public final class RecentsViewStateController extends updateAnim.setDuration(config.duration); builder.play(updateAnim); mRecentsView.updateEmptyMessage(); + builder.addOnFinishRunnable(() -> mRecentsView.setHintVisibility(1)); } } diff --git a/quickstep/src/com/android/quickstep/hints/HintUtil.java b/quickstep/src/com/android/quickstep/hints/HintUtil.java new file mode 100644 index 000000000..f2d40ecc4 --- /dev/null +++ b/quickstep/src/com/android/quickstep/hints/HintUtil.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 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.quickstep.hints; + +import android.app.PendingIntent; +import android.graphics.drawable.Icon; +import android.os.Bundle; + +public final class HintUtil { + + public static final String ID_KEY = "id"; + public static final String ICON_KEY = "icon"; + public static final String TEXT_KEY = "text"; + public static final String TAP_ACTION_KEY = "tap_action"; + + private HintUtil() {} + + public static Bundle makeHint(String id, Icon icon, CharSequence text) { + Bundle hint = new Bundle(); + hint.putString(ID_KEY, id); + hint.putParcelable(ICON_KEY, icon); + hint.putCharSequence(TEXT_KEY, text); + return hint; + } + + public static Bundle makeHint(Icon icon, CharSequence text, PendingIntent tapAction) { + Bundle hint = new Bundle(); + hint.putParcelable(ICON_KEY, icon); + hint.putCharSequence(TEXT_KEY, text); + hint.putParcelable(TAP_ACTION_KEY, tapAction); + return hint; + } + + public static String getId(Bundle hint) { + String id = hint.getString(ID_KEY); + if (id == null) { + throw new IllegalArgumentException("Hint does not contain an ID"); + } + return id; + } + + public static Icon getIcon(Bundle hint) { + Icon icon = hint.getParcelable(ICON_KEY); + if (icon == null) { + throw new IllegalArgumentException("Hint does not contain an icon"); + } + return icon; + } + + public static CharSequence getText(Bundle hint) { + CharSequence text = hint.getCharSequence(TEXT_KEY); + if (text == null) { + throw new IllegalArgumentException("Hint does not contain text"); + } + return text; + } + + public static PendingIntent getTapAction(Bundle hint) { + PendingIntent tapAction = hint.getParcelable(TAP_ACTION_KEY); + if (tapAction == null) { + throw new IllegalArgumentException("Hint does not contain a tap action"); + } + return tapAction; + } +} diff --git a/quickstep/src/com/android/quickstep/hints/HintView.java b/quickstep/src/com/android/quickstep/hints/HintView.java new file mode 100644 index 000000000..5399cc4ef --- /dev/null +++ b/quickstep/src/com/android/quickstep/hints/HintView.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2019 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.quickstep.hints; + +import static com.android.quickstep.hints.HintUtil.getIcon; +import static com.android.quickstep.hints.HintUtil.getText; + +import android.content.Context; +import android.graphics.drawable.Icon; +import android.os.Bundle; +import android.util.AttributeSet; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +import com.android.launcher3.R; + +public class HintView extends LinearLayout { + private ImageView mIconView; + private TextView mLabelView; + + public HintView(Context context) { + super(context); + } + + public HintView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public HintView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public HintView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public void setHint(Bundle hint) { + mLabelView.setText(getText(hint)); + + Icon icon = getIcon(hint); + if (icon == null) { + mIconView.setVisibility(GONE); + } else { + mIconView.setImageIcon(icon); + mIconView.setVisibility(VISIBLE); + } + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mIconView = findViewById(R.id.icon); + mLabelView = findViewById(R.id.label); + } +} diff --git a/quickstep/src/com/android/quickstep/hints/HintsContainer.java b/quickstep/src/com/android/quickstep/hints/HintsContainer.java new file mode 100644 index 000000000..22b121760 --- /dev/null +++ b/quickstep/src/com/android/quickstep/hints/HintsContainer.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2019 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.quickstep.hints; + +import static com.android.quickstep.hints.UiHintListenerConstants.HINTS_KEY; +import static com.android.quickstep.hints.UiHintListenerConstants.ON_HINTS_RETURNED_CODE; +import static com.android.quickstep.hints.UiInterfaceConstants.REQUEST_HINTS_CODE; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.util.AttributeSet; +import android.util.FloatProperty; +import android.util.Log; +import android.view.LayoutInflater; +import android.widget.LinearLayout; + +import androidx.annotation.Nullable; + +import com.android.launcher3.R; + +import java.util.ArrayList; + +public class HintsContainer extends LinearLayout { + + private static final String TAG = "HintsView"; + + public static final FloatProperty<HintsContainer> HINT_VISIBILITY = + new FloatProperty<HintsContainer>("hint_visibility") { + @Override + public void setValue(HintsContainer hintsContainer, float v) { + hintsContainer.setHintVisibility(v); + } + + @Override + public Float get(HintsContainer hintsContainer) { + return hintsContainer.mHintVisibility; + } + }; + + private static Intent mServiceIntent = + new Intent("com.android.systemui.action.UI_PULL_INTERFACE") + .setClassName( + "com.android.systemui.navbarhint", + "com.android.systemui.navbarhint.service.HintService"); + + @Nullable + private Messenger mHintServiceInterface; + private UiHintListener mUiHintListener; + private boolean mBound = false; + private float mHintVisibility; + + private final ServiceConnection mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + mHintServiceInterface = new Messenger(iBinder); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + mHintServiceInterface = null; + attemptBinding(); + } + + @Override + public void onBindingDied(ComponentName componentName) { + mHintServiceInterface = null; + attemptBinding(); + } + }; + + public HintsContainer(Context context) { + super(context); + } + + public HintsContainer(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public HintsContainer(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public HintsContainer(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (mUiHintListener == null) { + mUiHintListener = new UiHintListener(this); + } + if (!mBound) { + attemptBinding(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (mBound) { + getContext().unbindService(mServiceConnection); + mBound = false; + } + super.onDetachedFromWindow(); + } + + public void setHintVisibility(float v) { + if (v == 1) { + getHints(); + setVisibility(VISIBLE); + } else { + setVisibility(GONE); + } + mHintVisibility = v; + } + + private void attemptBinding() { + if (mBound) { + getContext().unbindService(mServiceConnection); + mBound = false; + } + boolean success = getContext().bindService(mServiceIntent, + mServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT); + if (success) { + mBound = true; + } else { + Log.w(TAG, "Binding to hint supplier failed"); + } + } + + private void sendOnHintTap(Bundle hint) { + if (mHintServiceInterface != null) { + Message msg = Message.obtain(null, UiInterfaceConstants.ON_HINT_TAP_CODE); + Bundle data = new Bundle(); + data.putString(UiInterfaceConstants.HINT_ID_KEY, HintUtil.getId(hint)); + data.putInt(UiInterfaceConstants.WIDTH_PX_KEY, getWidth()); + data.putInt(UiInterfaceConstants.HEIGHT_PX_KEY, getHeight()); + data.putInt(UiInterfaceConstants.HINT_SPACE_WIDTH_PX_KEY, 0); + data.putInt(UiInterfaceConstants.HINT_SPACE_HEIGHT_PX_KEY, 0); + msg.setData(data); + try { + mHintServiceInterface.send(msg); + } catch (RemoteException e) { + Log.e(TAG, "Failed to send hint tap", e); + } + } + } + + private void getHints() { + if (mHintServiceInterface != null) { + try { + Message m = Message.obtain(null, REQUEST_HINTS_CODE); + m.replyTo = new Messenger(mUiHintListener); + mHintServiceInterface.send(m); + } catch (RemoteException e) { + Log.e(TAG, "Failed to send message", e); + } + } + } + + private static class UiHintListener extends Handler { + private HintsContainer mView; + + UiHintListener(HintsContainer v) { + mView = v; + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case ON_HINTS_RETURNED_CODE: + handleHints(msg); + break; + default: + Log.e(TAG, "UiPullInterface got unrecognized code: " + msg.what); + break; + } + } + + private void handleHints(Message msg) { + Bundle bundle = msg.getData(); + ArrayList<Bundle> hints = bundle.getParcelableArrayList(HINTS_KEY); + + if (hints != null) { + mView.removeAllViews(); + + for (Bundle hint : hints) { + HintView h = (HintView) LayoutInflater.from(mView.getContext()).inflate( + R.layout.hint, mView, false); + h.setHint(hint); + h.setOnClickListener((v) -> mView.sendOnHintTap(hint)); + mView.addView(h); + } + } + } + } +} diff --git a/quickstep/src/com/android/quickstep/hints/UiHintListenerConstants.java b/quickstep/src/com/android/quickstep/hints/UiHintListenerConstants.java new file mode 100644 index 000000000..420033dd6 --- /dev/null +++ b/quickstep/src/com/android/quickstep/hints/UiHintListenerConstants.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019 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.quickstep.hints; + +public final class UiHintListenerConstants { + + private UiHintListenerConstants() {} + + // Operations + public static final int ON_HINTS_RETURNED_CODE = 5; + + // Keys + public static final String SESSION_ID_KEY = "session_id"; + public static final String HINTS_KEY = "hints"; +} diff --git a/quickstep/src/com/android/quickstep/hints/UiInterfaceConstants.java b/quickstep/src/com/android/quickstep/hints/UiInterfaceConstants.java new file mode 100644 index 000000000..01406130f --- /dev/null +++ b/quickstep/src/com/android/quickstep/hints/UiInterfaceConstants.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 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.quickstep.hints; + +public final class UiInterfaceConstants { + + private UiInterfaceConstants() {} + + // Operations + public static final int ON_HINT_TAP_CODE = 4; + + public static final int REQUEST_HINTS_CODE = 7; + + // Keys + public static final String SESSION_ID_KEY = "session_id"; + public static final String HINT_ID_KEY = "hint_id"; + public static final String WIDTH_PX_KEY = "width_px"; + public static final String HEIGHT_PX_KEY = "height_px"; + public static final String HINT_SPACE_WIDTH_PX_KEY = "hint_space_width_px"; + public static final String HINT_SPACE_HEIGHT_PX_KEY = "hint_space_height_px"; +} diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java index ed585c1d8..a06209ac4 100644 --- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java +++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java @@ -43,6 +43,8 @@ public class LayoutUtils { float extraSpace; if (dp.isVerticalBarLayout()) { extraSpace = 0; + } else if (FeatureFlags.ENABLE_HINTS_IN_OVERVIEW.get()){ + extraSpace = dp.hotseatBarSizePx + dp.verticalDragHandleSizePx + dp.chipHintHeightPx; } else { extraSpace = dp.hotseatBarSizePx + dp.verticalDragHandleSizePx; } diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index d2adef7d5..88fe2ee8a 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -21,6 +21,7 @@ import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; +import static com.android.launcher3.config.FeatureFlags.ENABLE_HINTS_IN_OVERVIEW; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import android.animation.AnimatorSet; @@ -40,8 +41,10 @@ import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.util.PendingAnimation; import com.android.launcher3.views.ScrimView; import com.android.quickstep.OverviewInteractionState; +import com.android.quickstep.hints.HintsContainer; import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.ClipAnimationHelper.TransformParams; import com.android.quickstep.util.LayoutUtils; @@ -74,6 +77,7 @@ public class LauncherRecentsView extends RecentsView<Launcher> { private float mTranslationYFactor; private final TransformParams mTransformParams = new TransformParams(); + private HintsContainer mHintsContainer; public LauncherRecentsView(Context context) { this(context, null); @@ -104,6 +108,13 @@ public class LauncherRecentsView extends RecentsView<Launcher> { setTranslationYFactor(mTranslationYFactor); } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mHintsContainer = mActivity.findViewById(R.id.hints); + mHintsContainer.setPadding(0, 0, 0, mActivity.getDeviceProfile().chipHintBottomMarginPx); + } + public void setTranslationYFactor(float translationFactor) { mTranslationYFactor = translationFactor; setTranslationY(computeTranslationYForFactor(mTranslationYFactor)); @@ -119,6 +130,12 @@ public class LauncherRecentsView extends RecentsView<Launcher> { return translationYFactor * (getPaddingBottom() - getPaddingTop()); } + public void setHintVisibility(float v) { + if (mHintsContainer != null && ENABLE_HINTS_IN_OVERVIEW.get()) { + mHintsContainer.setHintVisibility(v); + } + } + @Override public void draw(Canvas canvas) { maybeDrawEmptyMessage(canvas); @@ -170,6 +187,37 @@ public class LauncherRecentsView extends RecentsView<Launcher> { } @Override + public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) { + PendingAnimation anim = super.createTaskLauncherAnimation(tv, duration); + + if (ENABLE_HINTS_IN_OVERVIEW.get()) { + anim.anim.play(ObjectAnimator.ofFloat( + mHintsContainer, HintsContainer.HINT_VISIBILITY, 0)); + } + + return anim; + } + + @Override + public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView, + boolean shouldRemoveTask, long duration) { + PendingAnimation anim = super.createTaskDismissAnimation(taskView, animateTaskView, + shouldRemoveTask, duration); + + if (ENABLE_HINTS_IN_OVERVIEW.get()) { + anim.anim.play(ObjectAnimator.ofFloat( + mHintsContainer, HintsContainer.HINT_VISIBILITY, 0)); + anim.addEndListener(onEndListener -> { + if (!onEndListener.isSuccess) { + mHintsContainer.setHintVisibility(1); + } + }); + } + + return anim; + } + + @Override protected void getTaskSize(DeviceProfile dp, Rect outRect) { LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect); } diff --git a/res/layout/hint_container.xml b/res/layout/hint_container.xml new file mode 100644 index 000000000..75aa91341 --- /dev/null +++ b/res/layout/hint_container.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 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. +--> +<merge/>
\ No newline at end of file diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml index 87078b93e..91c37054b 100644 --- a/res/layout/launcher.xml +++ b/res/layout/launcher.xml @@ -43,6 +43,11 @@ layout="@layout/overview_panel" android:visibility="gone" /> + <include + android:id="@+id/hints" + layout="@layout/hint_container" + android:visibility="gone"/> + <!-- Keep these behind the workspace so that they are not visible when we go into AllApps --> <com.android.launcher3.pageindicators.WorkspacePageIndicator diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 078ce60a6..04e4591be 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -236,4 +236,8 @@ <dimen name="snackbar_elevation">3dp</dimen> <dimen name="snackbar_min_text_size">12sp</dimen> <dimen name="snackbar_max_text_size">14sp</dimen> + +<!-- Hints --> + <dimen name="chip_hint_height">26dp</dimen> + <dimen name="chip_hint_bottom_margin">194dp</dimen> </resources> diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 296c951bf..7aea87039 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -103,6 +103,10 @@ public class DeviceProfile { public int folderChildTextSizePx; public int folderChildDrawablePaddingPx; + // Hints + public int chipHintHeightPx; + public int chipHintBottomMarginPx; + // Hotseat public int hotseatCellHeightPx; // In portrait: size = height, in landscape: size = width @@ -200,6 +204,9 @@ public class DeviceProfile { workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x); + chipHintHeightPx = res.getDimensionPixelSize(R.dimen.chip_hint_height); + chipHintBottomMarginPx = res.getDimensionPixelSize(R.dimen.chip_hint_bottom_margin); + hotseatBarTopPaddingPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding); hotseatBarBottomPaddingPx = (isTallDevice ? 0 diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index cf16759e5..f571aa30e 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -257,7 +257,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, private RotationHelper mRotationHelper; - private final Handler mHandler = new Handler(); private final Runnable mHandleDeferredResume = this::handleDeferredResume; @@ -756,6 +755,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, if (mLauncherCallbacks != null) { mLauncherCallbacks.onStop(); } + getUserEventDispatcher().logActionCommand(Action.Command.STOP, mStateManager.getState().containerType, -1); diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java index 61467e0d2..882529dc3 100644 --- a/src/com/android/launcher3/config/BaseFlags.java +++ b/src/com/android/launcher3/config/BaseFlags.java @@ -108,6 +108,10 @@ abstract class BaseFlags { = new ToggleableGlobalSettingsFlag("SWIPE_HOME", false, "Swiping up on the nav bar goes home. Swipe and hold goes to recent apps."); + public static final TogglableFlag ENABLE_HINTS_IN_OVERVIEW = new TogglableFlag( + "ENABLE_HINTS_IN_OVERVIEW", false, + "Show chip hints and gleams on the overview screen"); + public static void initialize(Context context) { // Avoid the disk read for user builds if (Utilities.IS_DEBUG_DEVICE) { |