Loading packages/SystemUI/res/drawable/pip_dismiss_background.xml +15 −15 Original line number Diff line number Diff line <!-- Copyright (C) 2016 The Android Open Source Project Copyright (C) 2017 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. Loading @@ -14,9 +14,9 @@ Copyright (C) 2016 The Android Open Source Project limitations under the License. --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <corners android:radius="100dp" /> <solid android:color="#66000000" /> android:shape="rectangle"> <gradient android:startColor="#B3000000" android:endColor="#00000000" android:angle="90"/> </shape> No newline at end of file packages/SystemUI/res/layout/pip_dismiss_view.xml +40 −7 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2016 The Android Open Source Project <!-- Copyright (C) 2016 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. Loading @@ -13,12 +14,44 @@ See the License for the specific language governing permissions and limitations under the License. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pip_dismiss_view" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/pip_dismiss_background" android:foreground="@drawable/pip_dismiss" android:alpha="0" android:forceHasOverlappingRendering="false" /> android:alpha="0"> <!-- The height of the below view needs to be animated from a window so it needs to be in a container to resize smoothly --> <View android:id="@+id/gradient_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="bottom" android:background="@drawable/pip_dismiss_background" /> <LinearLayout android:id="@+id/pip_dismiss_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|center_horizontal" android:orientation="horizontal" android:paddingBottom="32dp" > <ImageView android:id="@+id/pip_dismiss_icon" android:layout_width="24dp" android:layout_height="24dp" android:padding="2dp" android:src="@drawable/pip_dismiss" android:tint="#FFFFFFFF" /> <TextView android:id="@+id/pip_dismiss_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/pip_phone_close" android:textColor="#FFFFFFFF" android:textSize="16sp" /> </LinearLayout> </FrameLayout> No newline at end of file packages/SystemUI/res/layout/pip_menu_activity.xml +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ android:layout_height="48dp" android:layout_gravity="top|end" android:padding="10dp" android:contentDescription="@string/pip_phone_dismiss" android:contentDescription="@string/pip_phone_close" android:src="@drawable/ic_close_white" android:background="?android:selectableItemBackgroundBorderless" /> Loading packages/SystemUI/res/values/strings.xml +2 −2 Original line number Diff line number Diff line Loading @@ -1746,8 +1746,8 @@ <!-- Label for PIP action to Minimize the PIP [CHAR LIMIT=25] --> <string name="pip_phone_minimize">Minimize</string> <!-- Label for PIP action to Dismiss the PIP --> <string name="pip_phone_dismiss">Dismiss</string> <!-- Label for PIP the drag to close zone [CHAR LIMIT=NONE]--> <string name="pip_phone_close">Close</string> <!-- PIP section of the tuner. Non-translatable since it should not appear on production builds ever. --> Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java +73 −8 Original line number Diff line number Diff line Loading @@ -17,13 +17,19 @@ package com.android.systemui.pip.phone; import android.content.Context; import android.content.res.Resources; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.view.Gravity; import android.view.LayoutInflater; import android.view.TouchDelegate; import android.view.View; import android.view.View.OnLayoutChangeListener; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.FrameLayout; import com.android.systemui.Interpolators; import com.android.systemui.R; Loading @@ -35,12 +41,22 @@ public class PipDismissViewController { private static final int SHOW_TARGET_DELAY = 100; private static final int SHOW_TARGET_DURATION = 200; private static final float DISMISS_TEXT_MAX_SCALE = 2f; private static final float DISMISS_GRADIENT_MIN_HEIGHT_PERCENT = 0.33f; private static final float DISMISS_GRADIENT_MAX_HEIGHT_PERCENT = 0.5f; private static final float DISMISS_THRESHOLD = 0.55f; private Context mContext; private WindowManager mWindowManager; private View mDismissView; private Rect mDismissTargetScreenBounds = new Rect(); private View mDismissContainer; private View mGradientView; private float mMinHeight; private float mMaxHeight; public PipDismissViewController(Context context) { mContext = context; mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Loading @@ -51,25 +67,37 @@ public class PipDismissViewController { */ public void createDismissTarget() { if (mDismissView == null) { // Determine sizes for the gradient Point windowSize = new Point(); mWindowManager.getDefaultDisplay().getSize(windowSize); mMinHeight = windowSize.y * DISMISS_GRADIENT_MIN_HEIGHT_PERCENT; mMaxHeight = windowSize.y * DISMISS_GRADIENT_MAX_HEIGHT_PERCENT; // Create a new view for the dismiss target int dismissTargetSize = mContext.getResources().getDimensionPixelSize( R.dimen.pip_dismiss_target_size); LayoutInflater inflater = LayoutInflater.from(mContext); mDismissView = inflater.inflate(R.layout.pip_dismiss_view, null); mDismissView.addOnLayoutChangeListener(new OnLayoutChangeListener() { mGradientView = mDismissView.findViewById(R.id.gradient_view); FrameLayout.LayoutParams glp = (android.widget.FrameLayout.LayoutParams) mGradientView .getLayoutParams(); glp.height = (int) mMaxHeight; mGradientView.setLayoutParams(glp); mGradientView.setPivotY(windowSize.y); mGradientView.setScaleY(mMaxHeight / mMinHeight); // Set to min height via scaling mDismissContainer = mDismissView.findViewById(R.id.pip_dismiss_container); mDismissContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { if (mDismissView != null) { mDismissView.getBoundsOnScreen(mDismissTargetScreenBounds); if (mDismissContainer != null) { mDismissContainer.getBoundsOnScreen(mDismissTargetScreenBounds); } } }); // Add the target to the window WindowManager.LayoutParams lp = new WindowManager.LayoutParams( dismissTargetSize, dismissTargetSize, windowSize.x, (int) mMaxHeight, WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE Loading @@ -84,7 +112,8 @@ public class PipDismissViewController { /** * Shows the dismiss target. */ public void showDismissTarget() { public void showDismissTarget(Rect pinnedStack) { updateDismissTarget(pinnedStack); mDismissView.animate() .alpha(1f) .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN) Loading Loading @@ -114,6 +143,36 @@ public class PipDismissViewController { } } /** * Updates the appearance of the dismiss target based on how close the PIP is. */ public void updateDismissTarget(Rect pinnedStack) { // As PIP moves over / away from delete target it grows / shrinks final float scalePercent = calculateDistancePercent(pinnedStack); final float newScale = 1 + (DISMISS_TEXT_MAX_SCALE - 1) * scalePercent; final float minGradientScale = mMinHeight / mMaxHeight; final float newHeight = Math.max(minGradientScale, scalePercent); mGradientView.setScaleY(newHeight); mDismissContainer.setScaleX(newScale); mDismissContainer.setScaleY(newScale); } /** * @return the percentage of distance the PIP is away from the dismiss target point. */ private float calculateDistancePercent(Rect pinnedStack) { final int distance = mDismissTargetScreenBounds.height(); final int textX = mDismissTargetScreenBounds.centerX(); final int textY = mDismissTargetScreenBounds.bottom; final float pipCurrX = pinnedStack.centerX(); final float pipCurrY = pinnedStack.bottom; final float currentDistance = PointF.length(pipCurrX - textX, pipCurrY - textY); if (currentDistance <= distance) { return 1 - (currentDistance / distance); } return 0; } /** * @return the dismiss target screen bounds. */ Loading @@ -121,4 +180,10 @@ public class PipDismissViewController { return mDismissTargetScreenBounds; } /** * @return whether the PIP is positioned on the dismiss target enough to be dismissed. */ public boolean shouldDismiss(Rect pinnedStack) { return calculateDistancePercent(pinnedStack) >= DISMISS_THRESHOLD; } } Loading
packages/SystemUI/res/drawable/pip_dismiss_background.xml +15 −15 Original line number Diff line number Diff line <!-- Copyright (C) 2016 The Android Open Source Project Copyright (C) 2017 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. Loading @@ -14,9 +14,9 @@ Copyright (C) 2016 The Android Open Source Project limitations under the License. --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <corners android:radius="100dp" /> <solid android:color="#66000000" /> android:shape="rectangle"> <gradient android:startColor="#B3000000" android:endColor="#00000000" android:angle="90"/> </shape> No newline at end of file
packages/SystemUI/res/layout/pip_dismiss_view.xml +40 −7 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2016 The Android Open Source Project <!-- Copyright (C) 2016 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. Loading @@ -13,12 +14,44 @@ See the License for the specific language governing permissions and limitations under the License. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pip_dismiss_view" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/pip_dismiss_background" android:foreground="@drawable/pip_dismiss" android:alpha="0" android:forceHasOverlappingRendering="false" /> android:alpha="0"> <!-- The height of the below view needs to be animated from a window so it needs to be in a container to resize smoothly --> <View android:id="@+id/gradient_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="bottom" android:background="@drawable/pip_dismiss_background" /> <LinearLayout android:id="@+id/pip_dismiss_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|center_horizontal" android:orientation="horizontal" android:paddingBottom="32dp" > <ImageView android:id="@+id/pip_dismiss_icon" android:layout_width="24dp" android:layout_height="24dp" android:padding="2dp" android:src="@drawable/pip_dismiss" android:tint="#FFFFFFFF" /> <TextView android:id="@+id/pip_dismiss_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/pip_phone_close" android:textColor="#FFFFFFFF" android:textSize="16sp" /> </LinearLayout> </FrameLayout> No newline at end of file
packages/SystemUI/res/layout/pip_menu_activity.xml +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ android:layout_height="48dp" android:layout_gravity="top|end" android:padding="10dp" android:contentDescription="@string/pip_phone_dismiss" android:contentDescription="@string/pip_phone_close" android:src="@drawable/ic_close_white" android:background="?android:selectableItemBackgroundBorderless" /> Loading
packages/SystemUI/res/values/strings.xml +2 −2 Original line number Diff line number Diff line Loading @@ -1746,8 +1746,8 @@ <!-- Label for PIP action to Minimize the PIP [CHAR LIMIT=25] --> <string name="pip_phone_minimize">Minimize</string> <!-- Label for PIP action to Dismiss the PIP --> <string name="pip_phone_dismiss">Dismiss</string> <!-- Label for PIP the drag to close zone [CHAR LIMIT=NONE]--> <string name="pip_phone_close">Close</string> <!-- PIP section of the tuner. Non-translatable since it should not appear on production builds ever. --> Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java +73 −8 Original line number Diff line number Diff line Loading @@ -17,13 +17,19 @@ package com.android.systemui.pip.phone; import android.content.Context; import android.content.res.Resources; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.view.Gravity; import android.view.LayoutInflater; import android.view.TouchDelegate; import android.view.View; import android.view.View.OnLayoutChangeListener; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.FrameLayout; import com.android.systemui.Interpolators; import com.android.systemui.R; Loading @@ -35,12 +41,22 @@ public class PipDismissViewController { private static final int SHOW_TARGET_DELAY = 100; private static final int SHOW_TARGET_DURATION = 200; private static final float DISMISS_TEXT_MAX_SCALE = 2f; private static final float DISMISS_GRADIENT_MIN_HEIGHT_PERCENT = 0.33f; private static final float DISMISS_GRADIENT_MAX_HEIGHT_PERCENT = 0.5f; private static final float DISMISS_THRESHOLD = 0.55f; private Context mContext; private WindowManager mWindowManager; private View mDismissView; private Rect mDismissTargetScreenBounds = new Rect(); private View mDismissContainer; private View mGradientView; private float mMinHeight; private float mMaxHeight; public PipDismissViewController(Context context) { mContext = context; mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Loading @@ -51,25 +67,37 @@ public class PipDismissViewController { */ public void createDismissTarget() { if (mDismissView == null) { // Determine sizes for the gradient Point windowSize = new Point(); mWindowManager.getDefaultDisplay().getSize(windowSize); mMinHeight = windowSize.y * DISMISS_GRADIENT_MIN_HEIGHT_PERCENT; mMaxHeight = windowSize.y * DISMISS_GRADIENT_MAX_HEIGHT_PERCENT; // Create a new view for the dismiss target int dismissTargetSize = mContext.getResources().getDimensionPixelSize( R.dimen.pip_dismiss_target_size); LayoutInflater inflater = LayoutInflater.from(mContext); mDismissView = inflater.inflate(R.layout.pip_dismiss_view, null); mDismissView.addOnLayoutChangeListener(new OnLayoutChangeListener() { mGradientView = mDismissView.findViewById(R.id.gradient_view); FrameLayout.LayoutParams glp = (android.widget.FrameLayout.LayoutParams) mGradientView .getLayoutParams(); glp.height = (int) mMaxHeight; mGradientView.setLayoutParams(glp); mGradientView.setPivotY(windowSize.y); mGradientView.setScaleY(mMaxHeight / mMinHeight); // Set to min height via scaling mDismissContainer = mDismissView.findViewById(R.id.pip_dismiss_container); mDismissContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { if (mDismissView != null) { mDismissView.getBoundsOnScreen(mDismissTargetScreenBounds); if (mDismissContainer != null) { mDismissContainer.getBoundsOnScreen(mDismissTargetScreenBounds); } } }); // Add the target to the window WindowManager.LayoutParams lp = new WindowManager.LayoutParams( dismissTargetSize, dismissTargetSize, windowSize.x, (int) mMaxHeight, WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE Loading @@ -84,7 +112,8 @@ public class PipDismissViewController { /** * Shows the dismiss target. */ public void showDismissTarget() { public void showDismissTarget(Rect pinnedStack) { updateDismissTarget(pinnedStack); mDismissView.animate() .alpha(1f) .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN) Loading Loading @@ -114,6 +143,36 @@ public class PipDismissViewController { } } /** * Updates the appearance of the dismiss target based on how close the PIP is. */ public void updateDismissTarget(Rect pinnedStack) { // As PIP moves over / away from delete target it grows / shrinks final float scalePercent = calculateDistancePercent(pinnedStack); final float newScale = 1 + (DISMISS_TEXT_MAX_SCALE - 1) * scalePercent; final float minGradientScale = mMinHeight / mMaxHeight; final float newHeight = Math.max(minGradientScale, scalePercent); mGradientView.setScaleY(newHeight); mDismissContainer.setScaleX(newScale); mDismissContainer.setScaleY(newScale); } /** * @return the percentage of distance the PIP is away from the dismiss target point. */ private float calculateDistancePercent(Rect pinnedStack) { final int distance = mDismissTargetScreenBounds.height(); final int textX = mDismissTargetScreenBounds.centerX(); final int textY = mDismissTargetScreenBounds.bottom; final float pipCurrX = pinnedStack.centerX(); final float pipCurrY = pinnedStack.bottom; final float currentDistance = PointF.length(pipCurrX - textX, pipCurrY - textY); if (currentDistance <= distance) { return 1 - (currentDistance / distance); } return 0; } /** * @return the dismiss target screen bounds. */ Loading @@ -121,4 +180,10 @@ public class PipDismissViewController { return mDismissTargetScreenBounds; } /** * @return whether the PIP is positioned on the dismiss target enough to be dismissed. */ public boolean shouldDismiss(Rect pinnedStack) { return calculateDistancePercent(pinnedStack) >= DISMISS_THRESHOLD; } }