Merge "Creates a new grid-based global actions menu on power button hold."
This commit is contained in:
committed by
Android (Google) Code Review
commit
5d1f0e0058
@@ -40,6 +40,7 @@ public class FeatureFlagUtils {
|
||||
public static final String SAFETY_HUB = "settings_safety_hub";
|
||||
public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
|
||||
public static final String AOD_IMAGEWALLPAPER_ENABLED = "settings_aod_imagewallpaper_enabled";
|
||||
public static final String GLOBAL_ACTIONS_GRID_ENABLED = "settings_global_actions_grid_enabled";
|
||||
|
||||
private static final Map<String, String> DEFAULT_FLAGS;
|
||||
private static final Set<String> OBSERVABLE_FLAGS;
|
||||
@@ -60,6 +61,7 @@ public class FeatureFlagUtils {
|
||||
DEFAULT_FLAGS.put(SAFETY_HUB, "false");
|
||||
DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
|
||||
DEFAULT_FLAGS.put(AOD_IMAGEWALLPAPER_ENABLED, "false");
|
||||
DEFAULT_FLAGS.put(GLOBAL_ACTIONS_GRID_ENABLED, "false");
|
||||
|
||||
OBSERVABLE_FLAGS = new HashSet<>();
|
||||
OBSERVABLE_FLAGS.add(AOD_IMAGEWALLPAPER_ENABLED);
|
||||
|
||||
83
packages/SystemUI/res/layout/global_actions_grid.xml
Normal file
83
packages/SystemUI/res/layout/global_actions_grid.xml
Normal file
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.android.systemui.globalactions.GlobalActionsGridLayout
|
||||
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:orientation="horizontal"
|
||||
android:clipToPadding="false"
|
||||
android:theme="@style/qs_theme"
|
||||
android:gravity="bottom|center"
|
||||
android:clipChildren="false"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_height="290dp"
|
||||
android:layout_width="412dp"
|
||||
android:gravity="bottom"
|
||||
android:padding="0dp"
|
||||
android:layout_marginBottom="@dimen/global_actions_grid_container_bottom_margin"
|
||||
>
|
||||
<!-- For separated items-->
|
||||
<LinearLayout
|
||||
android:id="@+id/separated_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/global_actions_grid_side_margin"
|
||||
android:layout_marginRight="@dimen/global_actions_grid_side_margin"
|
||||
android:paddingTop="@dimen/global_actions_grid_top_padding"
|
||||
android:paddingLeft="@dimen/global_actions_grid_left_padding"
|
||||
android:paddingBottom="@dimen/global_actions_grid_bottom_padding"
|
||||
android:paddingRight="@dimen/global_actions_grid_right_padding"
|
||||
android:orientation="vertical"
|
||||
android:background="?android:attr/colorBackgroundFloating"
|
||||
android:translationZ="@dimen/global_actions_translate"
|
||||
/>
|
||||
|
||||
<Space android:layout_width="match_parent" android:layout_height="2dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<!-- Grid of action items -->
|
||||
<com.android.systemui.globalactions.ListGridLayout
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="right"
|
||||
android:orientation="horizontal"
|
||||
android:layoutDirection="rtl"
|
||||
android:layout_marginRight="@dimen/global_actions_grid_side_margin"
|
||||
android:translationZ="@dimen/global_actions_translate"
|
||||
android:paddingLeft="@dimen/global_actions_grid_left_padding"
|
||||
android:paddingRight="@dimen/global_actions_grid_right_padding"
|
||||
android:paddingTop="@dimen/global_actions_grid_top_padding"
|
||||
android:paddingBottom="@dimen/global_actions_grid_bottom_padding"
|
||||
android:background="?android:attr/colorBackgroundFloating"
|
||||
>
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:visibility="gone"
|
||||
android:gravity="bottom"
|
||||
android:orientation="vertical"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:visibility="gone"
|
||||
android:gravity="bottom"
|
||||
android:orientation="vertical"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:visibility="gone"
|
||||
android:gravity="bottom"
|
||||
android:orientation="vertical"
|
||||
/>
|
||||
</com.android.systemui.globalactions.ListGridLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</com.android.systemui.globalactions.GlobalActionsGridLayout>
|
||||
61
packages/SystemUI/res/layout/global_actions_grid_item.xml
Normal file
61
packages/SystemUI/res/layout/global_actions_grid_item.xml
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 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.
|
||||
-->
|
||||
|
||||
<!-- RelativeLayouts have an issue enforcing minimum heights, so just
|
||||
work around this for now with LinearLayouts. -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="@dimen/global_actions_grid_item_vertical_margin"
|
||||
android:layout_marginBottom="@dimen/global_actions_grid_item_vertical_margin"
|
||||
android:layout_marginLeft="@dimen/global_actions_grid_item_side_margin"
|
||||
android:layout_marginRight="@dimen/global_actions_grid_item_side_margin"
|
||||
android:paddingEnd="4dip"
|
||||
android:paddingStart="4dip">
|
||||
|
||||
<ImageView
|
||||
android:id="@*android:id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="center"
|
||||
android:alpha="?android:attr/primaryContentAlpha"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@*android:id/message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_horizontal"
|
||||
android:paddingTop="10dp"
|
||||
android:gravity="center"
|
||||
android:textSize="12sp"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@*android:id/status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_horizontal"
|
||||
android:gravity="center"
|
||||
android:textColor="?android:attr/textColorTertiary"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
</LinearLayout>
|
||||
@@ -834,6 +834,18 @@
|
||||
|
||||
<dimen name="global_actions_panel_width">120dp</dimen>
|
||||
|
||||
<dimen name="global_actions_grid_container_bottom_margin">16dp</dimen>
|
||||
|
||||
<dimen name="global_actions_grid_side_margin">4dp</dimen>
|
||||
<dimen name="global_actions_grid_separated_panel_width">104dp</dimen>
|
||||
<dimen name="global_actions_grid_top_padding">8dp</dimen>
|
||||
<dimen name="global_actions_grid_bottom_padding">8dp</dimen>
|
||||
<dimen name="global_actions_grid_left_padding">4dp</dimen>
|
||||
<dimen name="global_actions_grid_right_padding">4dp</dimen>
|
||||
|
||||
<dimen name="global_actions_grid_item_side_margin">12dp</dimen>
|
||||
<dimen name="global_actions_grid_item_vertical_margin">8dp</dimen>
|
||||
|
||||
<dimen name="global_actions_top_padding">120dp</dimen>
|
||||
|
||||
<dimen name="global_actions_padding">12dp</dimen>
|
||||
|
||||
@@ -26,11 +26,11 @@ 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;
|
||||
protected boolean mHasOutsideTouch;
|
||||
protected boolean mHasSeparatedView;
|
||||
|
||||
int mExpectedSeparatedItemCount;
|
||||
int mExpectedListItemCount;
|
||||
protected int mExpectedSeparatedItemCount;
|
||||
protected int mExpectedListItemCount;
|
||||
|
||||
public MultiListLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
@@ -1090,9 +1090,16 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
}
|
||||
}
|
||||
|
||||
protected int getActionLayoutId(Context context) {
|
||||
if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.GLOBAL_ACTIONS_GRID_ENABLED)) {
|
||||
return com.android.systemui.R.layout.global_actions_grid_item;
|
||||
}
|
||||
return com.android.systemui.R.layout.global_actions_item;
|
||||
}
|
||||
|
||||
public View create(
|
||||
Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
|
||||
View v = inflater.inflate(com.android.systemui.R.layout.global_actions_item, parent,
|
||||
View v = inflater.inflate(getActionLayoutId(context), parent,
|
||||
false);
|
||||
|
||||
ImageView icon = (ImageView) v.findViewById(R.id.icon);
|
||||
@@ -1498,7 +1505,8 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
window.setBackgroundDrawable(mGradientDrawable);
|
||||
window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
|
||||
|
||||
setContentView(com.android.systemui.R.layout.global_actions_wrapped);
|
||||
|
||||
setContentView(getGlobalActionsLayoutId(context));
|
||||
mGlobalActionsLayout = (MultiListLayout)
|
||||
findViewById(com.android.systemui.R.id.global_actions_view);
|
||||
mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss());
|
||||
@@ -1515,6 +1523,13 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
setTitle(R.string.global_actions);
|
||||
}
|
||||
|
||||
private int getGlobalActionsLayoutId(Context context) {
|
||||
if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.GLOBAL_ACTIONS_GRID_ENABLED)) {
|
||||
return com.android.systemui.R.layout.global_actions_grid;
|
||||
}
|
||||
return com.android.systemui.R.layout.global_actions_wrapped;
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
mGlobalActionsLayout.removeAllItems();
|
||||
ArrayList<Action> separatedActions =
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.globalactions;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.systemui.HardwareBgDrawable;
|
||||
import com.android.systemui.MultiListLayout;
|
||||
|
||||
/**
|
||||
* Grid-based implementation of the button layout created by the global actions dialog.
|
||||
*/
|
||||
public class GlobalActionsGridLayout extends MultiListLayout {
|
||||
|
||||
boolean mBackgroundsSet;
|
||||
|
||||
public GlobalActionsGridLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
private void setBackgrounds() {
|
||||
HardwareBgDrawable listBackground = new HardwareBgDrawable(true, true, getContext());
|
||||
HardwareBgDrawable separatedViewBackground = new HardwareBgDrawable(true, true,
|
||||
getContext());
|
||||
getListView().setBackground(listBackground);
|
||||
getSeparatedView().setBackground(separatedViewBackground);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
// backgrounds set only once, the first time onMeasure is called after inflation
|
||||
if (getListView() != null && !mBackgroundsSet) {
|
||||
setBackgrounds();
|
||||
mBackgroundsSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpectedListItemCount(int count) {
|
||||
mExpectedListItemCount = count;
|
||||
getListView().setExpectedCount(count);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewGroup getSeparatedView() {
|
||||
return findViewById(com.android.systemui.R.id.separated_button);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListGridLayout getListView() {
|
||||
return findViewById(android.R.id.list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllItems() {
|
||||
ViewGroup separatedList = getSeparatedView();
|
||||
ListGridLayout list = getListView();
|
||||
if (separatedList != null) {
|
||||
separatedList.removeAllViews();
|
||||
}
|
||||
if (list != null) {
|
||||
list.removeAllItems();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewGroup getParentView(boolean separated, int index) {
|
||||
if (separated) {
|
||||
return getSeparatedView();
|
||||
} else {
|
||||
return getListView().getParentView(index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not used in this implementation of the Global Actions Menu, but necessary for some others.
|
||||
*/
|
||||
@Override
|
||||
public void setDivisionView(View v) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.globalactions;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
/**
|
||||
* Layout which uses nested LinearLayouts to create a grid with the following behavior:
|
||||
*
|
||||
* * Try to maintain a 'square' grid (equal number of columns and rows) based on the expected item
|
||||
* count.
|
||||
* * Display and hide sub-lists as needed, depending on the expected item count.
|
||||
* * Favor bias toward having more rows or columns depending on the orientation of the device
|
||||
* (TODO(123344999): Implement this, currently always favors adding more rows.)
|
||||
* * Change the orientation (horizontal vs. vertical) of the container and sub-lists to act as rows
|
||||
* or columns depending on the orientation of the device.
|
||||
* (TODO(123344999): Implement this, currently always columns.)
|
||||
*
|
||||
* While we could implement this behavior with a GridLayout, it would take significantly more
|
||||
* time and effort, and would require more substantial refactoring of the existing code in
|
||||
* GlobalActionsDialog, since it would require manipulation of the child items themselves.
|
||||
*
|
||||
*/
|
||||
|
||||
public class ListGridLayout extends LinearLayout {
|
||||
private int mExpectedCount;
|
||||
private int mRows;
|
||||
private int mColumns;
|
||||
|
||||
public ListGridLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all items from this grid.
|
||||
*/
|
||||
public void removeAllItems() {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
ViewGroup subList = (ViewGroup) getChildAt(i);
|
||||
if (subList != null) {
|
||||
subList.removeAllViews();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent view associated with the item which should be placed at the given position.
|
||||
*/
|
||||
public ViewGroup getParentView(int index) {
|
||||
ViewGroup firstParent = (ViewGroup) getChildAt(0);
|
||||
if (mRows == 0) {
|
||||
return firstParent;
|
||||
}
|
||||
int column = (int) Math.floor(index / mRows);
|
||||
ViewGroup parent = (ViewGroup) getChildAt(column);
|
||||
return parent != null ? parent : firstParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the expected number of items that this grid will be responsible for rendering.
|
||||
*/
|
||||
public void setExpectedCount(int count) {
|
||||
mExpectedCount = count;
|
||||
mRows = getRowCount();
|
||||
mColumns = getColumnCount();
|
||||
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (i <= mColumns) {
|
||||
setSublistVisibility(i, true);
|
||||
} else {
|
||||
setSublistVisibility(i, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setSublistVisibility(int index, boolean visible) {
|
||||
View subList = getChildAt(index);
|
||||
Log.d("ListGrid", "index: " + index + ", visibility: " + visible);
|
||||
if (subList != null) {
|
||||
subList.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private int getRowCount() {
|
||||
return (int) Math.ceil(Math.sqrt(mExpectedCount));
|
||||
}
|
||||
|
||||
private int getColumnCount() {
|
||||
return (int) Math.round(Math.sqrt(mExpectedCount));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user