Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 184af56d authored by Aaron Heuckroth's avatar Aaron Heuckroth Committed by Android (Google) Code Review
Browse files

Merge "Extract GlobalActionsLayout to an abstract class."

parents a462966c f708d47e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.HardwareUiLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@id/global_actions_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="top|right"
+3 −0
Original line number Diff line number Diff line
@@ -114,5 +114,8 @@
    <item type="id" name="aod_mask_transition_progress_tag" />
    <item type="id" name="aod_mask_transition_progress_end_tag" />
    <item type="id" name="aod_mask_transition_progress_start_tag" />

    <!-- Global Actions Menu -->
    <item type="id" name="global_actions_view" />
</resources>
+44 −33
Original line number Diff line number Diff line
@@ -37,23 +37,25 @@ import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.leak.RotationUtils;

public class HardwareUiLayout extends LinearLayout implements Tunable {
/**
 * Layout for placing two containers at a specific physical position on the device, relative to the
 * device's hardware, regardless of screen rotation.
 */
public class HardwareUiLayout extends MultiListLayout implements Tunable {

    private static final String EDGE_BLEED = "sysui_hwui_edge_bleed";
    private static final String ROUNDED_DIVIDER = "sysui_hwui_rounded_divider";
    private final int[] mTmp2 = new int[2];
    private View mList;
    private View mSeparatedView;
    private ViewGroup mList;
    private ViewGroup mSeparatedView;
    private int mOldHeight;
    private boolean mAnimating;
    private AnimatorSet mAnimation;
    private View mDivision;
    private boolean mHasOutsideTouch;
    private HardwareBgDrawable mListBackground;
    private HardwareBgDrawable mSeparatedViewBackground;
    private Animator mAnimator;
    private boolean mCollapse;
    private boolean mHasSeparatedButton;
    private int mEndPoint;
    private boolean mEdgeBleed;
    private boolean mRoundedDivider;
@@ -66,6 +68,35 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
        updateSettings();
    }

    @Override
    protected ViewGroup getSeparatedView() {
        return findViewById(com.android.systemui.R.id.separated_button);
    }

    @Override
    protected ViewGroup getListView() {
        return findViewById(android.R.id.list);
    }

    @Override
    public void removeAllItems() {
        if (mList != null) {
            mList.removeAllViews();
        }
        if (mSeparatedView != null) {
            mSeparatedView.removeAllViews();
        }
    }

    @Override
    public ViewGroup getParentView(boolean separated, int index) {
        if (separated) {
            return getSeparatedView();
        } else {
            return getListView();
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
@@ -137,9 +168,9 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mList == null) {
            if (getChildCount() != 0) {
                mList = getChildAt(0);
                mList = getListView();
                mList.setBackground(mListBackground);
                mSeparatedView = getChildAt(1);
                mSeparatedView = getSeparatedView();
                mSeparatedView.setBackground(mSeparatedViewBackground);
                updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
                mOldHeight = mList.getMeasuredHeight();
@@ -187,7 +218,7 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
        } else {
            rotateLeft();
        }
        if (mHasSeparatedButton) {
        if (mHasSeparatedView) {
            if (from == ROTATION_SEASCAPE || to == ROTATION_SEASCAPE) {
                // Separated view has top margin, so seascape separated view need special rotation,
                // not a full left or right rotation.
@@ -408,8 +439,8 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
        if (mList == null) return;
        // If got separated button, setRotatedBackground to false,
        // all items won't get white background.
        mListBackground.setRotatedBackground(mHasSeparatedButton);
        mSeparatedViewBackground.setRotatedBackground(mHasSeparatedButton);
        mListBackground.setRotatedBackground(mHasSeparatedView);
        mSeparatedViewBackground.setRotatedBackground(mHasSeparatedView);
        if (mDivision != null && mDivision.getVisibility() == VISIBLE) {
            int index = mRotatedBackground ? 0 : 1;
            mDivision.getLocationOnScreen(mTmp2);
@@ -460,21 +491,21 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
            case RotationUtils.ROTATION_LANDSCAPE:
                defaultTopPadding = getPaddingLeft();
                viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth();
                separatedViewTopMargin = mHasSeparatedButton ? params.leftMargin : 0;
                separatedViewTopMargin = mHasSeparatedView ? params.leftMargin : 0;
                screenHeight = getMeasuredWidth();
                targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.TOP;
                break;
            case RotationUtils.ROTATION_SEASCAPE:
                defaultTopPadding = getPaddingRight();
                viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth();
                separatedViewTopMargin = mHasSeparatedButton ? params.leftMargin : 0;
                separatedViewTopMargin = mHasSeparatedView ? params.leftMargin : 0;
                screenHeight = getMeasuredWidth();
                targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM;
                break;
            default: // Portrait
                defaultTopPadding = getPaddingTop();
                viewsTotalHeight = mList.getMeasuredHeight() + mSeparatedView.getMeasuredHeight();
                separatedViewTopMargin = mHasSeparatedButton ? params.topMargin : 0;
                separatedViewTopMargin = mHasSeparatedView ? params.topMargin : 0;
                screenHeight = getMeasuredHeight();
                targetGravity = Gravity.CENTER_VERTICAL|Gravity.RIGHT;
                break;
@@ -491,30 +522,10 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
        return super.getOutlineProvider();
    }

    public void setOutsideTouchListener(OnClickListener onClickListener) {
        mHasOutsideTouch = true;
        requestLayout();
        setOnClickListener(onClickListener);
        setClickable(true);
        setFocusable(true);
    }

    public void setCollapse() {
        mCollapse = true;
    }

    public void setHasSeparatedButton(boolean hasSeparatedButton) {
        mHasSeparatedButton = hasSeparatedButton;
    }

    public static HardwareUiLayout get(View v) {
        if (v instanceof HardwareUiLayout) return (HardwareUiLayout) v;
        if (v.getParent() instanceof View) {
            return get((View) v.getParent());
        }
        return null;
    }

    private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> {
        if (mHasOutsideTouch || (mList == null)) {
            inoutInfo.setTouchableInsets(
+124 −0
Original line number Diff line number Diff line
/*
 * 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.systemui;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

/**
 * Layout class representing the Global Actions menu which appears when the power button is held.
 */
public abstract class MultiListLayout extends LinearLayout {
    boolean mHasOutsideTouch;
    boolean mHasSeparatedView;

    int mExpectedSeparatedItemCount;
    int mExpectedListItemCount;

    public MultiListLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    protected abstract ViewGroup getSeparatedView();

    protected abstract ViewGroup getListView();

    /**
     * Removes all child items from the separated and list views, if they exist.
     */
    public abstract void removeAllItems();

    /**
     * Get the parent view which will be used to contain the item at the specified index.
     * @param separated Whether or not this index refers to a position in the separated or list
     *                  container.
     * @param index The index of the item within the container.
     * @return The parent ViewGroup which will be used to contain the specified item
     * after it has been added to the layout.
     */
    public abstract ViewGroup getParentView(boolean separated, int index);

    /**
     * Sets the divided view, which may have a differently-colored background.
     */
    public abstract void setDivisionView(View v);

    /**
     * Set the view accessibility delegate for the list view container.
     */
    public void setListViewAccessibilityDelegate(View.AccessibilityDelegate delegate) {
        getListView().setAccessibilityDelegate(delegate);
    }

    protected void setSeparatedViewVisibility(boolean visible) {
        getSeparatedView().setVisibility(visible ? View.VISIBLE : View.GONE);
    }

    /**
     * Sets the number of items expected to be rendered in the separated container. This allows the
     * layout to correctly determine which parent containers will be used for items before they have
     * beenadded to the layout.
     * @param count The number of items expected.
     */
    public void setExpectedSeparatedItemCount(int count) {
        mExpectedSeparatedItemCount = count;
    }

    /**
     * Sets the number of items expected to be rendered in the list container. This allows the
     * layout to correctly determine which parent containers will be used for items before they have
     * beenadded to the layout.
     * @param count The number of items expected.
     */
    public void setExpectedListItemCount(int count) {
        mExpectedListItemCount = count;
    }

    /**
     * Sets whether the separated view should be shown, and handles updating visibility on
     * that view.
     */
    public void setHasSeparatedView(boolean hasSeparatedView) {
        mHasSeparatedView = hasSeparatedView;
        setSeparatedViewVisibility(hasSeparatedView);
    }

    /**
     * Sets this layout to respond to an outside touch listener.
     */
    public void setOutsideTouchListener(OnClickListener onClickListener) {
        mHasOutsideTouch = true;
        requestLayout();
        setOnClickListener(onClickListener);
        setClickable(true);
        setFocusable(true);
    }

    /**
     * Retrieve the MultiListLayout associated with the given view.
     */
    public static MultiListLayout get(View v) {
        if (v instanceof MultiListLayout) return (MultiListLayout) v;
        if (v.getParent() instanceof View) {
            return get((View) v.getParent());
        }
        return null;
    }
}
+70 −29
Original line number Diff line number Diff line
@@ -67,10 +67,8 @@ import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.android.internal.R;
@@ -86,8 +84,8 @@ import com.android.internal.util.ScreenRecordHelper;
import com.android.internal.util.ScreenshotHelper;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
import com.android.systemui.HardwareUiLayout;
import com.android.systemui.Interpolators;
import com.android.systemui.MultiListLayout;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -490,6 +488,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
        public boolean showBeforeProvisioning() {
            return true;
        }

        @Override
        public boolean shouldBeSeparated() {
            return true;
        }
    }

    private final class RestartAction extends SinglePressAction implements LongPressAction {
@@ -926,6 +929,34 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
            return getItem(position).isEnabled();
        }

        public ArrayList<Action> getSeparatedActions(boolean shouldUseSeparatedView) {
            ArrayList<Action> separatedActions = new ArrayList<Action>();
            if (!shouldUseSeparatedView) {
                return separatedActions;
            }
            for (int i = 0; i < mItems.size(); i++) {
                final Action action = mItems.get(i);
                if (action.shouldBeSeparated()) {
                    separatedActions.add(action);
                }
            }
            return separatedActions;
        }

        public ArrayList<Action> getListActions(boolean shouldUseSeparatedView) {
            if (!shouldUseSeparatedView) {
                return new ArrayList<Action>(mItems);
            }
            ArrayList<Action> listActions = new ArrayList<Action>();
            for (int i = 0; i < mItems.size(); i++) {
                final Action action = mItems.get(i);
                if (!action.shouldBeSeparated()) {
                    listActions.add(action);
                }
            }
            return listActions;
        }

        @Override
        public boolean areAllItemsEnabled() {
            return false;
@@ -965,7 +996,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
            View view = action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
            // Everything but screenshot, the last item, gets white background.
            if (position == getCount() - 1) {
                HardwareUiLayout.get(parent).setDivisionView(view);
                MultiListLayout.get(parent).setDivisionView(view);
            }
            return view;
        }
@@ -1004,6 +1035,10 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
        boolean showBeforeProvisioning();

        boolean isEnabled();

        default boolean shouldBeSeparated() {
            return false;
        }
    }

    /**
@@ -1423,9 +1458,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,

        private final Context mContext;
        private final MyAdapter mAdapter;
        private final LinearLayout mListView;
        private final FrameLayout mSeparatedView;
        private final HardwareUiLayout mHardwareLayout;
        private final MultiListLayout mGlobalActionsLayout;
        private final OnClickListener mClickListener;
        private final OnItemLongClickListener mLongClickListener;
        private final GradientDrawable mGradientDrawable;
@@ -1466,16 +1499,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
            window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);

            setContentView(com.android.systemui.R.layout.global_actions_wrapped);
            mListView = findViewById(android.R.id.list);
            mSeparatedView = findViewById(com.android.systemui.R.id.separated_button);
            if (!mShouldDisplaySeparatedButton) {
                mSeparatedView.setVisibility(View.GONE);
            }
            mHardwareLayout = HardwareUiLayout.get(mListView);
            mHardwareLayout.setOutsideTouchListener(view -> dismiss());
            mHardwareLayout.setHasSeparatedButton(mShouldDisplaySeparatedButton);
            setTitle(R.string.global_actions);
            mListView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
            mGlobalActionsLayout = (MultiListLayout)
                    findViewById(com.android.systemui.R.id.global_actions_view);
            mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss());
            mGlobalActionsLayout.setHasSeparatedView(mShouldDisplaySeparatedButton);
            mGlobalActionsLayout.setListViewAccessibilityDelegate(new View.AccessibilityDelegate() {
                @Override
                public boolean dispatchPopulateAccessibilityEvent(
                        View host, AccessibilityEvent event) {
@@ -1484,20 +1512,33 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
                    return true;
                }
            });
            setTitle(R.string.global_actions);
        }

        private void updateList() {
            mListView.removeAllViews();
            mSeparatedView.removeAllViews();
            mGlobalActionsLayout.removeAllItems();
            ArrayList<Action> separatedActions =
                    mAdapter.getSeparatedActions(mShouldDisplaySeparatedButton);
            ArrayList<Action> listActions = mAdapter.getListActions(mShouldDisplaySeparatedButton);
            mGlobalActionsLayout.setExpectedListItemCount(listActions.size());
            mGlobalActionsLayout.setExpectedSeparatedItemCount(separatedActions.size());

            for (int i = 0; i < mAdapter.getCount(); i++) {
                ViewGroup parentView = mShouldDisplaySeparatedButton && i == mAdapter.getCount() - 1
                        ? mSeparatedView : mListView;
                View v = mAdapter.getView(i, null, parentView);
                Action action = mAdapter.getItem(i);
                int separatedIndex = separatedActions.indexOf(action);
                ViewGroup parent;
                if (separatedIndex != -1) {
                    parent = mGlobalActionsLayout.getParentView(true, separatedIndex);
                } else {
                    int listIndex = listActions.indexOf(action);
                    parent = mGlobalActionsLayout.getParentView(false, listIndex);
                }
                View v = mAdapter.getView(i, null, parent);
                final int pos = i;
                v.setOnClickListener(view -> mClickListener.onClick(this, pos));
                v.setOnLongClickListener(view ->
                        mLongClickListener.onItemLongClick(null, v, pos, 0));
                parentView.addView(v);
                parent.addView(v);
            }
        }

@@ -1543,9 +1584,9 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
            super.show();
            mShowing = true;
            mGradientDrawable.setAlpha(0);
            mHardwareLayout.setTranslationX(getAnimTranslation());
            mHardwareLayout.setAlpha(0);
            mHardwareLayout.animate()
            mGlobalActionsLayout.setTranslationX(getAnimTranslation());
            mGlobalActionsLayout.setAlpha(0);
            mGlobalActionsLayout.animate()
                    .alpha(1)
                    .translationX(0)
                    .setDuration(300)
@@ -1564,9 +1605,9 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
                return;
            }
            mShowing = false;
            mHardwareLayout.setTranslationX(0);
            mHardwareLayout.setAlpha(1);
            mHardwareLayout.animate()
            mGlobalActionsLayout.setTranslationX(0);
            mGlobalActionsLayout.setAlpha(1);
            mGlobalActionsLayout.animate()
                    .alpha(0)
                    .translationX(getAnimTranslation())
                    .setDuration(300)