Controls UI - Redline adjustment for structure switching + overflow

Align with specs. Align all overflow menus vertically. Create common
widget so that all menus look identical.

Bug: 154739676
Bug: 154737955
Test: manual
Change-Id: I79cd435c2d4270b6d5a8205eed9812965fe5d069
This commit is contained in:
Matt Pietal
2020-04-29 13:43:55 -04:00
parent 303e4056ac
commit f74554fab3
11 changed files with 165 additions and 90 deletions

View File

@@ -16,7 +16,7 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingMode="stack"
android:paddingStart="0dp"
android:paddingStart="40dp"
android:paddingEnd="40dp"
android:paddingLeft="0dp"
android:paddingRight="0dp">

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 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.
-->
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/controls_list_divider"
android:insetRight="@dimen/control_spinner_padding_horizontal"
android:insetLeft="@dimen/control_spinner_padding_horizontal" />

View File

@@ -18,6 +18,5 @@
style="@style/Control.MenuItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp"
android:layout_gravity="start" />

View File

@@ -17,7 +17,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
android:paddingVertical="@dimen/control_spinner_padding_vertical"
android:paddingHorizontal="@dimen/control_spinner_padding_horizontal">
<LinearLayout
android:orientation="horizontal"

View File

@@ -21,14 +21,14 @@
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_marginTop="@dimen/controls_top_margin"
android:layout_marginEnd="@dimen/controls_header_side_margin"
android:layout_marginStart="@dimen/controls_header_side_margin">
android:layout_marginBottom="@dimen/controls_header_bottom_margin">
<!-- make sure the header stays centered in the layout by adding a spacer -->
<Space
android:layout_width="@dimen/controls_header_menu_size"
android:layout_height="1dp" />
<!-- need to keep this outer view in order to have a correctly sized anchor
for the dropdown menu, as well as dropdown background in the right place -->
<LinearLayout
android:id="@+id/controls_header"
android:orientation="horizontal"
@@ -38,15 +38,6 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center">
<ImageView
android:id="@+id/app_icon"
android:layout_gravity="center"
android:layout_width="@dimen/controls_header_app_icon_size"
android:layout_height="@dimen/controls_header_app_icon_size"
android:contentDescription="@null"
android:layout_marginEnd="10dp" />
<TextView
style="@style/Control.Spinner.Header"
android:clickable="false"
@@ -55,7 +46,6 @@
android:layout_height="wrap_content"
android:layout_gravity="center" />
</LinearLayout>
<ImageView
android:id="@+id/controls_more"
android:src="@drawable/ic_more_vert"
@@ -73,7 +63,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="30dp"
android:layout_marginLeft="@dimen/global_actions_side_margin"
android:layout_marginRight="@dimen/global_actions_side_margin" />
</merge>

View File

@@ -20,8 +20,6 @@
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
android:paddingTop="@dimen/global_actions_grid_vertical_padding"
android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:orientation="horizontal"

View File

@@ -1249,9 +1249,17 @@
<!-- Home Controls -->
<dimen name="controls_header_side_margin">4dp</dimen>
<dimen name="controls_header_menu_size">48dp</dimen>
<dimen name="controls_header_app_icon_size">40dp</dimen>
<dimen name="controls_top_margin">44dp</dimen>
<dimen name="control_header_text_size">22sp</dimen>
<dimen name="controls_header_bottom_margin">24dp</dimen>
<dimen name="controls_header_app_icon_size">24dp</dimen>
<dimen name="controls_top_margin">48dp</dimen>
<dimen name="control_header_text_size">20sp</dimen>
<dimen name="control_item_text_size">16sp</dimen>
<dimen name="control_menu_item_text_size">16sp</dimen>
<dimen name="control_menu_item_min_height">56dp</dimen>
<dimen name="control_menu_vertical_padding">12dp</dimen>
<dimen name="control_menu_horizontal_padding">16dp</dimen>
<dimen name="control_spinner_padding_vertical">24dp</dimen>
<dimen name="control_spinner_padding_horizontal">20dp</dimen>
<dimen name="control_text_size">14sp</dimen>
<dimen name="control_icon_size">24dp</dimen>
<dimen name="control_spacing">4dp</dimen>

View File

@@ -692,14 +692,16 @@
<style name="Control" />
<style name="Control.MenuItem">
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
<item name="android:textSize">@dimen/control_text_size</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:textSize">@dimen/control_menu_item_text_size</item>
<item name="android:textColor">@color/control_primary_text</item>
<item name="android:singleLine">true</item>
<item name="android:gravity">center_vertical</item>
<item name="android:minHeight">@dimen/control_menu_item_min_height</item>
</style>
<style name="Control.Spinner">
<item name="android:textSize">@dimen/control_header_text_size</item>
<item name="android:textColor">@color/control_primary_text</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">end</item>
@@ -707,11 +709,12 @@
<style name="Control.Spinner.Header">
<item name="android:background">@drawable/control_spinner_background</item>
<item name="android:textColor">@color/control_primary_text</item>
<item name="android:textSize">@dimen/control_header_text_size</item>
</style>
<style name="Control.Spinner.Item">
<item name="android:textColor">@color/control_secondary_text</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:textSize">@dimen/control_item_text_size</item>
</style>
<style name="TextAppearance.Control.Status">
@@ -735,7 +738,8 @@
<item name="android:overlapAnchor">true</item>
<!-- used to override dark/light theming -->
<item name="*android:colorPopupBackground">@color/GM2_grey_900</item>
<item name="*android:colorBackgroundFloating">@color/GM2_grey_800</item>
<item name="*android:colorPopupBackground">@color/GM2_grey_800</item>
</style>
<style name="TextAppearance.ControlSetup">

View File

@@ -35,7 +35,6 @@ import android.util.TypedValue
import android.view.ContextThemeWrapper
import android.view.LayoutInflater
import android.view.View
import android.view.View.MeasureSpec
import android.view.ViewGroup
import android.view.WindowManager
import android.view.animation.AccelerateInterpolator
@@ -58,6 +57,7 @@ import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.management.ControlsProviderSelectorActivity
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.globalactions.GlobalActionsPopupMenu
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.concurrency.DelayableExecutor
@@ -287,14 +287,6 @@ class ControlsUiControllerImpl @Inject constructor (
createMenu()
}
private fun createPopup(): ListPopupWindow {
return ListPopupWindow(
ContextThemeWrapper(context, R.style.Control_ListPopupWindow)).apply {
setWindowLayoutType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
setModal(true)
}
}
private fun createMenu() {
val items = arrayOf(
context.resources.getString(R.string.controls_menu_add),
@@ -306,7 +298,7 @@ class ControlsUiControllerImpl @Inject constructor (
val anchor = parent.requireViewById<ImageView>(R.id.controls_more)
anchor.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View) {
popup = createPopup().apply {
popup = GlobalActionsPopupMenu(context, false /* isDropDownMode */).apply {
setAnchorView(anchor)
setAdapter(adapter)
setOnItemClickListener(object : AdapterView.OnItemClickListener {
@@ -329,20 +321,6 @@ class ControlsUiControllerImpl @Inject constructor (
dismiss()
}
})
// need to call show() first in order to construct the listView
show()
var width = 0
getListView()?.apply {
// width should be between [.5, .9] of screen
val parentWidth = this@ControlsUiControllerImpl.parent.getWidth()
val widthSpec = MeasureSpec.makeMeasureSpec(
(parentWidth * 0.9).toInt(), MeasureSpec.AT_MOST)
val child = adapter.getView(0, null, this)
child.measure(widthSpec, MeasureSpec.UNSPECIFIED)
width = Math.max(child.getMeasuredWidth(), (parentWidth * 0.5).toInt())
}
setWidth(width)
setHorizontalOffset(-width + anchor.getWidth())
show()
}
}
@@ -408,9 +386,6 @@ class ControlsUiControllerImpl @Inject constructor (
(getBackground() as LayerDrawable).getDrawable(1)
.setTint(context.resources.getColor(R.color.control_spinner_dropdown, null))
}
parent.requireViewById<ImageView>(R.id.app_icon).apply {
setImageDrawable(selectionItem.icon)
}
if (itemsWithStructure.size == 1) {
spinner.setBackground(null)
@@ -420,9 +395,14 @@ class ControlsUiControllerImpl @Inject constructor (
val anchor = parent.requireViewById<ViewGroup>(R.id.controls_header)
anchor.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View) {
popup = createPopup().apply {
popup = GlobalActionsPopupMenu(context, true /* isDropDownMode */).apply {
setAnchorView(anchor)
setAdapter(adapter)
val theme = ContextThemeWrapper(context, R.style.Control_ListPopupWindow)
.getTheme()
setBackgroundDrawable(
context.resources.getDrawable(R.drawable.rounded_bg_full, theme))
setOnItemClickListener(object : AdapterView.OnItemClickListener {
override fun onItemClick(
parent: AdapterView<*>,
@@ -435,14 +415,6 @@ class ControlsUiControllerImpl @Inject constructor (
dismiss()
}
})
// need to call show() first in order to construct the listView
show()
getListView()?.apply {
setDividerHeight(
context.resources.getDimensionPixelSize(R.dimen.control_list_divider))
setDivider(
context.resources.getDrawable(R.drawable.controls_list_divider))
}
show()
}
}

View File

@@ -82,7 +82,6 @@ import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.ListPopupWindow;
import android.widget.ListView;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -2021,42 +2020,23 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
private ListPopupWindow createPowerOverflowPopup() {
ListPopupWindow popup = new ListPopupWindow(new ContextThemeWrapper(
mContext, com.android.systemui.R.style.Control_ListPopupWindow));
popup.setWindowLayoutType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
ListPopupWindow popup = new GlobalActionsPopupMenu(
mContext, false /* isDropDownMode */);
View overflowButton =
findViewById(com.android.systemui.R.id.global_actions_overflow_button);
popup.setAnchorView(overflowButton);
int parentWidth = mGlobalActionsLayout.getWidth();
// arbitrarily set the menu width to half of parent
// TODO: Logic for menu sizing based on contents.
int halfParentWidth = Math.round(parentWidth * 0.5f);
popup.setContentWidth(halfParentWidth);
popup.setAdapter(mOverflowAdapter);
popup.setModal(true);
return popup;
}
private void showPowerOverflowMenu() {
mOverflowPopup.show();
// Width is fixed to slightly more than half of the GlobalActionsLayout container.
// TODO: Resize the width of this dialog based on the sizes of the items in it.
int width = Math.round(mGlobalActionsLayout.getWidth() * 0.6f);
ListView listView = mOverflowPopup.getListView();
listView.setDividerHeight(mContext.getResources()
.getDimensionPixelSize(com.android.systemui.R.dimen.control_list_divider));
listView.setDivider(mContext.getResources().getDrawable(
com.android.systemui.R.drawable.controls_list_divider));
mOverflowPopup.setWidth(width);
mOverflowPopup.setHorizontalOffset(-width + mOverflowPopup.getAnchorView().getWidth());
mOverflowPopup.setVerticalOffset(mOverflowPopup.getAnchorView().getHeight());
mOverflowPopup = createPowerOverflowPopup();
mOverflowPopup.show();
}
private void hidePowerOverflowMenu() {
mOverflowPopup.dismiss();
mOverflowPopup = null;
}
private void initializeLayout() {
@@ -2081,8 +2061,6 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mContainer = mGlobalActionsLayout;
}
mOverflowPopup = createPowerOverflowPopup();
View overflowButton = findViewById(
com.android.systemui.R.id.global_actions_overflow_button);
if (overflowButton != null) {

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2020 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.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.view.ContextThemeWrapper;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.WindowManager;
import android.widget.ListAdapter;
import android.widget.ListPopupWindow;
import android.widget.ListView;
import com.android.systemui.R;
/**
* Customized widget for use in the GlobalActionsDialog. Ensures common positioning and user
* interactions.
*/
public class GlobalActionsPopupMenu extends ListPopupWindow {
private Context mContext;
private boolean mIsDropDownMode;
private int mMenuHorizontalPadding = 0;
private int mMenuVerticalPadding = 0;
private int mGlobalActionsSidePadding = 0;
private ListAdapter mAdapter;
public GlobalActionsPopupMenu(@NonNull Context context, boolean isDropDownMode) {
super(new ContextThemeWrapper(context, R.style.Control_ListPopupWindow));
mContext = context;
mIsDropDownMode = isDropDownMode;
// required to show above the global actions dialog
setWindowLayoutType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
setModal(true);
Resources res = mContext.getResources();
mGlobalActionsSidePadding = res.getDimensionPixelSize(R.dimen.global_actions_side_margin);
if (!isDropDownMode) {
mMenuVerticalPadding = res.getDimensionPixelSize(R.dimen.control_menu_vertical_padding);
mMenuHorizontalPadding =
res.getDimensionPixelSize(R.dimen.control_menu_horizontal_padding);
}
}
/**
* Set the listadapter used to populate this menu.
*/
public void setAdapter(@Nullable ListAdapter adapter) {
mAdapter = adapter;
super.setAdapter(adapter);
}
/**
* Show the dialog.
*/
public void show() {
// need to call show() first in order to construct the listView
super.show();
ListView listView = getListView();
Resources res = mContext.getResources();
setVerticalOffset(-getAnchorView().getHeight() / 2);
if (mIsDropDownMode) {
// use a divider
listView.setDividerHeight(res.getDimensionPixelSize(R.dimen.control_list_divider));
listView.setDivider(res.getDrawable(R.drawable.controls_list_divider_inset));
} else {
if (mAdapter == null) return;
// width should be between [.5, .9] of screen
int parentWidth = res.getSystem().getDisplayMetrics().widthPixels;
int widthSpec = MeasureSpec.makeMeasureSpec(
(int) (parentWidth * 0.9), MeasureSpec.AT_MOST);
View child = mAdapter.getView(0, null, listView);
child.measure(widthSpec, MeasureSpec.UNSPECIFIED);
int width = Math.max(child.getMeasuredWidth(), (int) (parentWidth * 0.5));
listView.setPadding(mMenuHorizontalPadding, mMenuVerticalPadding,
mMenuHorizontalPadding, mMenuVerticalPadding);
setWidth(width);
setHorizontalOffset(getAnchorView().getWidth() - mGlobalActionsSidePadding - width);
}
super.show();
}
}