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 17package com.android.systemui.pip.phone; 18 19import android.content.Context; 20import android.graphics.PixelFormat; 21import android.graphics.Point; 22import android.graphics.PointF; 23import android.graphics.Rect; 24import android.graphics.drawable.Drawable; 25import android.view.Gravity; 26import android.view.LayoutInflater; 27import android.view.View; 28import android.view.View.OnLayoutChangeListener; 29import android.view.ViewGroup; 30import android.view.WindowManager; 31import android.view.WindowManager.LayoutParams; 32import android.widget.FrameLayout; 33 34import com.android.systemui.Interpolators; 35import com.android.systemui.R; 36import com.android.systemui.recents.misc.SystemServicesProxy; 37 38public 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 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 */ 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 | LayoutParams.FLAG_HARDWARE_ACCELERATED, 95 PixelFormat.TRANSLUCENT); 96 lp.setTitle("pip-dismiss-overlay"); 97 lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 98 lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; 99 mWindowManager.addView(mDismissView, lp); 100 } 101 mDismissView.animate().cancel(); 102 } 103 104 /** 105 * Shows the dismiss target. 106 */ 107 public void showDismissTarget() { 108 mDismissView.animate() 109 .alpha(1f) 110 .setInterpolator(Interpolators.LINEAR) 111 .setStartDelay(SHOW_TARGET_DELAY) 112 .setDuration(SHOW_TARGET_DURATION) 113 .start(); 114 } 115 116 /** 117 * Hides and destroys the dismiss target. 118 */ 119 public void destroyDismissTarget() { 120 if (mDismissView != null) { 121 mDismissView.animate() 122 .alpha(0f) 123 .setInterpolator(Interpolators.LINEAR) 124 .setStartDelay(0) 125 .setDuration(HIDE_TARGET_DURATION) 126 .withEndAction(new Runnable() { 127 @Override 128 public void run() { 129 mWindowManager.removeViewImmediate(mDismissView); 130 mDismissView = null; 131 } 132 }) 133 .start(); 134 } 135 } 136} 137