Add ability to change PiP menu icon locations on the fly.

This CL does:
- Add a PipMenuIconsAlgorithm, allowing calculation on the fly for
correct locations of individual icons
- Make it so that when PIP changes its bounds, it updates the location
of the action items accordingly (if needed)

Bug: 160825579
Test: enter PIP, icons are still where they are
Change-Id: I8618f7c5c36c8e09613c126c1ebb20b60e95de58
This commit is contained in:
Ben Lin
2020-07-08 18:45:35 -07:00
parent b210bbbe3f
commit be8b9eb16d
9 changed files with 169 additions and 22 deletions

View File

@@ -62,25 +62,30 @@
</FrameLayout>
</FrameLayout>
<ImageButton
android:id="@+id/settings"
android:layout_width="@dimen/pip_action_size"
android:layout_height="@dimen/pip_action_size"
android:layout_gravity="top|start"
android:padding="@dimen/pip_action_padding"
android:contentDescription="@string/pip_phone_settings"
android:src="@drawable/pip_ic_settings"
android:background="?android:selectableItemBackgroundBorderless" />
<ImageButton
android:id="@+id/dismiss"
android:layout_width="@dimen/pip_action_size"
android:layout_height="@dimen/pip_action_size"
<LinearLayout
android:id="@+id/top_end_container"
android:layout_gravity="top|end"
android:padding="@dimen/pip_action_padding"
android:contentDescription="@string/pip_phone_close"
android:src="@drawable/pip_ic_close_white"
android:background="?android:selectableItemBackgroundBorderless" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageButton
android:id="@+id/settings"
android:layout_width="@dimen/pip_action_size"
android:layout_height="@dimen/pip_action_size"
android:padding="@dimen/pip_action_padding"
android:contentDescription="@string/pip_phone_settings"
android:src="@drawable/pip_ic_settings"
android:background="?android:selectableItemBackgroundBorderless" />
<ImageButton
android:id="@+id/dismiss"
android:layout_width="@dimen/pip_action_size"
android:layout_height="@dimen/pip_action_size"
android:padding="@dimen/pip_action_padding"
android:contentDescription="@string/pip_phone_close"
android:src="@drawable/pip_ic_close_white"
android:background="?android:selectableItemBackgroundBorderless" />
</LinearLayout>
<!--TODO (b/156917828): Add content description for a11y purposes?-->
<ImageButton
@@ -89,6 +94,7 @@
android:layout_height="@dimen/pip_resize_handle_size"
android:layout_gravity="top|start"
android:layout_margin="@dimen/pip_resize_handle_margin"
android:padding="@dimen/pip_resize_handle_padding"
android:src="@drawable/pip_resize_handle"
android:background="?android:selectableItemBackgroundBorderless" />
</FrameLayout>

View File

@@ -52,7 +52,8 @@
<!-- The touchable/draggable edge size for PIP resize. -->
<dimen name="pip_resize_edge_size">48dp</dimen>
<!-- PIP Resize handle size and margin. -->
<!-- PIP Resize handle size, margin and padding. -->
<dimen name="pip_resize_handle_size">12dp</dimen>
<dimen name="pip_resize_handle_margin">4dp</dimen>
<dimen name="pip_resize_handle_padding">0dp</dimen>
</resources>

View File

@@ -29,6 +29,7 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.KeyguardSliceProvider;
import com.android.systemui.onehanded.dagger.OneHandedModule;
import com.android.systemui.pip.phone.PipMenuActivity;
import com.android.systemui.pip.phone.dagger.PipModule;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.InjectionInflationController;
@@ -121,4 +122,9 @@ public interface SystemUIRootComponent {
* Member injection into the supplied argument.
*/
void inject(KeyguardSliceProvider keyguardSliceProvider);
/**
* Member injection into the supplied argument.
*/
void inject(PipMenuActivity pipMenuActivity);
}

View File

@@ -178,6 +178,9 @@ public class PipTaskOrganizer extends TaskOrganizer implements
Rect startBounds = (Rect) args.arg2;
Rect toBounds = (Rect) args.arg3;
userResizePip(startBounds, toBounds);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
break;
}
}

View File

@@ -76,12 +76,15 @@ import android.widget.ImageButton;
import android.widget.LinearLayout;
import com.android.systemui.Interpolators;
import com.android.systemui.SystemUIFactory;
import com.android.wm.shell.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
/**
* Translucent activity that gets started on top of a task in PIP to allow the user to control it.
*/
@@ -100,6 +103,7 @@ public class PipMenuActivity extends Activity {
public static final int MESSAGE_POINTER_EVENT = 7;
public static final int MESSAGE_MENU_EXPANDED = 8;
public static final int MESSAGE_FADE_OUT_MENU = 9;
public static final int MESSAGE_UPDATE_MENU_LAYOUT = 10;
private static final int INITIAL_DISMISS_DELAY = 3500;
private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
@@ -129,8 +133,12 @@ public class PipMenuActivity extends Activity {
private View mSettingsButton;
private View mDismissButton;
private View mResizeHandle;
private View mTopEndContainer;
private int mBetweenActionPaddingLand;
@Inject
PipMenuIconsAlgorithm mPipMenuIconsAlgorithm;
private AnimatorSet mMenuContainerAnimator;
private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener =
@@ -193,6 +201,11 @@ public class PipMenuActivity extends Activity {
fadeOutMenu();
break;
}
case MESSAGE_UPDATE_MENU_LAYOUT: {
final Rect bounds = (Rect) msg.obj;
mPipMenuIconsAlgorithm.onBoundsChanged(bounds);
break;
}
}
}
};
@@ -208,6 +221,9 @@ public class PipMenuActivity extends Activity {
getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
super.onCreate(savedInstanceState);
SystemUIFactory.getInstance().getRootComponent().inject(this);
setContentView(R.layout.pip_menu_activity);
mAccessibilityManager = getSystemService(AccessibilityManager.class);
@@ -217,6 +233,7 @@ public class PipMenuActivity extends Activity {
mViewRoot.setBackground(mBackgroundDrawable);
mMenuContainer = findViewById(R.id.menu_container);
mMenuContainer.setAlpha(0);
mTopEndContainer = findViewById(R.id.top_end_container);
mSettingsButton = findViewById(R.id.settings);
mSettingsButton.setAlpha(0);
mSettingsButton.setOnClickListener((v) -> {
@@ -238,6 +255,8 @@ public class PipMenuActivity extends Activity {
mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
R.dimen.pip_between_action_padding_land);
mPipMenuIconsAlgorithm.bindViews((ViewGroup) mViewRoot, (ViewGroup) mTopEndContainer,
mResizeHandle, mSettingsButton, mDismissButton);
updateFromIntent(getIntent());
setTitle(R.string.pip_menu_title);
setDisablePreviewScreenshots(true);

View File

@@ -574,6 +574,22 @@ public class PipMenuActivityController {
}
}
/**
* Tell the PIP Menu to recalculate its layout given its current position on the display.
*/
public void updateMenuLayout(Rect bounds) {
if (mToActivityMessenger != null) {
Message m = Message.obtain();
m.what = PipMenuActivity.MESSAGE_UPDATE_MENU_LAYOUT;
m.obj = bounds;
try {
mToActivityMessenger.send(m);
} catch (RemoteException e) {
Log.e(TAG, "Could not dispatch touch event", e);
}
}
}
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);

View File

@@ -0,0 +1,90 @@
/*
* 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.pip.phone;
import android.content.Context;
import android.graphics.Rect;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import javax.inject.Inject;
/**
* Helper class to calculate and place the menu icons on the PIP Menu.
*/
public class PipMenuIconsAlgorithm {
private static final String TAG = "PipMenuIconsAlgorithm";
private boolean mFinishedLayout = false;
protected ViewGroup mViewRoot;
protected ViewGroup mTopEndContainer;
protected View mDragHandle;
protected View mSettingsButton;
protected View mDismissButton;
@Inject
public PipMenuIconsAlgorithm(Context context) {
}
/**
* Bind the necessary views.
*/
public void bindViews(ViewGroup viewRoot, ViewGroup topEndContainer, View dragHandle,
View settingsButton, View dismissButton) {
mViewRoot = viewRoot;
mTopEndContainer = topEndContainer;
mDragHandle = dragHandle;
mSettingsButton = settingsButton;
mDismissButton = dismissButton;
}
/**
* Updates the position of the drag handle based on where the PIP window is on the screen.
*/
public void onBoundsChanged(Rect bounds) {
if (mViewRoot == null || mTopEndContainer == null || mDragHandle == null
|| mSettingsButton == null || mDismissButton == null) {
Log.e(TAG, "One if the required views is null.");
}
//We only need to calculate the layout once since it does not change.
if (!mFinishedLayout) {
mTopEndContainer.removeView(mSettingsButton);
mViewRoot.addView(mSettingsButton);
setLayoutGravity(mDragHandle, Gravity.START | Gravity.TOP);
setLayoutGravity(mSettingsButton, Gravity.START | Gravity.TOP);
mFinishedLayout = true;
}
}
/**
* Set the gravity on the given view.
*/
protected static void setLayoutGravity(View v, int gravity) {
if (v.getLayoutParams() instanceof FrameLayout.LayoutParams) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) v.getLayoutParams();
params.gravity = gravity;
v.setLayoutParams(params);
}
}
}

View File

@@ -127,7 +127,10 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
new PhysicsAnimator.SpringConfig(
SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
private final Consumer<Rect> mUpdateBoundsCallback = mBounds::set;
private final Consumer<Rect> mUpdateBoundsCallback = (Rect newBounds) -> {
mMenuController.updateMenuLayout(newBounds);
mBounds.set(newBounds);
};
/**
* Whether we're springing to the touch event location (vs. moving it to that position
@@ -248,7 +251,10 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
mBounds.set(toBounds);
} else {
mTemporaryBounds.set(toBounds);
mPipTaskOrganizer.scheduleUserResizePip(mBounds, mTemporaryBounds, null);
mPipTaskOrganizer.scheduleUserResizePip(mBounds, mTemporaryBounds,
(Rect newBounds) -> {
mMenuController.updateMenuLayout(newBounds);
});
}
} else {
// If PIP is 'catching up' after being stuck in the dismiss target, update the animation

View File

@@ -348,7 +348,7 @@ public class PipTouchHandler {
}
private boolean shouldShowResizeHandle() {
return !mPipBoundsHandler.hasSaveReentryBounds();
return false;
}
public void setTouchGesture(PipTouchGesture gesture) {