1 /* 2 * Copyright (C) 2014 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.qs; 18 19 import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS; 20 21 import android.content.Context; 22 import android.content.res.Configuration; 23 import android.graphics.Point; 24 import android.util.AttributeSet; 25 import android.view.View; 26 import android.widget.FrameLayout; 27 28 import com.android.systemui.R; 29 import com.android.systemui.SysUiServiceProvider; 30 import com.android.systemui.qs.customize.QSCustomizer; 31 import com.android.systemui.statusbar.CommandQueue; 32 33 /** 34 * Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader} 35 */ 36 public class QSContainerImpl extends FrameLayout { 37 38 private final Point mSizePoint = new Point(); 39 40 private int mHeightOverride = -1; 41 private QSPanel mQSPanel; 42 private View mQSDetail; 43 private QuickStatusBarHeader mHeader; 44 private float mQsExpansion; 45 private QSCustomizer mQSCustomizer; 46 private View mQSFooter; 47 48 private View mBackground; 49 private View mBackgroundGradient; 50 private View mStatusBarBackground; 51 52 private int mSideMargins; 53 private boolean mQsDisabled; 54 QSContainerImpl(Context context, AttributeSet attrs)55 public QSContainerImpl(Context context, AttributeSet attrs) { 56 super(context, attrs); 57 } 58 59 @Override onFinishInflate()60 protected void onFinishInflate() { 61 super.onFinishInflate(); 62 mQSPanel = findViewById(R.id.quick_settings_panel); 63 mQSDetail = findViewById(R.id.qs_detail); 64 mHeader = findViewById(R.id.header); 65 mQSCustomizer = findViewById(R.id.qs_customize); 66 mQSFooter = findViewById(R.id.qs_footer); 67 mBackground = findViewById(R.id.quick_settings_background); 68 mStatusBarBackground = findViewById(R.id.quick_settings_status_bar_background); 69 mBackgroundGradient = findViewById(R.id.quick_settings_gradient_view); 70 mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings); 71 72 setClickable(true); 73 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); 74 setMargins(); 75 } 76 77 @Override onConfigurationChanged(Configuration newConfig)78 protected void onConfigurationChanged(Configuration newConfig) { 79 super.onConfigurationChanged(newConfig); 80 81 // Hide the backgrounds when in landscape mode. 82 if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { 83 mBackgroundGradient.setVisibility(View.INVISIBLE); 84 mStatusBarBackground.setVisibility(View.INVISIBLE); 85 } else { 86 mBackgroundGradient.setVisibility(View.VISIBLE); 87 mStatusBarBackground.setVisibility(View.VISIBLE); 88 } 89 90 updateResources(); 91 mSizePoint.set(0, 0); // Will be retrieved on next measure pass. 92 } 93 94 @Override performClick()95 public boolean performClick() { 96 // Want to receive clicks so missing QQS tiles doesn't cause collapse, but 97 // don't want to do anything with them. 98 return true; 99 } 100 101 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)102 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 103 // Since we control our own bottom, be whatever size we want. 104 // Otherwise the QSPanel ends up with 0 height when the window is only the 105 // size of the status bar. 106 mQSPanel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec( 107 MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED)); 108 int width = mQSPanel.getMeasuredWidth(); 109 LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams(); 110 int height = layoutParams.topMargin + layoutParams.bottomMargin 111 + mQSPanel.getMeasuredHeight(); 112 super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), 113 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 114 115 // QSCustomizer will always be the height of the screen, but do this after 116 // other measuring to avoid changing the height of the QS. 117 mQSCustomizer.measure(widthMeasureSpec, 118 MeasureSpec.makeMeasureSpec(getDisplayHeight(), MeasureSpec.EXACTLY)); 119 } 120 121 @Override onLayout(boolean changed, int left, int top, int right, int bottom)122 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 123 super.onLayout(changed, left, top, right, bottom); 124 updateExpansion(); 125 } 126 disable(int state1, int state2, boolean animate)127 public void disable(int state1, int state2, boolean animate) { 128 final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0; 129 if (disabled == mQsDisabled) return; 130 mQsDisabled = disabled; 131 mBackgroundGradient.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE); 132 mBackground.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE); 133 } 134 updateResources()135 private void updateResources() { 136 LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams(); 137 layoutParams.topMargin = mContext.getResources().getDimensionPixelSize( 138 com.android.internal.R.dimen.quick_qs_offset_height); 139 140 mQSPanel.setLayoutParams(layoutParams); 141 } 142 143 /** 144 * Overrides the height of this view (post-layout), so that the content is clipped to that 145 * height and the background is set to that height. 146 * 147 * @param heightOverride the overridden height 148 */ setHeightOverride(int heightOverride)149 public void setHeightOverride(int heightOverride) { 150 mHeightOverride = heightOverride; 151 updateExpansion(); 152 } 153 updateExpansion()154 public void updateExpansion() { 155 int height = calculateContainerHeight(); 156 setBottom(getTop() + height); 157 mQSDetail.setBottom(getTop() + height); 158 // Pin QS Footer to the bottom of the panel. 159 mQSFooter.setTranslationY(height - mQSFooter.getHeight()); 160 mBackground.setTop(mQSPanel.getTop()); 161 mBackground.setBottom(height); 162 } 163 calculateContainerHeight()164 protected int calculateContainerHeight() { 165 int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight(); 166 return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight() 167 : Math.round(mQsExpansion * (heightOverride - mHeader.getHeight())) 168 + mHeader.getHeight(); 169 } 170 setExpansion(float expansion)171 public void setExpansion(float expansion) { 172 mQsExpansion = expansion; 173 updateExpansion(); 174 } 175 setMargins()176 private void setMargins() { 177 setMargins(mQSDetail); 178 setMargins(mBackground); 179 setMargins(mQSFooter); 180 mQSPanel.setMargins(mSideMargins); 181 mHeader.setMargins(mSideMargins); 182 } 183 setMargins(View view)184 private void setMargins(View view) { 185 FrameLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams(); 186 lp.rightMargin = mSideMargins; 187 lp.leftMargin = mSideMargins; 188 } 189 getDisplayHeight()190 private int getDisplayHeight() { 191 if (mSizePoint.y == 0) { 192 getDisplay().getRealSize(mSizePoint); 193 } 194 return mSizePoint.y; 195 } 196 } 197