/*
|
* Copyright (C) 2014 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.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License
|
*/
|
|
package com.android.systemui.qs;
|
|
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
|
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
|
import android.content.Context;
|
import android.content.res.Configuration;
|
import android.graphics.Point;
|
import android.util.AttributeSet;
|
import android.view.View;
|
import android.widget.FrameLayout;
|
|
import com.android.systemui.R;
|
import com.android.systemui.qs.customize.QSCustomizer;
|
|
/**
|
* Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
|
*/
|
public class QSContainerImpl extends FrameLayout {
|
|
private final Point mSizePoint = new Point();
|
|
private int mHeightOverride = -1;
|
private QSPanel mQSPanel;
|
private View mQSDetail;
|
private QuickStatusBarHeader mHeader;
|
private float mQsExpansion;
|
private QSCustomizer mQSCustomizer;
|
private View mQSFooter;
|
|
private View mBackground;
|
private View mBackgroundGradient;
|
private View mStatusBarBackground;
|
|
private int mSideMargins;
|
private boolean mQsDisabled;
|
|
public QSContainerImpl(Context context, AttributeSet attrs) {
|
super(context, attrs);
|
}
|
|
@Override
|
protected void onFinishInflate() {
|
super.onFinishInflate();
|
mQSPanel = findViewById(R.id.quick_settings_panel);
|
mQSDetail = findViewById(R.id.qs_detail);
|
mHeader = findViewById(R.id.header);
|
mQSCustomizer = findViewById(R.id.qs_customize);
|
mQSFooter = findViewById(R.id.qs_footer);
|
mBackground = findViewById(R.id.quick_settings_background);
|
mStatusBarBackground = findViewById(R.id.quick_settings_status_bar_background);
|
mBackgroundGradient = findViewById(R.id.quick_settings_gradient_view);
|
mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
|
|
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
setMargins();
|
}
|
|
@Override
|
protected void onConfigurationChanged(Configuration newConfig) {
|
super.onConfigurationChanged(newConfig);
|
setBackgroundGradientVisibility(newConfig);
|
updateResources();
|
mSizePoint.set(0, 0); // Will be retrieved on next measure pass.
|
}
|
|
@Override
|
public boolean performClick() {
|
// Want to receive clicks so missing QQS tiles doesn't cause collapse, but
|
// don't want to do anything with them.
|
return true;
|
}
|
|
@Override
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
// QSPanel will show as many rows as it can (up to TileLayout.MAX_ROWS) such that the
|
// bottom and footer are inside the screen.
|
Configuration config = getResources().getConfiguration();
|
boolean navBelow = config.smallestScreenWidthDp >= 600
|
|| config.orientation != Configuration.ORIENTATION_LANDSCAPE;
|
MarginLayoutParams layoutParams = (MarginLayoutParams) mQSPanel.getLayoutParams();
|
|
// The footer is pinned to the bottom of QSPanel (same bottoms), therefore we don't need to
|
// subtract its height. We do not care if the collapsed notifications fit in the screen.
|
int maxQs = getDisplayHeight() - layoutParams.topMargin - layoutParams.bottomMargin
|
- getPaddingBottom();
|
if (navBelow) {
|
maxQs -= getResources().getDimensionPixelSize(R.dimen.navigation_bar_height);
|
}
|
// Measure with EXACTLY. That way, PagedTileLayout will only use excess height and will be
|
// measured last, after other views and padding is accounted for.
|
mQSPanel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(maxQs, MeasureSpec.EXACTLY));
|
int width = mQSPanel.getMeasuredWidth();
|
int height = layoutParams.topMargin + layoutParams.bottomMargin
|
+ mQSPanel.getMeasuredHeight() + getPaddingBottom();
|
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
|
|
// QSCustomizer will always be the height of the screen, but do this after
|
// other measuring to avoid changing the height of the QS.
|
mQSCustomizer.measure(widthMeasureSpec,
|
MeasureSpec.makeMeasureSpec(getDisplayHeight(), MeasureSpec.EXACTLY));
|
}
|
|
@Override
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
super.onLayout(changed, left, top, right, bottom);
|
updateExpansion();
|
}
|
|
public void disable(int state1, int state2, boolean animate) {
|
final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
|
if (disabled == mQsDisabled) return;
|
mQsDisabled = disabled;
|
setBackgroundGradientVisibility(getResources().getConfiguration());
|
mBackground.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
|
}
|
|
private void updateResources() {
|
LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
|
layoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
|
com.android.internal.R.dimen.quick_qs_offset_height);
|
|
mQSPanel.setLayoutParams(layoutParams);
|
}
|
|
/**
|
* Overrides the height of this view (post-layout), so that the content is clipped to that
|
* height and the background is set to that height.
|
*
|
* @param heightOverride the overridden height
|
*/
|
public void setHeightOverride(int heightOverride) {
|
mHeightOverride = heightOverride;
|
updateExpansion();
|
}
|
|
public void updateExpansion() {
|
int height = calculateContainerHeight();
|
setBottom(getTop() + height);
|
mQSDetail.setBottom(getTop() + height);
|
// Pin QS Footer to the bottom of the panel.
|
mQSFooter.setTranslationY(height - mQSFooter.getHeight());
|
mBackground.setTop(mQSPanel.getTop());
|
mBackground.setBottom(height);
|
}
|
|
protected int calculateContainerHeight() {
|
int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
|
return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
|
: Math.round(mQsExpansion * (heightOverride - mHeader.getHeight()))
|
+ mHeader.getHeight();
|
}
|
|
private void setBackgroundGradientVisibility(Configuration newConfig) {
|
if (newConfig.orientation == ORIENTATION_LANDSCAPE) {
|
mBackgroundGradient.setVisibility(View.INVISIBLE);
|
mStatusBarBackground.setVisibility(View.INVISIBLE);
|
} else {
|
mBackgroundGradient.setVisibility(mQsDisabled ? View.INVISIBLE : View.VISIBLE);
|
mStatusBarBackground.setVisibility(View.VISIBLE);
|
}
|
}
|
|
public void setExpansion(float expansion) {
|
mQsExpansion = expansion;
|
updateExpansion();
|
}
|
|
private void setMargins() {
|
setMargins(mQSDetail);
|
setMargins(mBackground);
|
setMargins(mQSFooter);
|
mQSPanel.setMargins(mSideMargins);
|
mHeader.setMargins(mSideMargins);
|
}
|
|
private void setMargins(View view) {
|
FrameLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
lp.rightMargin = mSideMargins;
|
lp.leftMargin = mSideMargins;
|
}
|
|
private int getDisplayHeight() {
|
if (mSizePoint.y == 0) {
|
getDisplay().getRealSize(mSizePoint);
|
}
|
return mSizePoint.y;
|
}
|
}
|