diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java new file mode 100644 index 0000000000000..4f957bfcbbccd --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2018 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.systemui.statusbar.phone; + +import android.annotation.DrawableRes; +import android.annotation.IdRes; +import android.content.Context; +import android.view.View; +import com.android.systemui.statusbar.policy.KeyButtonDrawable; +import com.android.systemui.statusbar.policy.KeyButtonView; + +/** + * Simple contextual button that is added to the {@link ContextualButtonGroup}. Extend if need extra + * functionality. + */ +public class ContextualButton extends ButtonDispatcher { + + protected final @DrawableRes int mIconResId; + + /** + * Create a contextual button that will use a {@link KeyButtonView} and + * {@link KeyButtonDrawable} get and show the button from xml to its icon drawable. + * @param buttonResId the button view from xml layout + * @param iconResId icon resource to be used + */ + public ContextualButton(@IdRes int buttonResId, @DrawableRes int iconResId) { + super(buttonResId); + mIconResId = iconResId; + } + + /** + * Reload the drawable from resource id, should reapply the previous dark intensity. + */ + public void updateIcon() { + final KeyButtonDrawable currentDrawable = getImageDrawable(); + KeyButtonDrawable drawable = getNewDrawable(); + if (currentDrawable != null) { + drawable.setDarkIntensity(currentDrawable.getDarkIntensity()); + } + setImageDrawable(drawable); + } + + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + + // Stop any active animations if hidden + final KeyButtonDrawable currentDrawable = getImageDrawable(); + if (visibility != View.VISIBLE && currentDrawable != null && currentDrawable.canAnimate()) { + currentDrawable.clearAnimationCallbacks(); + currentDrawable.resetAnimation(); + } + } + + protected KeyButtonDrawable getNewDrawable() { + return KeyButtonDrawable.create(getContext(), mIconResId, false /* shadow */); + } + + protected Context getContext() { + return getCurrentView().getContext(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java new file mode 100644 index 0000000000000..1b039663ab735 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2018 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.systemui.statusbar.phone; + +import android.annotation.IdRes; +import android.annotation.NonNull; +import android.view.View; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +public class ContextualButtonGroup extends ButtonDispatcher { + private static final int INVALID_INDEX = -1; + + // List of pairs that contains the button and if the button was visible within this group + private final List mButtonData = new ArrayList<>(); + + public ContextualButtonGroup(@IdRes int containerId) { + super(containerId); + } + + /** + * Add a contextual button to the group. The order of adding increases in its priority. The + * priority is used to determine which button should be visible when setting multiple button's + * visibility {@see setButtonVisiblity}. + * @param button the button added to the group + */ + public void addButton(@NonNull ContextualButton button) { + mButtonData.add(new ButtonData(button)); + } + + public ContextualButton getContextButton(@IdRes int buttonResId) { + int index = getContextButtonIndex(buttonResId); + if (index != INVALID_INDEX) { + return mButtonData.get(index).button; + } + return null; + } + + public ContextualButton getVisibleContextButton() { + for (int i = mButtonData.size() - 1; i >= 0; --i) { + if (mButtonData.get(i).markedVisible) { + return mButtonData.get(i).button; + } + } + return null; + } + + /** + * Set the visibility of the button by {@param buttonResId} with {@param visible}. Only one + * button is shown at a time. The input button will only show up if it has higher priority than + * a previous button, otherwise it will be marked as visible and shown later if all higher + * priority buttons are invisible. Therefore hiding a button will show the next marked visible + * button. This group's view will be visible if at least one button is visible. + * @return if the button is visible after operation + * @throws RuntimeException if the input id does not match any of the ids in the group + */ + public int setButtonVisiblity(@IdRes int buttonResId, boolean visible) { + final int index = getContextButtonIndex(buttonResId); + if (index == INVALID_INDEX) { + throw new RuntimeException("Cannot find the button id of " + buttonResId + + " in context group"); + } + setVisibility(View.INVISIBLE); + mButtonData.get(index).markedVisible = visible; + + // Make all buttons invisible except the first markedVisible button + boolean alreadyFoundVisibleButton = false; + int i = mButtonData.size() - 1; + for (; i >= 0; --i) { + final ButtonData buttonData = mButtonData.get(i); + if (!alreadyFoundVisibleButton && buttonData.markedVisible) { + buttonData.setVisibility(View.VISIBLE); + setVisibility(View.VISIBLE); + alreadyFoundVisibleButton = true; + } else { + buttonData.setVisibility(View.INVISIBLE); + } + } + return mButtonData.get(index).button.getVisibility(); + } + + /** + * See if button is group visible. Group visible determines if a button can be visible when + * higher priority buttons go invisible. + * @param buttonResId the button to see if it is group visible + * @return true if button is group visible + */ + public boolean isButtonVisibleWithinGroup(@IdRes int buttonResId) { + final int index = getContextButtonIndex(buttonResId); + return index != INVALID_INDEX && mButtonData.get(index).markedVisible; + } + + /** + * Update all the icons that are attached to this group. This will get all the buttons to update + * their icons for their buttons. + */ + public void updateIcons() { + for (ButtonData data : mButtonData) { + data.button.updateIcon(); + } + } + + public void dump(PrintWriter pw) { + pw.println("ContextualButtonGroup {"); + pw.println(" getVisibleContextButton(): " + getVisibleContextButton()); + pw.println(" isVisible(): " + isVisible()); + pw.println(" mButtonData [ "); + for (int i = mButtonData.size() - 1; i >= 0; --i) { + final ButtonData data = mButtonData.get(i); + pw.println(" " + i + ": markedVisible=" + data.markedVisible + + " visible=" + data.button.getVisibility() + + " alpha=" + data.button.getAlpha()); + } + pw.println(" ]"); + pw.println(" }"); + } + + private int getContextButtonIndex(@IdRes int buttonResId) { + for (int i = 0; i < mButtonData.size(); ++i) { + if (mButtonData.get(i).button.getId() == buttonResId) { + return i; + } + } + return INVALID_INDEX; + } + + private final static class ButtonData { + ContextualButton button; + boolean markedVisible; + + ButtonData(ContextualButton button) { + this.button = button; + this.markedVisible = false; + } + + void setVisibility(int visiblity) { + button.setVisibility(visiblity); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java index 66486cedcfb59..cbbb0e3dea969 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -463,7 +463,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks { style = rotationCCW ? R.style.RotateButtonCCWStart0 : R.style.RotateButtonCWStart0; } - mNavigationBarView.updateRotateSuggestionButtonStyle(style, true); + mNavigationBarView.updateRotateSuggestionButtonStyle(style); } if (mNavigationBarWindowState != WINDOW_STATE_SHOWING) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 9d13ea22b281a..aebcb9f27e24d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -36,8 +36,6 @@ import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Point; import android.graphics.Rect; -import android.graphics.drawable.AnimatedVectorDrawable; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -46,7 +44,6 @@ import androidx.annotation.ColorInt; import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; -import android.view.ContextThemeWrapper; import android.view.Display; import android.view.MotionEvent; import android.view.Surface; @@ -59,7 +56,6 @@ import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.inputmethod.InputMethodManager; import android.widget.FrameLayout; -import com.android.settingslib.Utils; import com.android.systemui.Dependency; import com.android.systemui.DockedStackExistsListener; import com.android.systemui.Interpolators; @@ -106,10 +102,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener