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:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -348,7 +348,7 @@ public class PipTouchHandler {
|
||||
}
|
||||
|
||||
private boolean shouldShowResizeHandle() {
|
||||
return !mPipBoundsHandler.hasSaveReentryBounds();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setTouchGesture(PipTouchGesture gesture) {
|
||||
|
||||
Reference in New Issue
Block a user