1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.quickstep.views; 18 19 import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS; 20 import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SHARE; 21 import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; 22 23 import android.content.Context; 24 import android.content.res.Configuration; 25 import android.graphics.Rect; 26 import android.util.AttributeSet; 27 import android.view.View; 28 import android.view.View.OnClickListener; 29 import android.widget.FrameLayout; 30 31 import androidx.annotation.IntDef; 32 import androidx.annotation.Nullable; 33 34 import com.android.launcher3.Insettable; 35 import com.android.launcher3.R; 36 import com.android.launcher3.util.MultiValueAlpha; 37 import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; 38 import com.android.quickstep.SysUINavigationMode; 39 import com.android.quickstep.SysUINavigationMode.Mode; 40 import com.android.quickstep.TaskOverlayFactory.OverlayUICallbacks; 41 import com.android.quickstep.util.LayoutUtils; 42 43 import java.lang.annotation.Retention; 44 import java.lang.annotation.RetentionPolicy; 45 46 /** 47 * View for showing action buttons in Overview 48 */ 49 public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayout 50 implements OnClickListener, Insettable { 51 52 private final Rect mInsets = new Rect(); 53 54 @IntDef(flag = true, value = { 55 HIDDEN_UNSUPPORTED_NAVIGATION, 56 HIDDEN_DISABLED_FEATURE, 57 HIDDEN_NON_ZERO_ROTATION, 58 HIDDEN_NO_TASKS, 59 HIDDEN_GESTURE_RUNNING, 60 HIDDEN_NO_RECENTS}) 61 @Retention(RetentionPolicy.SOURCE) 62 public @interface ActionsHiddenFlags { } 63 64 public static final int HIDDEN_UNSUPPORTED_NAVIGATION = 1 << 0; 65 public static final int HIDDEN_DISABLED_FEATURE = 1 << 1; 66 public static final int HIDDEN_NON_ZERO_ROTATION = 1 << 2; 67 public static final int HIDDEN_NO_TASKS = 1 << 3; 68 public static final int HIDDEN_GESTURE_RUNNING = 1 << 4; 69 public static final int HIDDEN_NO_RECENTS = 1 << 5; 70 71 @IntDef(flag = true, value = { 72 DISABLED_SCROLLING, 73 DISABLED_ROTATED}) 74 @Retention(RetentionPolicy.SOURCE) 75 public @interface ActionsDisabledFlags { } 76 77 public static final int DISABLED_SCROLLING = 1 << 0; 78 public static final int DISABLED_ROTATED = 1 << 1; 79 80 private static final int INDEX_CONTENT_ALPHA = 0; 81 private static final int INDEX_VISIBILITY_ALPHA = 1; 82 private static final int INDEX_FULLSCREEN_ALPHA = 2; 83 private static final int INDEX_HIDDEN_FLAGS_ALPHA = 3; 84 85 private final MultiValueAlpha mMultiValueAlpha; 86 87 @ActionsHiddenFlags 88 private int mHiddenFlags; 89 90 @ActionsDisabledFlags 91 protected int mDisabledFlags; 92 93 protected T mCallbacks; 94 OverviewActionsView(Context context)95 public OverviewActionsView(Context context) { 96 this(context, null); 97 } 98 OverviewActionsView(Context context, @Nullable AttributeSet attrs)99 public OverviewActionsView(Context context, @Nullable AttributeSet attrs) { 100 this(context, attrs, 0); 101 } 102 OverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)103 public OverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 104 super(context, attrs, defStyleAttr, 0); 105 mMultiValueAlpha = new MultiValueAlpha(this, 4); 106 } 107 108 @Override onFinishInflate()109 protected void onFinishInflate() { 110 super.onFinishInflate(); 111 View share = findViewById(R.id.action_share); 112 share.setOnClickListener(this); 113 findViewById(R.id.action_screenshot).setOnClickListener(this); 114 if (ENABLE_OVERVIEW_SHARE.get()) { 115 share.setVisibility(VISIBLE); 116 findViewById(R.id.share_space).setVisibility(VISIBLE); 117 } 118 } 119 120 /** 121 * Set listener for callbacks on action button taps. 122 * 123 * @param callbacks for callbacks, or {@code null} to clear the listener. 124 */ setCallbacks(T callbacks)125 public void setCallbacks(T callbacks) { 126 mCallbacks = callbacks; 127 } 128 129 @Override onClick(View view)130 public void onClick(View view) { 131 if (mCallbacks == null) { 132 return; 133 } 134 int id = view.getId(); 135 if (id == R.id.action_share) { 136 mCallbacks.onShare(); 137 } else if (id == R.id.action_screenshot) { 138 mCallbacks.onScreenshot(); 139 } 140 } 141 142 @Override onAttachedToWindow()143 protected void onAttachedToWindow() { 144 super.onAttachedToWindow(); 145 updateHiddenFlags(HIDDEN_DISABLED_FEATURE, !ENABLE_OVERVIEW_ACTIONS.get()); 146 updateHiddenFlags(HIDDEN_UNSUPPORTED_NAVIGATION, !removeShelfFromOverview(getContext())); 147 } 148 149 @Override onConfigurationChanged(Configuration newConfig)150 protected void onConfigurationChanged(Configuration newConfig) { 151 super.onConfigurationChanged(newConfig); 152 updateVerticalMargin(SysUINavigationMode.getMode(getContext())); 153 } 154 155 @Override setInsets(Rect insets)156 public void setInsets(Rect insets) { 157 mInsets.set(insets); 158 updateVerticalMargin(SysUINavigationMode.getMode(getContext())); 159 } 160 updateHiddenFlags(@ctionsHiddenFlags int visibilityFlags, boolean enable)161 public void updateHiddenFlags(@ActionsHiddenFlags int visibilityFlags, boolean enable) { 162 if (enable) { 163 mHiddenFlags |= visibilityFlags; 164 } else { 165 mHiddenFlags &= ~visibilityFlags; 166 } 167 boolean isHidden = mHiddenFlags != 0; 168 mMultiValueAlpha.getProperty(INDEX_HIDDEN_FLAGS_ALPHA).setValue(isHidden ? 0 : 1); 169 setVisibility(isHidden ? INVISIBLE : VISIBLE); 170 } 171 172 /** 173 * Updates the proper disabled flag to indicate whether OverviewActionsView should be enabled. 174 * Ignores DISABLED_ROTATED flag for determining enabled. Flag is used to enable/disable 175 * buttons individually, currently done for select button in subclass. 176 * 177 * @param disabledFlags The flag to update. 178 * @param enable Whether to enable the disable flag: True will cause view to be disabled. 179 */ updateDisabledFlags(@ctionsDisabledFlags int disabledFlags, boolean enable)180 public void updateDisabledFlags(@ActionsDisabledFlags int disabledFlags, boolean enable) { 181 if (enable) { 182 mDisabledFlags |= disabledFlags; 183 } else { 184 mDisabledFlags &= ~disabledFlags; 185 } 186 // 187 boolean isEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0; 188 LayoutUtils.setViewEnabled(this, isEnabled); 189 } 190 getContentAlpha()191 public AlphaProperty getContentAlpha() { 192 return mMultiValueAlpha.getProperty(INDEX_CONTENT_ALPHA); 193 } 194 getVisibilityAlpha()195 public AlphaProperty getVisibilityAlpha() { 196 return mMultiValueAlpha.getProperty(INDEX_VISIBILITY_ALPHA); 197 } 198 getFullscreenAlpha()199 public AlphaProperty getFullscreenAlpha() { 200 return mMultiValueAlpha.getProperty(INDEX_FULLSCREEN_ALPHA); 201 } 202 203 /** Updates vertical margins for different navigation mode or configuration changes. */ updateVerticalMargin(Mode mode)204 public void updateVerticalMargin(Mode mode) { 205 int bottomMargin; 206 int orientation = getResources().getConfiguration().orientation; 207 if (orientation == Configuration.ORIENTATION_LANDSCAPE) { 208 bottomMargin = 0; 209 } else if (mode == Mode.THREE_BUTTONS) { 210 bottomMargin = getResources() 211 .getDimensionPixelSize(R.dimen.overview_actions_bottom_margin_three_button); 212 } else { 213 bottomMargin = getResources() 214 .getDimensionPixelSize(R.dimen.overview_actions_bottom_margin_gesture); 215 } 216 bottomMargin += mInsets.bottom; 217 LayoutParams params = (LayoutParams) getLayoutParams(); 218 params.setMargins( 219 params.leftMargin, params.topMargin, params.rightMargin, bottomMargin); 220 } 221 } 222