diff options
11 files changed, 357 insertions, 319 deletions
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml index ddff0f031fb6..bed8f1be54fe 100644 --- a/packages/SystemUI/res/layout/qs_detail.xml +++ b/packages/SystemUI/res/layout/qs_detail.xml @@ -14,12 +14,35 @@ See the License for the specific language governing permissions and limitations under the License. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<!-- Extends LinearLayout --> +<com.android.systemui.qs.QSDetail + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:systemui="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/qs_detail_background" + android:paddingBottom="8dp" + android:clickable="true" + android:visibility="invisible" + android:orientation="vertical"> + + <include + android:id="@+id/qs_detail_header" + layout="@layout/qs_detail_header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="28dp" + /> + + <com.android.systemui.statusbar.AlphaOptimizedImageView + android:id="@+id/qs_detail_header_progress" + android:src="@drawable/indeterminate_anim" + android:alpha="0" + android:background="@color/qs_detail_progress_track" android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@drawable/qs_detail_background" - android:paddingBottom="8dp" - android:orientation="vertical"> + android:layout_height="wrap_content" + systemui:hasOverlappingRendering="false" + /> <FrameLayout android:id="@android:id/content" @@ -53,4 +76,4 @@ android:focusable="true"/> </LinearLayout> -</LinearLayout> +</com.android.systemui.qs.QSDetail> diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml index 153e35f1f675..df46271b5d64 100644 --- a/packages/SystemUI/res/layout/qs_detail_header.xml +++ b/packages/SystemUI/res/layout/qs_detail_header.xml @@ -19,7 +19,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingEnd="@dimen/qs_panel_padding" - android:visibility="invisible" android:background="@drawable/btn_borderless_rect" android:gravity="center"> diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml index 45236a075e72..9f90af231b20 100644 --- a/packages/SystemUI/res/layout/qs_panel.xml +++ b/packages/SystemUI/res/layout/qs_panel.xml @@ -30,4 +30,6 @@ <include layout="@layout/quick_status_bar_expanded_header" /> + <include android:id="@+id/qs_detail" layout="@layout/qs_detail" /> + </com.android.systemui.qs.QSContainer> diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml index 07ac6a58e351..84df0d643e58 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml @@ -159,14 +159,6 @@ android:clipChildren="false" android:clipToPadding="false" /> - <include - android:id="@+id/qs_detail_header" - layout="@layout/qs_detail_header" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="28dp" - /> - <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/qs_detail_header_progress" android:src="@drawable/indeterminate_anim" diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java index 32eeb0787113..34dfd6c55abd 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java @@ -40,6 +40,7 @@ public class QSContainer extends FrameLayout { private int mHeightOverride = -1; private QSPanel mQSPanel; + private QSDetail mQSDetail; protected BaseStatusBarHeader mHeader; private float mQsExpansion; private boolean mQsExpanded; @@ -57,6 +58,8 @@ public class QSContainer extends FrameLayout { protected void onFinishInflate() { super.onFinishInflate(); mQSPanel = (QSPanel) findViewById(R.id.quick_settings_panel); + mQSDetail = (QSDetail) findViewById(R.id.qs_detail); + mQSDetail.setQsPanel(mQSPanel); mHeader = (BaseStatusBarHeader) findViewById(R.id.header); } @@ -82,7 +85,7 @@ public class QSContainer extends FrameLayout { * during closing the detail panel, this already returns the smaller height. */ public int getDesiredHeight() { - if (mQSPanel.isClosingDetail()) { + if (mQSDetail.isClosingDetail()) { return mQSPanel.getGridHeight() + mHeader.getCollapsedHeight() + getPaddingBottom(); } else { return getMeasuredHeight(); @@ -94,6 +97,7 @@ public class QSContainer extends FrameLayout { int height = (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight())) + mHeader.getCollapsedHeight(); setBottom(getTop() + height); + mQSDetail.setBottom(getTop() + height); } private void updateQsState() { @@ -115,6 +119,10 @@ public class QSContainer extends FrameLayout { return mQSPanel; } + public boolean isShowingDetail() { + return mQSPanel.isShowingCustomize() || mQSDetail.isShowingDetail(); + } + public void setHeaderClickable(boolean clickable) { if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable); mHeader.setClickable(clickable); @@ -154,6 +162,7 @@ public class QSContainer extends FrameLayout { } mHeader.setExpansion(mKeyguardShowing ? 1 : expansion); mQSPanel.setTranslationY(translationScaleY * mQSPanel.getHeight()); + mQSDetail.setFullyExpanded(expansion == 1); updateBottom(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java new file mode 100644 index 000000000000..50c0cca8d8e7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2016 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 android.animation.Animator; +import android.animation.Animator.AnimatorListener; +import android.animation.AnimatorListenerAdapter; +import android.annotation.Nullable; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.drawable.Animatable; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.view.View; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.Switch; +import android.widget.TextView; +import com.android.internal.logging.MetricsLogger; +import com.android.systemui.FontSizeUtils; +import com.android.systemui.R; +import com.android.systemui.qs.QSTile.DetailAdapter; +import com.android.systemui.statusbar.phone.QSTileHost; + +public class QSDetail extends LinearLayout { + + private static final String TAG = "QSDetail"; + private static final long FADE_DURATION = 300; + + private final SparseArray<View> mDetailViews = new SparseArray<>(); + + private ViewGroup mDetailContent; + private TextView mDetailSettingsButton; + private TextView mDetailDoneButton; + private QSDetailClipper mClipper; + private DetailAdapter mDetailAdapter; + private QSPanel mQsPanel; + + private View mQsDetailHeader; + private TextView mQsDetailHeaderTitle; + private Switch mQsDetailHeaderSwitch; + private ImageView mQsDetailHeaderProgress; + + private QSTileHost mHost; + + private boolean mScanState; + private boolean mClosingDetail; + private boolean mFullyExpanded; + private View mQsDetailHeaderBack; + + public QSDetail(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + FontSizeUtils.updateFontSize(mDetailDoneButton, R.dimen.qs_detail_button_text_size); + FontSizeUtils.updateFontSize(mDetailSettingsButton, R.dimen.qs_detail_button_text_size); + + for (int i = 0; i < mDetailViews.size(); i++) { + mDetailViews.valueAt(i).dispatchConfigurationChanged(newConfig); + } + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mDetailContent = (ViewGroup) findViewById(android.R.id.content); + mDetailSettingsButton = (TextView) findViewById(android.R.id.button2); + mDetailDoneButton = (TextView) findViewById(android.R.id.button1); + + mQsDetailHeader = findViewById(R.id.qs_detail_header); + mQsDetailHeaderBack = mQsDetailHeader.findViewById(com.android.internal.R.id.up); + mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title); + mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle); + mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress); + + updateDetailText(); + + mClipper = new QSDetailClipper(this); + + final OnClickListener doneListener = new OnClickListener() { + @Override + public void onClick(View v) { + announceForAccessibility( + mContext.getString(R.string.accessibility_desc_quick_settings)); + mQsPanel.closeDetail(); + } + }; + mQsDetailHeaderBack.setOnClickListener(doneListener); + mDetailDoneButton.setOnClickListener(doneListener); + } + + public void setQsPanel(QSPanel panel) { + mQsPanel = panel; + mQsPanel.setCallback(mQsPanelCallback); + } + + public void setHost(QSTileHost host) { + mHost = host; + } + public boolean isShowingDetail() { + return mDetailAdapter != null; + } + + public void setFullyExpanded(boolean fullyExpanded) { + mFullyExpanded = fullyExpanded; + } + + private void updateDetailText() { + mDetailDoneButton.setText(R.string.quick_settings_done); + mDetailSettingsButton.setText(R.string.quick_settings_more_settings); + } + + public void updateResources() { + updateDetailText(); + } + + public boolean isClosingDetail() { + return mClosingDetail; + } + + private void handleShowingDetail(final QSTile.DetailAdapter adapter, int x, int y) { + final boolean showingDetail = adapter != null; + setClickable(showingDetail); + if (showingDetail) { + mQsDetailHeaderTitle.setText(adapter.getTitle()); + final Boolean toggleState = adapter.getToggleState(); + if (toggleState == null) { + mQsDetailHeaderSwitch.setVisibility(INVISIBLE); + mQsDetailHeader.setClickable(false); + } else { + mQsDetailHeaderSwitch.setVisibility(VISIBLE); + mQsDetailHeaderSwitch.setChecked(toggleState); + mQsDetailHeader.setClickable(true); + mQsDetailHeader.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + boolean checked = !mQsDetailHeaderSwitch.isChecked(); + mQsDetailHeaderSwitch.setChecked(checked); + adapter.setToggleState(checked); + } + }); + } + } + + boolean visibleDiff = (mDetailAdapter != null) != (adapter != null); + if (!visibleDiff && mDetailAdapter == adapter) return; // already in right state + AnimatorListener listener = null; + if (adapter != null) { + int viewCacheIndex = adapter.getMetricsCategory(); + View detailView = adapter.createDetailView(mContext, mDetailViews.get(viewCacheIndex), + mDetailContent); + if (detailView == null) throw new IllegalStateException("Must return detail view"); + + final Intent settingsIntent = adapter.getSettingsIntent(); + mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE); + mDetailSettingsButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mHost.startActivityDismissingKeyguard(settingsIntent); + } + }); + + mDetailContent.removeAllViews(); + mDetailContent.addView(detailView); + mDetailViews.put(viewCacheIndex, detailView); + MetricsLogger.visible(mContext, adapter.getMetricsCategory()); + announceForAccessibility(mContext.getString( + R.string.accessibility_quick_settings_detail, + adapter.getTitle())); + mDetailAdapter = adapter; + listener = mHideGridContentWhenDone; + setVisibility(View.VISIBLE); + } else { + if (mDetailAdapter != null) { + MetricsLogger.hidden(mContext, mDetailAdapter.getMetricsCategory()); + } + mClosingDetail = true; + mDetailAdapter = null; + listener = mTeardownDetailWhenDone; + mQsPanel.setGridContentVisibility(true); + mQsPanelCallback.onScanStateChanged(false); + } + sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + if (visibleDiff) { + if (mFullyExpanded || mDetailAdapter != null) { + setAlpha(1); + mClipper.animateCircularClip(x, y, mDetailAdapter != null, listener); + } else { + animate().alpha(0) + .setDuration(FADE_DURATION) + .setListener(listener) + .start(); + } + } + } + + private void handleToggleStateChanged(boolean state) { + mQsDetailHeaderSwitch.setChecked(state); + } + + private void handleScanStateChanged(boolean state) { + if (mScanState == state) return; + mScanState = state; + final Animatable anim = (Animatable) mQsDetailHeaderProgress.getDrawable(); + if (state) { + mQsDetailHeaderProgress.animate().alpha(1f); + anim.start(); + } else { + mQsDetailHeaderProgress.animate().alpha(0f); + anim.stop(); + } + } + + private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() { + @Override + public void onToggleStateChanged(final boolean state) { + post(new Runnable() { + @Override + public void run() { + handleToggleStateChanged(state); + } + }); + } + + @Override + public void onShowingDetail(final DetailAdapter detail, final int x, final int y) { + post(new Runnable() { + @Override + public void run() { + handleShowingDetail(detail, x, y); + } + }); + } + + @Override + public void onScanStateChanged(final boolean state) { + post(new Runnable() { + @Override + public void run() { + handleScanStateChanged(state); + } + }); + } + }; + + private final AnimatorListenerAdapter mHideGridContentWhenDone = new AnimatorListenerAdapter() { + public void onAnimationCancel(Animator animation) { + // If we have been cancelled, remove the listener so that onAnimationEnd doesn't get + // called, this will avoid accidentally turning off the grid when we don't want to. + animation.removeListener(this); + }; + + @Override + public void onAnimationEnd(Animator animation) { + // Only hide content if still in detail state. + if (mDetailAdapter != null) { + mQsPanel.setGridContentVisibility(false); + } + } + }; + + private final AnimatorListenerAdapter mTeardownDetailWhenDone = new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + mDetailContent.removeAllViews(); + setVisibility(View.INVISIBLE); + mClosingDetail = false; + }; + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 4ffa527c6a42..53abe37d4752 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -16,12 +16,8 @@ package com.android.systemui.qs; -import android.animation.Animator; -import android.animation.Animator.AnimatorListener; -import android.animation.AnimatorListenerAdapter; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; import android.os.Handler; @@ -29,16 +25,11 @@ import android.os.Message; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; -import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.TextView; - import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; -import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.qs.QSTile.DetailAdapter; import com.android.systemui.qs.customize.QSCustomizer; @@ -60,21 +51,14 @@ public class QSPanel extends FrameLayout implements Tunable { protected final Context mContext; protected final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>(); - private final View mDetail; - private final ViewGroup mDetailContent; - private final TextView mDetailSettingsButton; - private final TextView mDetailDoneButton; protected final View mBrightnessView; - private final QSDetailClipper mClipper; private final H mHandler = new H(); private int mPanelPaddingBottom; private int mBrightnessPaddingTop; private boolean mExpanded; private boolean mListening; - private boolean mClosingDetail; - private Record mDetailRecord; private Callback mCallback; private BrightnessController mBrightnessController; protected QSTileHost mHost; @@ -86,6 +70,7 @@ public class QSPanel extends FrameLayout implements Tunable { protected QSTileLayout mTileLayout; private QSCustomizer mCustomizePanel; + private Record mDetailRecord; public QSPanel(Context context) { this(context, null); @@ -95,14 +80,6 @@ public class QSPanel extends FrameLayout implements Tunable { super(context, attrs); mContext = context; - mDetail = LayoutInflater.from(context).inflate(R.layout.qs_detail, this, false); - mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content); - mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2); - mDetailDoneButton = (TextView) mDetail.findViewById(android.R.id.button1); - updateDetailText(); - mDetail.setVisibility(GONE); - mDetail.setClickable(true); - addView(mDetail); mQsContainer = new LinearLayout(mContext); mQsContainer.setOrientation(LinearLayout.VERTICAL); @@ -132,21 +109,16 @@ public class QSPanel extends FrameLayout implements Tunable { mFooter = new QSFooter(this, context); mQsContainer.addView(mFooter.getView()); - mClipper = new QSDetailClipper(mDetail); updateResources(); mBrightnessController = new BrightnessController(getContext(), (ImageView) findViewById(R.id.brightness_icon), (ToggleSlider) findViewById(R.id.brightness_slider)); - mDetailDoneButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - announceForAccessibility( - mContext.getString(R.string.accessibility_desc_quick_settings)); - closeDetail(); - } - }); + } + + public boolean isShowingCustomize() { + return mCustomizePanel != null && mCustomizePanel.isCustomizing(); } @Override @@ -189,11 +161,6 @@ public class QSPanel extends FrameLayout implements Tunable { mCustomizePanel.setHost(mHost); } - private void updateDetailText() { - mDetailDoneButton.setText(R.string.quick_settings_done); - mDetailSettingsButton.setText(R.string.quick_settings_more_settings); - } - public void setBrightnessMirror(BrightnessMirrorController c) { super.onFinishInflate(); ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider); @@ -227,7 +194,6 @@ public class QSPanel extends FrameLayout implements Tunable { if (mListening) { refreshAllTiles(); } - updateDetailText(); if (mTileLayout != null) { mTileLayout.updateResources(); } @@ -236,18 +202,6 @@ public class QSPanel extends FrameLayout implements Tunable { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - FontSizeUtils.updateFontSize(mDetailDoneButton, R.dimen.qs_detail_button_text_size); - FontSizeUtils.updateFontSize(mDetailSettingsButton, R.dimen.qs_detail_button_text_size); - - // We need to poke the detail views as well as they might not be attached to the view - // hierarchy but reused at a later point. - int count = mRecords.size(); - for (int i = 0; i < count; i++) { - View detailView = mRecords.get(i).detailView; - if (detailView != null) { - detailView.dispatchConfigurationChanged(newConfig); - } - } mFooter.onConfigurationChanged(); } @@ -295,7 +249,7 @@ public class QSPanel extends FrameLayout implements Tunable { public void showDetailAdapter(boolean show, DetailAdapter adapter, int[] locationInWindow) { int xInWindow = locationInWindow[0]; int yInWindow = locationInWindow[1]; - mDetail.getLocationInWindow(locationInWindow); + ((View) getParent()).getLocationInWindow(locationInWindow); Record r = new Record(); r.detailAdapter = adapter; @@ -320,9 +274,6 @@ public class QSPanel extends FrameLayout implements Tunable { for (QSTile<?> tile : tiles) { addTile(tile); } - if (isShowingDetail()) { - mDetail.bringToFront(); - } } private void drawTile(TileRecord r, QSTile.State state) { @@ -340,9 +291,7 @@ public class QSPanel extends FrameLayout implements Tunable { final QSTile.Callback callback = new QSTile.Callback() { @Override public void onStateChanged(QSTile.State state) { - if (!r.openingDetail) { - drawTile(r, state); - } + drawTile(r, state); } @Override @@ -417,11 +366,6 @@ public class QSPanel extends FrameLayout implements Tunable { tile.click(); } - public boolean isShowingDetail() { - return mDetailRecord != null - || (mCustomizePanel != null && mCustomizePanel.isCustomizing()); - } - public void closeDetail() { if (mCustomizePanel != null && mCustomizePanel.isCustomizing()) { // Treat this as a detail panel for now, to make things easy. @@ -431,10 +375,6 @@ public class QSPanel extends FrameLayout implements Tunable { showDetail(false, mDetailRecord); } - public boolean isClosingDetail() { - return mClosingDetail; - } - public int getGridHeight() { return mQsContainer.getMeasuredHeight(); } @@ -465,58 +405,25 @@ public class QSPanel extends FrameLayout implements Tunable { } r.tile.setDetailListening(show); int x = r.tileView.getLeft() + r.tileView.getWidth() / 2; - int y = r.tileView.getTop() + mTileLayout.getOffsetTop(r) + r.tileView.getHeight() / 2; + int y = r.tileView.getTop() + mTileLayout.getOffsetTop(r) + r.tileView.getHeight() / 2 + + getTop(); handleShowDetailImpl(r, show, x, y); } private void handleShowDetailImpl(Record r, boolean show, int x, int y) { - boolean visibleDiff = (mDetailRecord != null) != show; - if (!visibleDiff && mDetailRecord == r) return; // already in right state - DetailAdapter detailAdapter = null; - AnimatorListener listener = null; - if (show) { - detailAdapter = r.detailAdapter; - r.detailView = detailAdapter.createDetailView(mContext, r.detailView, mDetailContent); - if (r.detailView == null) throw new IllegalStateException("Must return detail view"); - - final Intent settingsIntent = detailAdapter.getSettingsIntent(); - mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE); - mDetailSettingsButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mHost.startActivityDismissingKeyguard(settingsIntent); - } - }); - - mDetailContent.removeAllViews(); - mDetail.bringToFront(); - mDetailContent.addView(r.detailView); - MetricsLogger.visible(mContext, detailAdapter.getMetricsCategory()); - announceForAccessibility(mContext.getString( - R.string.accessibility_quick_settings_detail, - detailAdapter.getTitle())); - setDetailRecord(r); - listener = mHideGridContentWhenDone; - if (r instanceof TileRecord && visibleDiff) { - ((TileRecord) r).openingDetail = true; - } - } else { - if (mDetailRecord != null) { - MetricsLogger.hidden(mContext, mDetailRecord.detailAdapter.getMetricsCategory()); - } - mClosingDetail = true; - setGridContentVisibility(true); - listener = mTeardownDetailWhenDone; - fireScanStateChanged(false); - } - sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); - fireShowingDetail(show ? detailAdapter : null); - if (visibleDiff) { - mClipper.animateCircularClip(x, y, show, listener); - } + setDetailRecord(show ? r : null); + fireShowingDetail(show ? r.detailAdapter : null, x, y); } - private void setGridContentVisibility(boolean visible) { + private void setDetailRecord(Record r) { + if (r == mDetailRecord) return; + mDetailRecord = r; + final boolean scanState = mDetailRecord instanceof TileRecord + && ((TileRecord) mDetailRecord).scanState; + fireScanStateChanged(scanState); + } + + void setGridContentVisibility(boolean visible) { int newVis = visible ? VISIBLE : INVISIBLE; mQsContainer.setVisibility(newVis); if (mGridContentVisible != visible) { @@ -532,9 +439,9 @@ public class QSPanel extends FrameLayout implements Tunable { } } - private void fireShowingDetail(QSTile.DetailAdapter detail) { + private void fireShowingDetail(DetailAdapter detail, int x, int y) { if (mCallback != null) { - mCallback.onShowingDetail(detail); + mCallback.onShowingDetail(detail, x, y); } } @@ -550,14 +457,6 @@ public class QSPanel extends FrameLayout implements Tunable { } } - private void setDetailRecord(Record r) { - if (r == mDetailRecord) return; - mDetailRecord = r; - final boolean scanState = mDetailRecord instanceof TileRecord - && ((TileRecord) mDetailRecord).scanState; - fireScanStateChanged(scanState); - } - public void clickTile(ComponentName tile) { final String spec = CustomTile.toSpec(tile); final int N = mRecords.size(); @@ -581,7 +480,6 @@ public class QSPanel extends FrameLayout implements Tunable { } protected static class Record { - View detailView; DetailAdapter detailAdapter; int x; int y; @@ -591,45 +489,10 @@ public class QSPanel extends FrameLayout implements Tunable { public QSTile<?> tile; public QSTileBaseView tileView; public boolean scanState; - public boolean openingDetail; } - private final AnimatorListenerAdapter mTeardownDetailWhenDone = new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - mDetailContent.removeAllViews(); - setDetailRecord(null); - mClosingDetail = false; - }; - }; - - private final AnimatorListenerAdapter mHideGridContentWhenDone = new AnimatorListenerAdapter() { - public void onAnimationCancel(Animator animation) { - // If we have been cancelled, remove the listener so that onAnimationEnd doesn't get - // called, this will avoid accidentally turning off the grid when we don't want to. - animation.removeListener(this); - redrawTile(); - }; - - @Override - public void onAnimationEnd(Animator animation) { - // Only hide content if still in detail state. - if (mDetailRecord != null) { - setGridContentVisibility(false); - redrawTile(); - } - } - - private void redrawTile() { - if (mDetailRecord instanceof TileRecord) { - final TileRecord tileRecord = (TileRecord) mDetailRecord; - tileRecord.openingDetail = false; - drawTile(tileRecord, tileRecord.tile.getState()); - } - } - }; - public interface Callback { - void onShowingDetail(QSTile.DetailAdapter detail); + void onShowingDetail(DetailAdapter detail, int x, int y); void onToggleStateChanged(boolean state); void onScanStateChanged(boolean state); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 8f0f51f502b7..88a78430e679 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1975,7 +1975,7 @@ public class NotificationPanelView extends PanelView implements } public boolean isQsDetailShowing() { - return mQsContainer.getQsPanel().isShowingDetail(); + return mQsContainer.isShowingDetail(); } public void closeQsDetail() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 17e43c406288..3aa576ffc0a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -69,7 +69,6 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; -import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.Vibrator; @@ -89,7 +88,6 @@ import android.view.ThreadedRenderer; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; -import android.view.ViewParent; import android.view.ViewStub; import android.view.WindowManager; import android.view.WindowManagerGlobal; @@ -97,7 +95,6 @@ import android.view.animation.AccelerateInterpolator; import android.view.animation.Interpolator; import android.widget.ImageView; import android.widget.TextView; - import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.internal.statusbar.NotificationVisibility; @@ -118,6 +115,7 @@ import com.android.systemui.classifier.FalsingManager; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.qs.QSDetail; import com.android.systemui.qs.QSPanel; import com.android.systemui.recents.ScreenPinningRequest; import com.android.systemui.recents.events.EventBus; @@ -176,7 +174,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.TreeSet; import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; @@ -875,6 +872,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow); mQSPanel.setBrightnessMirror(mBrightnessMirrorController); mHeader.setQSPanel(mQSPanel); + QSDetail qsDetail = (QSDetail) mStatusBarWindow.findViewById(R.id.qs_detail); + qsDetail.setHost(qsh); qsh.addCallback(new QSTileHost.Callback() { @Override public void onTilesChanged() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java index fe463855020a..11d99ffe97dc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java @@ -21,14 +21,12 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Rect; -import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.graphics.drawable.RippleDrawable; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; -import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; import com.android.keyguard.KeyguardStatusView; @@ -50,17 +48,12 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements private SettingsButton mSettingsButton; private View mSettingsContainer; private TextView mAlarmStatus; - private View mQsDetailHeader; - private ImageView mQsDetailHeaderProgress; private QSPanel mQsPanel; - private Switch mQsDetailHeaderSwitch; private boolean mExpanded; private boolean mAlarmShowing; - private boolean mShowingDetail; - private boolean mDetailTransitioning; private ViewGroup mExpandedGroup; private ViewGroup mDateTimeGroup; private View mEmergencyOnly; @@ -101,13 +94,6 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements mAlarmStatus = (TextView) findViewById(R.id.alarm_status); mAlarmStatus.setOnClickListener(this); - mQsDetailHeader = findViewById(R.id.qs_detail_header); - mQsDetailHeader.setAlpha(0); - mQsDetailHeaderBack = mQsDetailHeader.findViewById(com.android.internal.R.id.up); - mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title); - mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle); - mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress); - mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch); mMultiUserAvatar = (ImageView) mMultiUserSwitch.findViewById(R.id.multi_user_avatar); @@ -179,7 +165,6 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements private void updateVisibilities() { mAlarmStatus.setVisibility(mAlarmShowing ? View.VISIBLE : View.GONE); - mQsDetailHeader.setVisibility(mExpanded && mShowingDetail ? View.VISIBLE : View.INVISIBLE); mEmergencyOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? View.VISIBLE : View.INVISIBLE); mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility( @@ -188,10 +173,6 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements : View.GONE); } - private boolean hasMultiUsers() { - return false; - } - private void updateListeners() { if (mListening) { mNextAlarmController.addStateChangedCallback(this); @@ -210,7 +191,6 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements mQsPanel = qsPanel; setupHost(qsPanel.getHost()); if (mQsPanel != null) { - mQsPanel.setCallback(mQsPanelCallback); mMultiUserSwitch.setQsPanel(qsPanel); } } @@ -290,121 +270,4 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements } } } - - private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() { - private boolean mScanState; - - @Override - public void onShowingDetail(final QSTile.DetailAdapter detail) { - mDetailTransitioning = true; - post(new Runnable() { - @Override - public void run() { - handleShowingDetail(detail); - } - }); - } - - @Override - public void onToggleStateChanged(final boolean state) { - post(new Runnable() { - @Override - public void run() { - handleToggleStateChanged(state); - } - }); - - } - - @Override - public void onScanStateChanged(final boolean state) { - post(new Runnable() { - @Override - public void run() { - handleScanStateChanged(state); - } - }); - } - - private void handleToggleStateChanged(boolean state) { - mQsDetailHeaderSwitch.setChecked(state); - } - - private void handleScanStateChanged(boolean state) { - if (mScanState == state) return; - mScanState = state; - final Animatable anim = (Animatable) mQsDetailHeaderProgress.getDrawable(); - if (state) { - mQsDetailHeaderProgress.animate().alpha(1f); - anim.start(); - } else { - mQsDetailHeaderProgress.animate().alpha(0f); - anim.stop(); - } - } - - private void handleShowingDetail(final QSTile.DetailAdapter detail) { - final boolean showingDetail = detail != null; - transition(mDateTimeGroup, !showingDetail); - transition(mExpandedGroup, !showingDetail); - if (mAlarmShowing) { - transition(mAlarmStatus, !showingDetail); - } - transition(mQsDetailHeader, showingDetail); - mShowingDetail = showingDetail; - if (showingDetail) { - mQsDetailHeaderTitle.setText(detail.getTitle()); - final Boolean toggleState = detail.getToggleState(); - if (toggleState == null) { - mQsDetailHeaderSwitch.setVisibility(INVISIBLE); - mQsDetailHeader.setClickable(false); - } else { - mQsDetailHeaderSwitch.setVisibility(VISIBLE); - mQsDetailHeaderSwitch.setChecked(toggleState); - mQsDetailHeader.setClickable(true); - mQsDetailHeader.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - boolean checked = !mQsDetailHeaderSwitch.isChecked(); - mQsDetailHeaderSwitch.setChecked(checked); - detail.setToggleState(checked); - } - }); - } - mQsDetailHeaderBack.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - v.getLocationInWindow(mTmpInt2); - mTmpInt2[0] += v.getWidth() / 2; - mTmpInt2[1] += v.getHeight() / 2; - mQsPanel.showDetailAdapter(false, null, mTmpInt2); - } - }); - } else { - mQsDetailHeader.setClickable(false); - } - } - - private void transition(final View v, final boolean in) { - if (in) { - v.bringToFront(); - v.setVisibility(VISIBLE); - } - if (v.hasOverlappingRendering()) { - v.animate().withLayer(); - } - v.animate() - .alpha(in ? 1 : 0) - .withEndAction(new Runnable() { - @Override - public void run() { - if (!in) { - v.setVisibility(INVISIBLE); - } - mDetailTransitioning = false; - } - }) - .start(); - } - }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java index d2f1ca9630e2..3e3b16922f7a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -46,6 +46,7 @@ import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSTile; +import com.android.systemui.qs.QSTile.DetailAdapter; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener; import com.android.systemui.statusbar.policy.NextAlarmController; @@ -742,7 +743,7 @@ public class StatusBarHeaderView extends BaseStatusBarHeader implements View.OnC } @Override - public void onShowingDetail(final QSTile.DetailAdapter detail) { + public void onShowingDetail(final DetailAdapter detail, int x, int y) { mDetailTransitioning = true; post(new Runnable() { @Override |