Merge "Quick prototype of new header"
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
** Copyright 2015, 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.
|
||||
-->
|
||||
|
||||
<!-- Extends RelativeLayout -->
|
||||
<com.android.systemui.statusbar.phone.QuickStatusBarHeader
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:systemui="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/header"
|
||||
android:layout_width="@dimen/notification_panel_width"
|
||||
android:layout_height="@dimen/status_bar_header_height"
|
||||
android:layout_gravity="@integer/notification_panel_layout_gravity"
|
||||
android:baselineAligned="false"
|
||||
android:elevation="4dp"
|
||||
android:background="@drawable/notification_header_bg"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/expanded_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingEnd="12dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.android.systemui.statusbar.AlphaOptimizedButton android:id="@+id/alarm_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:drawablePadding="6dp"
|
||||
android:drawableStart="@drawable/ic_access_alarms_small"
|
||||
android:textColor="#64ffffff"
|
||||
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
|
||||
<com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
|
||||
android:layout_below="@id/clock"
|
||||
systemui:datePattern="EEE"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="20sp"
|
||||
android:paddingTop="16dp"
|
||||
android:layout_marginBottom="@dimen/clock_collapsed_bottom_margin" />
|
||||
|
||||
<include layout="@layout/split_clock_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:id="@+id/clock"
|
||||
/>
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
|
||||
android:id="@+id/settings_button_container"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="@dimen/status_bar_header_height"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<com.android.systemui.statusbar.phone.SettingsButton android:id="@+id/settings_button"
|
||||
style="@android:style/Widget.Material.Button.Borderless"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/ripple_drawable"
|
||||
android:src="@drawable/ic_settings"
|
||||
android:contentDescription="@string/accessibility_desc_settings" />
|
||||
<com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/tuner_icon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingStart="36dp"
|
||||
android:tint="#4DFFFFFF"
|
||||
android:tintMode="src_in"
|
||||
android:visibility="invisible"
|
||||
android:src="@drawable/tuner" />
|
||||
|
||||
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/qs_detail_header"
|
||||
layout="@layout/qs_detail_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
/>
|
||||
|
||||
<com.android.systemui.qs.QuickQSPanel
|
||||
android:id="@+id/quick_qs_panel"
|
||||
android:background="#0000"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<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="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
systemui:hasOverlappingRendering="false"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/header_debug_info"
|
||||
android:visibility="invisible"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:textSize="11dp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#00A040"
|
||||
android:padding="2dp"
|
||||
/>
|
||||
|
||||
</com.android.systemui.statusbar.phone.QuickStatusBarHeader>
|
||||
@@ -98,7 +98,12 @@
|
||||
layout="@layout/keyguard_bottom_area"
|
||||
android:visibility="gone" />
|
||||
|
||||
<include layout="@layout/status_bar_expanded_header" />
|
||||
<ViewStub
|
||||
android:id="@+id/status_bar_header"
|
||||
android:layout_width="@dimen/notification_panel_width"
|
||||
android:layout_height="@dimen/status_bar_header_height"
|
||||
android:layout_marginStart="@dimen/notification_side_padding"
|
||||
android:layout_marginEnd="@dimen/notification_side_padding" />
|
||||
|
||||
<com.android.systemui.statusbar.AlphaOptimizedView
|
||||
android:id="@+id/qs_navbar_scrim"
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
android:layout_width="@dimen/notification_panel_width"
|
||||
android:layout_height="@dimen/status_bar_header_height"
|
||||
android:layout_gravity="@integer/notification_panel_layout_gravity"
|
||||
android:paddingStart="@dimen/notification_side_padding"
|
||||
android:paddingEnd="@dimen/notification_side_padding"
|
||||
android:baselineAligned="false"
|
||||
android:elevation="4dp"
|
||||
android:background="@drawable/notification_header_bg"
|
||||
|
||||
@@ -556,4 +556,7 @@
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
<dimen name="fab_elevation">12dp</dimen>
|
||||
<dimen name="fab_press_translation_z">9dp</dimen>
|
||||
|
||||
<!-- TODO: Remove this -->
|
||||
<dimen name="qs_header_neg_padding">-8dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -1156,7 +1156,7 @@
|
||||
<!-- Option to show brightness bar in quick settings [CHAR LIMIT=60] -->
|
||||
<string name="show_brightness">Show brightness in Quick Settings</string>
|
||||
<!-- Option to use new paging layout in quick settings [CHAR LIMIT=60] -->
|
||||
<string name="qs_paging">Use paging in Quick Settings</string>
|
||||
<string name="qs_paging" translatable="false">Use the new Quick Settings</string>
|
||||
|
||||
<!-- Category in the System UI Tuner settings, where new/experimental
|
||||
settings are -->
|
||||
|
||||
@@ -37,10 +37,6 @@
|
||||
android:key="qs_paged_panel"
|
||||
android:title="@string/qs_paging" />
|
||||
|
||||
<com.android.systemui.tuner.TunerSwitch
|
||||
android:key="qs_allow_customize"
|
||||
android:title="@string/qs_customize" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -34,7 +34,6 @@ 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.systemui.FontSizeUtils;
|
||||
import com.android.systemui.R;
|
||||
@@ -54,8 +53,7 @@ import java.util.Collection;
|
||||
public class QSPanel extends FrameLayout implements Tunable {
|
||||
|
||||
public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
|
||||
public static final String QS_PAGED_PANEL = "qs_paged_panel";
|
||||
public static final String QS_ALLOW_CUSTOMIZE = "qs_allow_customize";
|
||||
public static final String QS_THE_NEW_QS = "qs_paged_panel";
|
||||
|
||||
protected final Context mContext;
|
||||
protected final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>();
|
||||
@@ -135,8 +133,7 @@ public class QSPanel extends FrameLayout implements Tunable {
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
TunerService.get(mContext).addTunable(this,
|
||||
QS_SHOW_BRIGHTNESS, QS_PAGED_PANEL, QS_ALLOW_CUSTOMIZE);
|
||||
TunerService.get(mContext).addTunable(this, QS_SHOW_BRIGHTNESS, QS_THE_NEW_QS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,14 +147,15 @@ public class QSPanel extends FrameLayout implements Tunable {
|
||||
if (QS_SHOW_BRIGHTNESS.equals(key)) {
|
||||
mBrightnessView.setVisibility(newValue == null || Integer.parseInt(newValue) != 0
|
||||
? VISIBLE : GONE);
|
||||
} else if (QS_PAGED_PANEL.equals(key)) {
|
||||
} else if (QS_THE_NEW_QS.equals(key)) {
|
||||
boolean theNewQs = newValue != null && Integer.parseInt(newValue) != 0;
|
||||
if (mTileLayout != null) {
|
||||
for (int i = 0; i < mRecords.size(); i++) {
|
||||
mTileLayout.removeTile(mRecords.get(i));
|
||||
}
|
||||
mQsContainer.removeView((View) mTileLayout);
|
||||
}
|
||||
int layout = newValue != null && Integer.parseInt(newValue) != 0
|
||||
int layout = theNewQs
|
||||
? R.layout.qs_paged_tile_layout : R.layout.qs_tile_layout;
|
||||
mTileLayout =
|
||||
(QSTileLayout) LayoutInflater.from(mContext).inflate(layout, mQsContainer, false);
|
||||
@@ -165,8 +163,7 @@ public class QSPanel extends FrameLayout implements Tunable {
|
||||
for (int i = 0; i < mRecords.size(); i++) {
|
||||
mTileLayout.addTile(mRecords.get(i));
|
||||
}
|
||||
} else if (QS_ALLOW_CUSTOMIZE.equals(key)) {
|
||||
if (newValue != null && Integer.parseInt(newValue) != 0) {
|
||||
if (theNewQs) {
|
||||
mCustomizePanel = (QSCustomizer) LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.qs_customize_panel, null);
|
||||
mCustomizePanel.setHost(mHost);
|
||||
|
||||
@@ -267,7 +267,7 @@ public class QSTileView extends ViewGroup {
|
||||
final int w = MeasureSpec.getSize(widthMeasureSpec);
|
||||
final int h = MeasureSpec.getSize(heightMeasureSpec);
|
||||
final int iconSpec = exactly(mIconSizePx);
|
||||
mIcon.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY), iconSpec);
|
||||
mIcon.measure(MeasureSpec.makeMeasureSpec(w, getIconMeasureMode()), iconSpec);
|
||||
switch (mType) {
|
||||
case QS_TYPE_QUICK:
|
||||
mCircle.measure(
|
||||
@@ -287,6 +287,10 @@ public class QSTileView extends ViewGroup {
|
||||
setMeasuredDimension(w, h);
|
||||
}
|
||||
|
||||
protected int getIconMeasureMode() {
|
||||
return MeasureSpec.EXACTLY;
|
||||
}
|
||||
|
||||
private static int exactly(int size) {
|
||||
return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
|
||||
}
|
||||
|
||||
123
packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
Normal file
123
packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import com.android.systemui.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Version of QSPanel that only shows 4 Quick Tiles in the QS Header.
|
||||
*/
|
||||
public class QuickQSPanel extends QSPanel {
|
||||
|
||||
public QuickQSPanel(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
if (mTileLayout != null) {
|
||||
for (int i = 0; i < mRecords.size(); i++) {
|
||||
mTileLayout.removeTile(mRecords.get(i));
|
||||
}
|
||||
mQsContainer.removeView((View) mTileLayout);
|
||||
}
|
||||
mTileLayout = new HeaderTileLayout(context);
|
||||
mQsContainer.addView((View) mTileLayout, 1 /* Between brightness and footer */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTuningChanged(String key, String newValue) {
|
||||
// No tunings for you.
|
||||
if (key.equals(QS_SHOW_BRIGHTNESS)) {
|
||||
// No Brightness for you.
|
||||
super.onTuningChanged(key, "0");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTiles(Collection<QSTile<?>> tiles) {
|
||||
ArrayList<QSTile<?>> quickTiles = new ArrayList<>();
|
||||
for (QSTile<?> tile : tiles) {
|
||||
if (tile.getTileType() == QSTileView.QS_TYPE_QUICK) {
|
||||
quickTiles.add(tile);
|
||||
}
|
||||
if (quickTiles.size() == 4) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
super.setTiles(quickTiles);
|
||||
}
|
||||
|
||||
private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {
|
||||
|
||||
public HeaderTileLayout(Context context) {
|
||||
super(context);
|
||||
setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
|
||||
int qsCompensation = (int)
|
||||
context.getResources().getDimension(R.dimen.qs_header_neg_padding);
|
||||
setPadding(0, qsCompensation, 0, 0);
|
||||
ImageView downArrow = new ImageView(context);
|
||||
downArrow.setImageResource(R.drawable.ic_expand_more);
|
||||
downArrow.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(
|
||||
android.R.color.white, null)));
|
||||
downArrow.setLayoutParams(generateLayoutParams());
|
||||
downArrow.setPadding(0, -qsCompensation, 0, 0);
|
||||
addView(downArrow);
|
||||
setOrientation(LinearLayout.HORIZONTAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTile(TileRecord tile) {
|
||||
tile.tileView.setLayoutParams(generateLayoutParams());
|
||||
// These shouldn't be normal tiles, but they will be for now so that the circles don't
|
||||
// show up.
|
||||
tile.tileView.setType(QSTileView.QS_TYPE_NORMAL);
|
||||
addView(tile.tileView, getChildCount() - 1 /* Leave icon at end */);
|
||||
}
|
||||
|
||||
private LayoutParams generateLayoutParams() {
|
||||
LayoutParams lp = new LayoutParams(0, LayoutParams.MATCH_PARENT);
|
||||
lp.weight = 1;
|
||||
return lp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTile(TileRecord tile) {
|
||||
removeView(tile.tileView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTileVisibility(TileRecord tile, int visibility) {
|
||||
tile.tileView.setVisibility(visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffsetTop(TileRecord tile) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateResources() {
|
||||
// No resources here.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,11 @@ public final class SignalTileView extends QSTileView {
|
||||
layoutIndicator(mOut);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getIconMeasureMode() {
|
||||
return MeasureSpec.AT_MOST;
|
||||
}
|
||||
|
||||
private void layoutIndicator(View indicator) {
|
||||
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
|
||||
int left, right;
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.util.MathUtils;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
import android.view.ViewStub;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
@@ -43,7 +44,6 @@ import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.keyguard.KeyguardStatusView;
|
||||
import com.android.systemui.DejankUtils;
|
||||
@@ -64,6 +64,7 @@ import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
|
||||
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
|
||||
import com.android.systemui.statusbar.stack.StackStateAnimator;
|
||||
import com.android.systemui.tuner.TunerService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -71,7 +72,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
|
||||
View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
|
||||
KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
|
||||
HeadsUpManager.OnHeadsUpChangedListener {
|
||||
HeadsUpManager.OnHeadsUpChangedListener, TunerService.Tunable {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
@@ -219,20 +220,41 @@ public class NotificationPanelView extends PanelView implements
|
||||
private final Interpolator mTouchResponseInterpolator =
|
||||
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
|
||||
|
||||
private boolean mNewQs;
|
||||
|
||||
public NotificationPanelView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setWillNotDraw(!DEBUG);
|
||||
mFalsingManager = FalsingManager.getInstance(context);
|
||||
TunerService.get(context).addTunable(this, QSPanel.QS_THE_NEW_QS);
|
||||
}
|
||||
|
||||
public void setStatusBar(PhoneStatusBar bar) {
|
||||
mStatusBar = bar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTuningChanged(String key, String newValue) {
|
||||
if (QSPanel.QS_THE_NEW_QS.equals(key)) {
|
||||
boolean b = newValue != null && Integer.parseInt(newValue) != 0;
|
||||
if (mNewQs != b) {
|
||||
if (mHeader != null) {
|
||||
// We are too late, no good way to re-initialize yet, just die and come back up.
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
} else {
|
||||
mNewQs = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mHeader = (BaseStatusBarHeader) findViewById(R.id.header);
|
||||
ViewStub stub = (ViewStub) findViewById(R.id.status_bar_header);
|
||||
stub.setLayoutResource(mNewQs
|
||||
? R.layout.quick_status_bar_expanded_header : R.layout.status_bar_expanded_header);
|
||||
mHeader = (BaseStatusBarHeader) stub.inflate();
|
||||
mHeader.setOnClickListener(this);
|
||||
mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
|
||||
mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
|
||||
|
||||
@@ -868,13 +868,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
(SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
|
||||
mNetworkController.addSignalCallback(signalCluster);
|
||||
mNetworkController.addSignalCallback(signalClusterKeyguard);
|
||||
mNetworkController.addSignalCallback(signalClusterQs);
|
||||
signalCluster.setSecurityController(mSecurityController);
|
||||
signalCluster.setNetworkController(mNetworkController);
|
||||
signalClusterKeyguard.setSecurityController(mSecurityController);
|
||||
signalClusterKeyguard.setNetworkController(mNetworkController);
|
||||
signalClusterQs.setSecurityController(mSecurityController);
|
||||
signalClusterQs.setNetworkController(mNetworkController);
|
||||
if (signalClusterQs != null) {
|
||||
mNetworkController.addSignalCallback(signalClusterQs);
|
||||
signalClusterQs.setSecurityController(mSecurityController);
|
||||
signalClusterQs.setNetworkController(mNetworkController);
|
||||
}
|
||||
final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
|
||||
if (isAPhone) {
|
||||
mNetworkController.addEmergencyListener(mHeader);
|
||||
|
||||
@@ -97,6 +97,10 @@ public class QSTileHost implements QSTile.Host, Tunable {
|
||||
TunerService.get(mContext).addTunable(this, TILES_SETTING);
|
||||
}
|
||||
|
||||
PhoneStatusBar getPhoneStatusBar() {
|
||||
return mStatusBar;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
TunerService.get(mContext).removeTunable(this);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.statusbar.phone;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Animatable;
|
||||
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.systemui.R;
|
||||
import com.android.systemui.qs.QSPanel;
|
||||
import com.android.systemui.qs.QSTile;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
import com.android.systemui.statusbar.policy.NextAlarmController;
|
||||
import com.android.systemui.statusbar.policy.UserInfoController;
|
||||
import com.android.systemui.tuner.TunerService;
|
||||
|
||||
public class QuickStatusBarHeader extends BaseStatusBarHeader implements
|
||||
NextAlarmController.NextAlarmChangeCallback, View.OnClickListener {
|
||||
|
||||
private ActivityStarter mActivityStarter;
|
||||
private NextAlarmController mNextAlarmController;
|
||||
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 TextView mQsDetailHeaderTitle;
|
||||
private boolean mListening;
|
||||
private AlarmManager.AlarmClockInfo mNextAlarm;
|
||||
|
||||
private QSPanel mHeaderQsPanel;
|
||||
|
||||
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mExpandedGroup = (ViewGroup) findViewById(R.id.expanded_group);
|
||||
|
||||
mHeaderQsPanel = (QSPanel) findViewById(R.id.quick_qs_panel);
|
||||
|
||||
mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
|
||||
mSettingsContainer = findViewById(R.id.settings_button_container);
|
||||
mSettingsButton.setOnClickListener(this);
|
||||
|
||||
mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
|
||||
mAlarmStatus.setOnClickListener(this);
|
||||
|
||||
mQsDetailHeader = findViewById(R.id.qs_detail_header);
|
||||
mQsDetailHeader.setAlpha(0);
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCollapsedHeight() {
|
||||
return getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getExpandedHeight() {
|
||||
return getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpanded(boolean expanded) {
|
||||
mExpanded = expanded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
|
||||
mNextAlarm = nextAlarm;
|
||||
if (nextAlarm != null) {
|
||||
// TODO:...
|
||||
// mAlarmStatus.setText(KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm));
|
||||
}
|
||||
mAlarmShowing = nextAlarm != null;
|
||||
updateEverything();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpansion(float headerExpansionFraction) {
|
||||
float offset = getHeight() * headerExpansionFraction;
|
||||
mExpandedGroup.setTranslationY(offset - getHeight());
|
||||
mHeaderQsPanel.setTranslationY(offset);
|
||||
}
|
||||
|
||||
public void setListening(boolean listening) {
|
||||
if (listening == mListening) {
|
||||
return;
|
||||
}
|
||||
mHeaderQsPanel.setListening(listening);
|
||||
mListening = listening;
|
||||
updateListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEverything() {
|
||||
updateVisibilities();
|
||||
}
|
||||
|
||||
private void updateVisibilities() {
|
||||
mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.GONE);
|
||||
mQsDetailHeader.setVisibility(mExpanded && mShowingDetail ? View.VISIBLE : View.INVISIBLE);
|
||||
mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
|
||||
TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
|
||||
private void updateListeners() {
|
||||
if (mListening) {
|
||||
mNextAlarmController.addStateChangedCallback(this);
|
||||
} else {
|
||||
mNextAlarmController.removeStateChangedCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActivityStarter(ActivityStarter activityStarter) {
|
||||
mActivityStarter = activityStarter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQSPanel(final QSPanel qsPanel) {
|
||||
mQsPanel = qsPanel;
|
||||
setupHost(qsPanel.getHost());
|
||||
if (mQsPanel != null) {
|
||||
mQsPanel.setCallback(mQsPanelCallback);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupHost(QSTileHost host) {
|
||||
final QSTileHost myHost = new QSTileHost(host.getContext(), host.getPhoneStatusBar(),
|
||||
host.getBluetoothController(), host.getLocationController(),
|
||||
host.getRotationLockController(), host.getNetworkController(),
|
||||
host.getZenModeController(), host.getHotspotController(),
|
||||
host.getCastController(), host.getFlashlightController(),
|
||||
host.getUserSwitcherController(), host.getUserInfoController(),
|
||||
host.getKeyguardMonitor(), host.getSecurityController(),
|
||||
host.getBatteryController());
|
||||
mHeaderQsPanel.setHost(myHost);
|
||||
mHeaderQsPanel.setTiles(myHost.getTiles());
|
||||
myHost.setCallback(new QSTile.Host.Callback() {
|
||||
@Override
|
||||
public void onTilesChanged() {
|
||||
mHeaderQsPanel.setTiles(myHost.getTiles());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == mSettingsButton) {
|
||||
if (mSettingsButton.isTunerClick()) {
|
||||
if (TunerService.isTunerEnabled(mContext)) {
|
||||
TunerService.showResetRequest(mContext, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Relaunch settings so that the tuner disappears.
|
||||
startSettingsActivity();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show();
|
||||
TunerService.setTunerEnabled(mContext, true);
|
||||
}
|
||||
}
|
||||
startSettingsActivity();
|
||||
} else if (v == mAlarmStatus && mNextAlarm != null) {
|
||||
PendingIntent showIntent = mNextAlarm.getShowIntent();
|
||||
if (showIntent != null && showIntent.isActivity()) {
|
||||
mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startSettingsActivity() {
|
||||
mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
|
||||
true /* dismissShade */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextAlarmController(NextAlarmController nextAlarmController) {
|
||||
mNextAlarmController = nextAlarmController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatteryController(BatteryController batteryController) {
|
||||
// Don't care
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserInfoController(UserInfoController userInfoController) {
|
||||
// Don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmergencyCallsOnly(boolean emergencyOnly) {
|
||||
// Don't care.
|
||||
}
|
||||
|
||||
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(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);
|
||||
}
|
||||
});
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -237,7 +237,7 @@ public class StatusBarHeaderView extends BaseStatusBarHeader implements View.OnC
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
TunerService.get(mContext).addTunable(this, QSPanel.QS_PAGED_PANEL);
|
||||
TunerService.get(mContext).addTunable(this, QSPanel.QS_THE_NEW_QS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -248,7 +248,7 @@ public class StatusBarHeaderView extends BaseStatusBarHeader implements View.OnC
|
||||
|
||||
@Override
|
||||
public void onTuningChanged(String key, String newValue) {
|
||||
if (QSPanel.QS_PAGED_PANEL.equals(key)) {
|
||||
if (QSPanel.QS_THE_NEW_QS.equals(key)) {
|
||||
mAllowExpand = newValue == null || Integer.parseInt(newValue) == 0;
|
||||
if (!mAllowExpand) {
|
||||
setExpanded(false);
|
||||
|
||||
@@ -101,7 +101,7 @@ public class TunerFragment extends PreferenceFragment {
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
TunerService.get(getContext()).addTunable(mQsPaging, QSPanel.QS_PAGED_PANEL);
|
||||
TunerService.get(getContext()).addTunable(mQsPaging, QSPanel.QS_THE_NEW_QS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user