1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.pip.phone; 18 19 import android.content.Context; 20 import android.graphics.PixelFormat; 21 import android.graphics.Point; 22 import android.graphics.PointF; 23 import android.graphics.Rect; 24 import android.graphics.drawable.Drawable; 25 import android.view.Gravity; 26 import android.view.LayoutInflater; 27 import android.view.View; 28 import android.view.View.OnLayoutChangeListener; 29 import android.view.ViewGroup; 30 import android.view.WindowManager; 31 import android.view.WindowManager.LayoutParams; 32 import android.widget.FrameLayout; 33 34 import com.android.systemui.Interpolators; 35 import com.android.systemui.R; 36 import com.android.systemui.recents.misc.SystemServicesProxy; 37 38 public class PipDismissViewController { 39 40 // This delay controls how long to wait before we show the target when the user first moves 41 // the PIP, to prevent the target from animating if the user just wants to fling the PIP 42 private static final int SHOW_TARGET_DELAY = 100; 43 private static final int SHOW_TARGET_DURATION = 350; 44 private static final int HIDE_TARGET_DURATION = 225; 45 46 private Context mContext; 47 private WindowManager mWindowManager; 48 private View mDismissView; 49 PipDismissViewController(Context context)50 public PipDismissViewController(Context context) { 51 mContext = context; 52 mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 53 } 54 55 /** 56 * Creates the dismiss target for showing via {@link #showDismissTarget()}. 57 */ createDismissTarget()58 public void createDismissTarget() { 59 if (mDismissView == null) { 60 // Determine sizes for the view 61 final Rect stableInsets = new Rect(); 62 SystemServicesProxy.getInstance(mContext).getStableInsets(stableInsets); 63 final Point windowSize = new Point(); 64 mWindowManager.getDefaultDisplay().getRealSize(windowSize); 65 final int gradientHeight = mContext.getResources().getDimensionPixelSize( 66 R.dimen.pip_dismiss_gradient_height); 67 final int bottomMargin = mContext.getResources().getDimensionPixelSize( 68 R.dimen.pip_dismiss_text_bottom_margin); 69 70 // Create a new view for the dismiss target 71 LayoutInflater inflater = LayoutInflater.from(mContext); 72 mDismissView = inflater.inflate(R.layout.pip_dismiss_view, null); 73 mDismissView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE); 74 mDismissView.forceHasOverlappingRendering(false); 75 76 // Set the gradient background 77 Drawable gradient = mContext.getResources().getDrawable(R.drawable.pip_dismiss_scrim); 78 gradient.setAlpha((int) (255 * 0.85f)); 79 mDismissView.setBackground(gradient); 80 81 // Adjust bottom margins of the text 82 View text = mDismissView.findViewById(R.id.pip_dismiss_text); 83 FrameLayout.LayoutParams tlp = (FrameLayout.LayoutParams) text.getLayoutParams(); 84 tlp.bottomMargin = stableInsets.bottom + bottomMargin; 85 86 // Add the target to the window 87 LayoutParams lp = new LayoutParams( 88 LayoutParams.MATCH_PARENT, gradientHeight, 89 0, windowSize.y - gradientHeight, 90 LayoutParams.TYPE_NAVIGATION_BAR_PANEL, 91 LayoutParams.FLAG_LAYOUT_IN_SCREEN 92 | LayoutParams.FLAG_NOT_TOUCHABLE 93 | LayoutParams.FLAG_NOT_FOCUSABLE, 94 PixelFormat.TRANSLUCENT); 95 lp.setTitle("pip-dismiss-overlay"); 96 lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 97 lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; 98 mWindowManager.addView(mDismissView, lp); 99 } 100 mDismissView.animate().cancel(); 101 } 102 103 /** 104 * Shows the dismiss target. 105 */ showDismissTarget()106 public void showDismissTarget() { 107 mDismissView.animate() 108 .alpha(1f) 109 .setInterpolator(Interpolators.LINEAR) 110 .setStartDelay(SHOW_TARGET_DELAY) 111 .setDuration(SHOW_TARGET_DURATION) 112 .start(); 113 } 114 115 /** 116 * Hides and destroys the dismiss target. 117 */ destroyDismissTarget()118 public void destroyDismissTarget() { 119 if (mDismissView != null) { 120 mDismissView.animate() 121 .alpha(0f) 122 .setInterpolator(Interpolators.LINEAR) 123 .setStartDelay(0) 124 .setDuration(HIDE_TARGET_DURATION) 125 .withEndAction(new Runnable() { 126 @Override 127 public void run() { 128 mWindowManager.removeViewImmediate(mDismissView); 129 mDismissView = null; 130 } 131 }) 132 .start(); 133 } 134 } 135 } 136