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 DISABLED_NO_THUMBNAIL}) 75 @Retention(RetentionPolicy.SOURCE) 76 public @interface ActionsDisabledFlags { } 77 78 public static final int DISABLED_SCROLLING = 1 << 0; 79 public static final int DISABLED_ROTATED = 1 << 1; 80 public static final int DISABLED_NO_THUMBNAIL = 1 << 2; 81 82 private static final int INDEX_CONTENT_ALPHA = 0; 83 private static final int INDEX_VISIBILITY_ALPHA = 1; 84 private static final int INDEX_FULLSCREEN_ALPHA = 2; 85 private static final int INDEX_HIDDEN_FLAGS_ALPHA = 3; 86 87 private final MultiValueAlpha mMultiValueAlpha; 88 89 @ActionsHiddenFlags 90 private int mHiddenFlags; 91 92 @ActionsDisabledFlags 93 protected int mDisabledFlags; 94 95 protected T mCallbacks; 96 OverviewActionsView(Context context)97 public OverviewActionsView(Context context) { 98 this(context, null); 99 } 100 OverviewActionsView(Context context, @Nullable AttributeSet attrs)101 public OverviewActionsView(Context context, @Nullable AttributeSet attrs) { 102 this(context, attrs, 0); 103 } 104 OverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)105 public OverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 106 super(context, attrs, defStyleAttr, 0); 107 mMultiValueAlpha = new MultiValueAlpha(this, 4); 108 mMultiValueAlpha.setUpdateVisibility(true); 109 } 110 111 @Override onFinishInflate()112 protected void onFinishInflate() { 113 super.onFinishInflate(); 114 View share = findViewById(R.id.action_share); 115 share.setOnClickListener(this); 116 findViewById(R.id.action_screenshot).setOnClickListener(this); 117 if (ENABLE_OVERVIEW_SHARE.get()) { 118 share.setVisibility(VISIBLE); 119 findViewById(R.id.share_space).setVisibility(VISIBLE); 120 } 121 } 122 123 /** 124 * Set listener for callbacks on action button taps. 125 * 126 * @param callbacks for callbacks, or {@code null} to clear the listener. 127 */ setCallbacks(T callbacks)128 public void setCallbacks(T callbacks) { 129 mCallbacks = callbacks; 130 } 131 132 @Override onClick(View view)133 public void onClick(View view) { 134 if (mCallbacks == null) { 135 return; 136 } 137 int id = view.getId(); 138 if (id == R.id.action_share) { 139 mCallbacks.onShare(); 140 } else if (id == R.id.action_screenshot) { 141 mCallbacks.onScreenshot(); 142 } 143 } 144 145 @Override onAttachedToWindow()146 protected void onAttachedToWindow() { 147 super.onAttachedToWindow(); 148 updateHiddenFlags(HIDDEN_DISABLED_FEATURE, !ENABLE_OVERVIEW_ACTIONS.get()); 149 updateHiddenFlags(HIDDEN_UNSUPPORTED_NAVIGATION, !removeShelfFromOverview(getContext())); 150 } 151 152 @Override onConfigurationChanged(Configuration newConfig)153 protected void onConfigurationChanged(Configuration newConfig) { 154 super.onConfigurationChanged(newConfig); 155 updateVerticalMargin(SysUINavigationMode.getMode(getContext())); 156 } 157 158 @Override setInsets(Rect insets)159 public void setInsets(Rect insets) { 160 mInsets.set(insets); 161 updateVerticalMargin(SysUINavigationMode.getMode(getContext())); 162 } 163 updateHiddenFlags(@ctionsHiddenFlags int visibilityFlags, boolean enable)164 public void updateHiddenFlags(@ActionsHiddenFlags int visibilityFlags, boolean enable) { 165 if (enable) { 166 mHiddenFlags |= visibilityFlags; 167 } else { 168 mHiddenFlags &= ~visibilityFlags; 169 } 170 boolean isHidden = mHiddenFlags != 0; 171 mMultiValueAlpha.getProperty(INDEX_HIDDEN_FLAGS_ALPHA).setValue(isHidden ? 0 : 1); 172 } 173 174 /** 175 * Updates the proper disabled flag to indicate whether OverviewActionsView should be enabled. 176 * Ignores DISABLED_ROTATED flag for determining enabled. Flag is used to enable/disable 177 * buttons individually, currently done for select button in subclass. 178 * 179 * @param disabledFlags The flag to update. 180 * @param enable Whether to enable the disable flag: True will cause view to be disabled. 181 */ updateDisabledFlags(@ctionsDisabledFlags int disabledFlags, boolean enable)182 public void updateDisabledFlags(@ActionsDisabledFlags int disabledFlags, boolean enable) { 183 if (enable) { 184 mDisabledFlags |= disabledFlags; 185 } else { 186 mDisabledFlags &= ~disabledFlags; 187 } 188 // 189 boolean isEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0; 190 LayoutUtils.setViewEnabled(this, isEnabled); 191 } 192 getContentAlpha()193 public AlphaProperty getContentAlpha() { 194 return mMultiValueAlpha.getProperty(INDEX_CONTENT_ALPHA); 195 } 196 getVisibilityAlpha()197 public AlphaProperty getVisibilityAlpha() { 198 return mMultiValueAlpha.getProperty(INDEX_VISIBILITY_ALPHA); 199 } 200 getFullscreenAlpha()201 public AlphaProperty getFullscreenAlpha() { 202 return mMultiValueAlpha.getProperty(INDEX_FULLSCREEN_ALPHA); 203 } 204 205 /** Updates vertical margins for different navigation mode or configuration changes. */ updateVerticalMargin(Mode mode)206 public void updateVerticalMargin(Mode mode) { 207 int bottomMargin; 208 int orientation = getResources().getConfiguration().orientation; 209 if (orientation == Configuration.ORIENTATION_LANDSCAPE) { 210 bottomMargin = 0; 211 } else if (mode == Mode.THREE_BUTTONS) { 212 bottomMargin = getResources() 213 .getDimensionPixelSize(R.dimen.overview_actions_bottom_margin_three_button); 214 } else { 215 bottomMargin = getResources() 216 .getDimensionPixelSize(R.dimen.overview_actions_bottom_margin_gesture); 217 } 218 bottomMargin += mInsets.bottom; 219 LayoutParams params = (LayoutParams) getLayoutParams(); 220 params.setMargins( 221 params.leftMargin, params.topMargin, params.rightMargin, bottomMargin); 222 } 223 } 224