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