Move NavButtons to end of taskbar

* Layout hotseat icons from the end instead of the start
* IME down and system back arrow are now separate views

Bug: 191399224
Test: Tested w/ RTL + LTR in gesture
and 3 button nav w/ and w/o IME

Change-Id: I4d0ecd0bee0c519892c63eeefef45055b26d349b
This commit is contained in:
Vinit Nayak 2021-07-19 12:53:28 -07:00
parent 5bd217414c
commit 8dcbde87c0
6 changed files with 65 additions and 44 deletions

View File

@ -36,18 +36,27 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" > android:layout_gravity="bottom" >
<FrameLayout
android:id="@+id/start_contextual_buttons"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
android:gravity="center_vertical"
android:layout_gravity="start"/>
<LinearLayout <LinearLayout
android:id="@+id/start_nav_buttons" android:id="@+id/end_nav_buttons"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingLeft="@dimen/taskbar_nav_buttons_spacing" android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
android:paddingRight="@dimen/taskbar_nav_buttons_spacing" android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
android:gravity="center_vertical" android:gravity="center_vertical"
android:layout_gravity="start"/> android:layout_gravity="end"/>
<FrameLayout <FrameLayout
android:id="@+id/end_nav_buttons" android:id="@+id/end_contextual_buttons"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingLeft="@dimen/taskbar_nav_buttons_spacing" android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"

View File

@ -79,8 +79,10 @@ public class NavbarButtonsViewController {
private final TaskbarActivityContext mContext; private final TaskbarActivityContext mContext;
private final FrameLayout mNavButtonsView; private final FrameLayout mNavButtonsView;
private final ViewGroup mStartContainer; private final ViewGroup mNavButtonContainer;
private final ViewGroup mEndContainer; // Used for IME+A11Y buttons
private final ViewGroup mEndContextualContainer;
private final ViewGroup mStartContextualContainer;
// Initialized in init. // Initialized in init.
private TaskbarControllers mControllers; private TaskbarControllers mControllers;
@ -91,8 +93,9 @@ public class NavbarButtonsViewController {
public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) { public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
mContext = context; mContext = context;
mNavButtonsView = navButtonsView; mNavButtonsView = navButtonsView;
mStartContainer = mNavButtonsView.findViewById(R.id.start_nav_buttons); mNavButtonContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
mEndContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons); mEndContextualContainer = mNavButtonsView.findViewById(R.id.end_contextual_buttons);
mStartContextualContainer = mNavButtonsView.findViewById(R.id.start_contextual_buttons);
} }
/** /**
@ -114,21 +117,22 @@ public class NavbarButtonsViewController {
// IME switcher // IME switcher
View imeSwitcherButton = addButton(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH, View imeSwitcherButton = addButton(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH,
mEndContainer, mControllers.navButtonController, R.id.ime_switcher); mEndContextualContainer, mControllers.navButtonController, R.id.ime_switcher);
mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton, mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE) flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
&& ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0) && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)
&& ((flags & FLAG_A11Y_VISIBLE) == 0))); && ((flags & FLAG_A11Y_VISIBLE) == 0)));
mBackButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK, View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
mStartContainer, mControllers.navButtonController, R.id.back); mStartContextualContainer, mControllers.navButtonController, R.id.back);
imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
// Rotate when Ime visible // Rotate when Ime visible
mPropertyHolders.add(new StatePropertyHolder(mBackButton, mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
flags -> (flags & FLAG_IME_VISIBLE) == 0, View.ROTATION, 0, flags -> (flags & FLAG_IME_VISIBLE) != 0));
Utilities.isRtl(mContext.getResources()) ? 90 : -90));
if (mContext.isThreeButtonNav()) { if (mContext.isThreeButtonNav()) {
initButtons(mStartContainer, mEndContainer, mControllers.navButtonController); initButtons(mNavButtonContainer, mEndContextualContainer,
mControllers.navButtonController);
// Animate taskbar background when IME shows // Animate taskbar background when IME shows
mPropertyHolders.add(new StatePropertyHolder( mPropertyHolders.add(new StatePropertyHolder(
@ -142,21 +146,18 @@ public class NavbarButtonsViewController {
// Rotation button // Rotation button
RotationButton rotationButton = new RotationButtonImpl( RotationButton rotationButton = new RotationButtonImpl(
addButton(mEndContainer, R.id.rotate_suggestion)); addButton(mEndContextualContainer, R.id.rotate_suggestion));
rotationButton.hide(); rotationButton.hide();
mControllers.rotationButtonController.setRotationButton(rotationButton); mControllers.rotationButtonController.setRotationButton(rotationButton);
} else { } else {
mControllers.rotationButtonController.setRotationButton(new RotationButton() {}); mControllers.rotationButtonController.setRotationButton(new RotationButton() {});
// Show when IME is visible
mPropertyHolders.add(new StatePropertyHolder(mBackButton,
flags -> (flags & FLAG_IME_VISIBLE) != 0));
} }
applyState(); applyState();
mPropertyHolders.forEach(StatePropertyHolder::endAnimation); mPropertyHolders.forEach(StatePropertyHolder::endAnimation);
} }
private void initButtons(ViewGroup startContainer, ViewGroup endContainer, private void initButtons(ViewGroup navContainer, ViewGroup endContainer,
TaskbarNavButtonController navButtonController) { TaskbarNavButtonController navButtonController) {
// Hide when keyguard is showing, show when bouncer is showing // Hide when keyguard is showing, show when bouncer is showing
@ -164,14 +165,19 @@ public class NavbarButtonsViewController {
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 || flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 ||
(flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0)); (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0));
mBackButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
mNavButtonContainer, mControllers.navButtonController, R.id.back);
mPropertyHolders.add(new StatePropertyHolder(mBackButton,
flags -> (flags & FLAG_IME_VISIBLE) == 0));
// home and recents buttons // home and recents buttons
View homeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, startContainer, View homeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
navButtonController, R.id.home); navButtonController, R.id.home);
mPropertyHolders.add(new StatePropertyHolder(homeButton, mPropertyHolders.add(new StatePropertyHolder(homeButton,
flags -> (flags & FLAG_IME_VISIBLE) == 0 && flags -> (flags & FLAG_IME_VISIBLE) == 0 &&
(flags & FLAG_KEYGUARD_VISIBLE) == 0)); (flags & FLAG_KEYGUARD_VISIBLE) == 0));
View recentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS, View recentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
startContainer, navButtonController, R.id.recent_apps); navContainer, navButtonController, R.id.recent_apps);
mPropertyHolders.add(new StatePropertyHolder(recentsButton, mPropertyHolders.add(new StatePropertyHolder(recentsButton,
flags -> (flags & FLAG_IME_VISIBLE) == 0 && flags -> (flags & FLAG_IME_VISIBLE) == 0 &&
(flags & FLAG_KEYGUARD_VISIBLE) == 0)); (flags & FLAG_KEYGUARD_VISIBLE) == 0));

View File

@ -194,24 +194,30 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
protected void onLayout(boolean changed, int left, int top, int right, int bottom) { protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int count = getChildCount(); int count = getChildCount();
int spaceNeeded = count * (mItemMarginLeftRight * 2 + mIconTouchSize); int spaceNeeded = count * (mItemMarginLeftRight * 2 + mIconTouchSize);
int iconStart = (right - left - spaceNeeded) / 2; int navSpaceNeeded = ApiWrapper.getHotseatEndOffset(getContext());
int startOffset = ApiWrapper.getHotseatStartOffset(getContext()); boolean layoutRtl = isLayoutRtl();
if (startOffset > iconStart) { int iconEnd = right - (right - left - spaceNeeded) / 2;
int diff = startOffset - iconStart; boolean needMoreSpaceForNav = layoutRtl ?
iconStart = isLayoutRtl() ? (iconStart - diff) : iconStart + diff; navSpaceNeeded > (iconEnd - spaceNeeded) :
iconEnd > (right - navSpaceNeeded);
if (needMoreSpaceForNav) {
int offset = layoutRtl ?
navSpaceNeeded - (iconEnd - spaceNeeded) :
(right - navSpaceNeeded) - iconEnd;
iconEnd += offset;
} }
// Layout the children // Layout the children
mIconLayoutBounds.left = iconStart; mIconLayoutBounds.right = iconEnd;
mIconLayoutBounds.top = (bottom - top - mIconTouchSize) / 2; mIconLayoutBounds.top = (bottom - top - mIconTouchSize) / 2;
mIconLayoutBounds.bottom = mIconLayoutBounds.top + mIconTouchSize; mIconLayoutBounds.bottom = mIconLayoutBounds.top + mIconTouchSize;
for (int i = 0; i < count; i++) { for (int i = count; i > 0; i--) {
View child = getChildAt(i); View child = getChildAt(i - 1);
iconStart += mItemMarginLeftRight; iconEnd -= mItemMarginLeftRight;
int iconEnd = iconStart + mIconTouchSize; int iconStart = iconEnd - mIconTouchSize;
child.layout(iconStart, mIconLayoutBounds.top, iconEnd, mIconLayoutBounds.bottom); child.layout(iconStart, mIconLayoutBounds.top, iconEnd, mIconLayoutBounds.bottom);
iconStart = iconEnd + mItemMarginLeftRight; iconEnd = iconStart - mItemMarginLeftRight;
} }
mIconLayoutBounds.right = iconStart; mIconLayoutBounds.left = iconEnd;
} }
@Override @Override

View File

@ -44,9 +44,9 @@ public class ApiWrapper {
} }
/** /**
* Returns the minimum space that should be left empty at the start of hotseat * Returns the minimum space that should be left empty at the end of hotseat
*/ */
public static int getHotseatStartOffset(Context context) { public static int getHotseatEndOffset(Context context) {
if (SysUINavigationMode.INSTANCE.get(context).getMode() == Mode.THREE_BUTTONS) { if (SysUINavigationMode.INSTANCE.get(context).getMode() == Mode.THREE_BUTTONS) {
Resources res = context.getResources(); Resources res = context.getResources();
return 2 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_spacing) return 2 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_spacing)

View File

@ -777,7 +777,7 @@ public class DeviceProfile {
int taskbarOffset = getTaskbarOffsetY(); int taskbarOffset = getTaskbarOffsetY();
int hotseatTopDiff = hotseatHeight - taskbarSize - taskbarOffset; int hotseatTopDiff = hotseatHeight - taskbarSize - taskbarOffset;
int startOffset = ApiWrapper.getHotseatStartOffset(context); int endOffset = ApiWrapper.getHotseatEndOffset(context);
int requiredWidth = iconSizePx * numShownHotseatIcons; int requiredWidth = iconSizePx * numShownHotseatIcons;
Resources res = context.getResources(); Resources res = context.getResources();
@ -785,16 +785,16 @@ public class DeviceProfile {
float taskbarIconSpacing = 2 * res.getDimension(R.dimen.taskbar_icon_spacing); float taskbarIconSpacing = 2 * res.getDimension(R.dimen.taskbar_icon_spacing);
int maxSize = (int) (requiredWidth int maxSize = (int) (requiredWidth
* (taskbarIconSize + taskbarIconSpacing) / taskbarIconSize); * (taskbarIconSize + taskbarIconSpacing) / taskbarIconSize);
int hotseatSize = Math.min(maxSize, availableWidthPx - startOffset); int hotseatSize = Math.min(maxSize, availableWidthPx - endOffset);
int sideSpacing = (availableWidthPx - hotseatSize) / 2; int sideSpacing = (availableWidthPx - hotseatSize) / 2;
mHotseatPadding.set(sideSpacing, hotseatTopDiff, sideSpacing, taskbarOffset); mHotseatPadding.set(sideSpacing, hotseatTopDiff, sideSpacing, taskbarOffset);
if (startOffset > sideSpacing) { if (endOffset > sideSpacing) {
int diff = Utilities.isRtl(context.getResources()) int diff = Utilities.isRtl(context.getResources())
? sideSpacing - startOffset ? sideSpacing - endOffset
: startOffset - sideSpacing; : endOffset - sideSpacing;
mHotseatPadding.left += diff; mHotseatPadding.left -= diff;
mHotseatPadding.right -= diff; mHotseatPadding.right += diff;
} }
} else { } else {
// We want the edges of the hotseat to line up with the edges of the workspace, but the // We want the edges of the hotseat to line up with the edges of the workspace, but the

View File

@ -39,9 +39,9 @@ public class ApiWrapper {
} }
/** /**
* Returns the minimum space that should be left empty at the start of hotseat * Returns the minimum space that should be left empty at the end of hotseat
*/ */
public static int getHotseatStartOffset(Context context) { public static int getHotseatEndOffset(Context context) {
return 0; return 0;
} }
} }