Merge "Merge changes I3b8babc2,I56ea3eee into rvc-dev am: 3a8b73a881 am: b9ed45c308 am: 50db05188b" into rvc-qpr-dev-plus-aosp
This commit is contained in:
committed by
Android (Google) Code Review
commit
f04d153efc
@@ -34,7 +34,7 @@ public interface QS extends FragmentBase {
|
|||||||
|
|
||||||
String ACTION = "com.android.systemui.action.PLUGIN_QS";
|
String ACTION = "com.android.systemui.action.PLUGIN_QS";
|
||||||
|
|
||||||
int VERSION = 7;
|
int VERSION = 8;
|
||||||
|
|
||||||
String TAG = "QS";
|
String TAG = "QS";
|
||||||
|
|
||||||
@@ -67,15 +67,12 @@ public interface QS extends FragmentBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We need this to handle nested scrolling for QS..
|
* Should touches from the notification panel be disallowed?
|
||||||
* Normally we would do this with requestDisallowInterceptTouchEvent, but when both the
|
* The notification panel might grab any touches rom QS at any time to collapse the shade.
|
||||||
* scroll containers are using the same touch slop, they try to start scrolling at the
|
* We should disallow that in case we are showing the detail panel.
|
||||||
* same time and NotificationPanelView wins, this lets QS win.
|
|
||||||
*
|
|
||||||
* TODO: Do this using NestedScroll capabilities.
|
|
||||||
*/
|
*/
|
||||||
default boolean onInterceptTouchEvent(MotionEvent event) {
|
default boolean disallowPanelTouches() {
|
||||||
return isCustomizing();
|
return isShowingDetail();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ProvidesInterface(version = HeightListener.VERSION)
|
@ProvidesInterface(version = HeightListener.VERSION)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
android:background="@drawable/qs_detail_background"
|
android:background="@drawable/qs_detail_background"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:layout_marginTop="@*android:dimen/quick_qs_offset_height"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
android:elevation="4dp"
|
android:elevation="4dp"
|
||||||
@@ -44,7 +45,7 @@
|
|||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<com.android.systemui.qs.NonInterceptingScrollView
|
<ScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
@@ -54,7 +55,7 @@
|
|||||||
android:id="@android:id/content"
|
android:id="@android:id/content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"/>
|
android:layout_height="match_parent"/>
|
||||||
</com.android.systemui.qs.NonInterceptingScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<include layout="@layout/qs_detail_buttons" />
|
<include layout="@layout/qs_detail_buttons" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2017 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.
|
|
||||||
-->
|
|
||||||
<View xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:alpha=".12"
|
|
||||||
android:background="?android:attr/colorForeground" />
|
|
||||||
@@ -61,7 +61,10 @@
|
|||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
android:textAppearance="@style/TextAppearance.QS.Status"
|
android:textAppearance="@style/TextAppearance.QS.Status"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
</com.android.keyguard.AlphaOptimizedLinearLayout>
|
</com.android.keyguard.AlphaOptimizedLinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,5 @@
|
|||||||
android:id="@+id/tile_page"
|
android:id="@+id/tile_page"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingStart="@dimen/notification_side_paddings"
|
|
||||||
android:paddingEnd="@dimen/notification_side_paddings"
|
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:clipToPadding="false" />
|
android:clipToPadding="false" />
|
||||||
|
|||||||
@@ -48,18 +48,22 @@
|
|||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:background="@drawable/qs_bg_gradient" />
|
android:background="@drawable/qs_bg_gradient" />
|
||||||
|
|
||||||
|
<com.android.systemui.qs.NonInterceptingScrollView
|
||||||
<com.android.systemui.qs.QSPanel
|
android:id="@+id/expanded_qs_scroll_view"
|
||||||
android:id="@+id/quick_settings_panel"
|
|
||||||
android:layout_marginTop="@*android:dimen/quick_qs_offset_height"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:elevation="4dp"
|
android:elevation="4dp"
|
||||||
android:background="@android:color/transparent"
|
android:layout_weight="1">
|
||||||
android:focusable="true"
|
<com.android.systemui.qs.QSPanel
|
||||||
android:accessibilityTraversalBefore="@android:id/edit">
|
android:id="@+id/quick_settings_panel"
|
||||||
<include layout="@layout/qs_footer_impl" />
|
android:layout_width="match_parent"
|
||||||
</com.android.systemui.qs.QSPanel>
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:focusable="true"
|
||||||
|
android:accessibilityTraversalBefore="@android:id/edit">
|
||||||
|
<include layout="@layout/qs_footer_impl" />
|
||||||
|
</com.android.systemui.qs.QSPanel>
|
||||||
|
</com.android.systemui.qs.NonInterceptingScrollView>
|
||||||
|
|
||||||
<include layout="@layout/quick_status_bar_expanded_header" />
|
<include layout="@layout/quick_status_bar_expanded_header" />
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.android.systemui.util.NeverExactlyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:paddingBottom="@dimen/qs_tile_padding_top"
|
android:paddingBottom="@dimen/qs_tile_padding_top"
|
||||||
@@ -23,23 +23,28 @@
|
|||||||
android:paddingStart="@dimen/qs_footer_padding_start"
|
android:paddingStart="@dimen/qs_footer_padding_start"
|
||||||
android:paddingEnd="@dimen/qs_footer_padding_end"
|
android:paddingEnd="@dimen/qs_footer_padding_end"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
android:layout_gravity="center_vertical|center_horizontal"
|
||||||
android:background="@android:color/transparent">
|
android:background="@android:color/transparent">
|
||||||
|
|
||||||
<TextView
|
<com.android.systemui.util.AutoMarqueeTextView
|
||||||
android:id="@+id/footer_text"
|
android:id="@+id/footer_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:marqueeRepeatLimit="marquee_forever"
|
||||||
android:textAppearance="@style/TextAppearance.QS.TileLabel"
|
android:textAppearance="@style/TextAppearance.QS.TileLabel"
|
||||||
style="@style/qs_security_footer"/>
|
android:textColor="?android:attr/textColorPrimary"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/footer_icon"
|
android:id="@+id/footer_icon"
|
||||||
android:layout_width="@dimen/qs_footer_icon_size"
|
android:layout_width="@dimen/qs_footer_icon_size"
|
||||||
android:layout_height="@dimen/qs_footer_icon_size"
|
android:layout_height="@dimen/qs_footer_icon_size"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_info_outline"
|
android:src="@drawable/ic_info_outline"
|
||||||
style="@style/qs_security_footer"/>
|
android:tint="?android:attr/textColorPrimary" />
|
||||||
|
|
||||||
</LinearLayout>
|
</com.android.systemui.util.NeverExactlyLinearLayout>
|
||||||
|
|||||||
@@ -20,11 +20,12 @@
|
|||||||
android:layout_height="@dimen/qs_header_tooltip_height"
|
android:layout_height="@dimen/qs_header_tooltip_height"
|
||||||
android:layout_below="@id/quick_status_bar_system_icons"
|
android:layout_below="@id/quick_status_bar_system_icons"
|
||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
android:theme="@style/QSHeaderTheme">
|
android:theme="@style/QSHeaderTheme"
|
||||||
|
android:forceHasOverlappingRendering="false">
|
||||||
|
|
||||||
<com.android.systemui.qs.QSHeaderInfoLayout
|
<com.android.systemui.qs.QSHeaderInfoLayout
|
||||||
android:id="@+id/status_container"
|
android:id="@+id/status_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@
|
|||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingTop="0dp"
|
android:paddingTop="0dp"
|
||||||
android:paddingEnd="0dp"
|
android:paddingEnd="0dp"
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:paddingStart="0dp"
|
android:paddingStart="0dp"
|
||||||
android:elevation="4dp" >
|
android:elevation="4dp" >
|
||||||
|
|
||||||
@@ -52,6 +51,7 @@
|
|||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
android:importantForAccessibility="yes" />
|
android:importantForAccessibility="yes" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
<dimen name="battery_detail_graph_space_bottom">9dp</dimen>
|
<dimen name="battery_detail_graph_space_bottom">9dp</dimen>
|
||||||
|
|
||||||
<integer name="quick_settings_num_columns">4</integer>
|
<integer name="quick_settings_num_columns">4</integer>
|
||||||
<bool name="quick_settings_wide">true</bool>
|
|
||||||
<dimen name="qs_detail_margin_top">0dp</dimen>
|
<dimen name="qs_detail_margin_top">0dp</dimen>
|
||||||
|
|
||||||
<dimen name="volume_tool_tip_right_margin">136dp</dimen>
|
<dimen name="volume_tool_tip_right_margin">136dp</dimen>
|
||||||
|
|||||||
@@ -29,9 +29,4 @@
|
|||||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="qs_security_footer" parent="@style/qs_theme">
|
|
||||||
<item name="android:textColor">#B3FFFFFF</item> <!-- 70% white -->
|
|
||||||
<item name="android:tint">#FFFFFFFF</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -15,8 +15,5 @@
|
|||||||
~ limitations under the License
|
~ limitations under the License
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Whether QuickSettings is in a phone landscape -->
|
|
||||||
<bool name="quick_settings_wide">false</bool>
|
|
||||||
|
|
||||||
<integer name="quick_settings_num_columns">3</integer>
|
<integer name="quick_settings_num_columns">3</integer>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
21
packages/SystemUI/res/values-sw600dp-port/dimens.xml
Normal file
21
packages/SystemUI/res/values-sw600dp-port/dimens.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2020 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.
|
||||||
|
-->
|
||||||
|
<resources>
|
||||||
|
<!-- Size of the panel of large phones on portrait. This shouldn't fill, but have some padding on the side -->
|
||||||
|
<dimen name="notification_panel_width">416dp</dimen>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -16,8 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Standard notification width + gravity -->
|
|
||||||
<dimen name="notification_panel_width">416dp</dimen>
|
|
||||||
|
|
||||||
<!-- Diameter of outer shape drawable shown in navbar search-->
|
<!-- Diameter of outer shape drawable shown in navbar search-->
|
||||||
<dimen name="navbar_search_outerring_diameter">430dip</dimen>
|
<dimen name="navbar_search_outerring_diameter">430dip</dimen>
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
* Copyright (c) 2012, 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.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<!-- Standard notification width + gravity for tablet large screen device -->
|
|
||||||
<dimen name="notification_panel_width">544dp</dimen>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
|
|
||||||
@@ -20,9 +20,5 @@
|
|||||||
<!-- These resources are around just to allow their values to be customized
|
<!-- These resources are around just to allow their values to be customized
|
||||||
for different hardware and product builds. -->
|
for different hardware and product builds. -->
|
||||||
<resources>
|
<resources>
|
||||||
|
<integer name="quick_settings_num_columns">6</integer>
|
||||||
<!-- Whether QuickSettings is in a phone landscape -->
|
|
||||||
<bool name="quick_settings_wide">true</bool>
|
|
||||||
|
|
||||||
<integer name="quick_settings_num_columns">4</integer>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<!-- Standard notification width + gravity -->
|
|
||||||
<dimen name="notification_panel_width">544dp</dimen>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
21
packages/SystemUI/res/values-w650dp-land/dimens.xml
Normal file
21
packages/SystemUI/res/values-w650dp-land/dimens.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2020 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.
|
||||||
|
-->
|
||||||
|
<resources>
|
||||||
|
<!-- Standard notification width + gravity -->
|
||||||
|
<dimen name="notification_panel_width">644dp</dimen>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -95,9 +95,6 @@
|
|||||||
<!-- The maximum number of tiles in the QuickQSPanel -->
|
<!-- The maximum number of tiles in the QuickQSPanel -->
|
||||||
<integer name="quick_qs_panel_max_columns">6</integer>
|
<integer name="quick_qs_panel_max_columns">6</integer>
|
||||||
|
|
||||||
<!-- Whether QuickSettings is in a phone landscape -->
|
|
||||||
<bool name="quick_settings_wide">false</bool>
|
|
||||||
|
|
||||||
<!-- The number of columns in the QuickSettings -->
|
<!-- The number of columns in the QuickSettings -->
|
||||||
<integer name="quick_settings_num_columns">3</integer>
|
<integer name="quick_settings_num_columns">3</integer>
|
||||||
|
|
||||||
|
|||||||
@@ -1075,8 +1075,7 @@
|
|||||||
<dimen name="edge_margin">8dp</dimen>
|
<dimen name="edge_margin">8dp</dimen>
|
||||||
|
|
||||||
<!-- The absolute side margins of quick settings -->
|
<!-- The absolute side margins of quick settings -->
|
||||||
<dimen name="quick_settings_expanded_bottom_margin">16dp</dimen>
|
<dimen name="quick_settings_bottom_margin_media">16dp</dimen>
|
||||||
<dimen name="quick_settings_media_extra_bottom_margin">6dp</dimen>
|
|
||||||
<dimen name="rounded_corner_content_padding">0dp</dimen>
|
<dimen name="rounded_corner_content_padding">0dp</dimen>
|
||||||
<dimen name="nav_content_padding">0dp</dimen>
|
<dimen name="nav_content_padding">0dp</dimen>
|
||||||
<dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
|
<dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
|
||||||
@@ -1264,8 +1263,8 @@
|
|||||||
<dimen name="qs_media_panel_outer_padding">16dp</dimen>
|
<dimen name="qs_media_panel_outer_padding">16dp</dimen>
|
||||||
<dimen name="qs_media_album_size">52dp</dimen>
|
<dimen name="qs_media_album_size">52dp</dimen>
|
||||||
<dimen name="qs_seamless_icon_size">20dp</dimen>
|
<dimen name="qs_seamless_icon_size">20dp</dimen>
|
||||||
<dimen name="qqs_media_spacing">8dp</dimen>
|
<dimen name="qqs_media_spacing">16dp</dimen>
|
||||||
<dimen name="qqs_horizonal_tile_padding_bottom">8dp</dimen>
|
<dimen name="qs_footer_horizontal_margin">22dp</dimen>
|
||||||
|
|
||||||
<dimen name="magnification_border_size">5dp</dimen>
|
<dimen name="magnification_border_size">5dp</dimen>
|
||||||
<dimen name="magnification_frame_move_short">5dp</dimen>
|
<dimen name="magnification_frame_move_short">5dp</dimen>
|
||||||
|
|||||||
@@ -387,11 +387,6 @@
|
|||||||
<item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
|
<item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="qs_security_footer" parent="@style/qs_theme">
|
|
||||||
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
|
||||||
<item name="android:tint">?android:attr/textColorSecondary</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
|
<style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
|
||||||
<item name="android:colorAccent">@color/remote_input_accent</item>
|
<item name="android:colorAccent">@color/remote_input_accent</item>
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -480,7 +480,17 @@ class MediaHierarchyManager @Inject constructor(
|
|||||||
if (inOverlay) {
|
if (inOverlay) {
|
||||||
rootOverlay!!.add(mediaFrame)
|
rootOverlay!!.add(mediaFrame)
|
||||||
} else {
|
} else {
|
||||||
|
// When adding back to the host, let's make sure to reset the bounds.
|
||||||
|
// Usually adding the view will trigger a layout that does this automatically,
|
||||||
|
// but we sometimes suppress this.
|
||||||
targetHost.addView(mediaFrame)
|
targetHost.addView(mediaFrame)
|
||||||
|
val left = targetHost.paddingLeft
|
||||||
|
val top = targetHost.paddingTop
|
||||||
|
mediaFrame.setLeftTopRightBottom(
|
||||||
|
left,
|
||||||
|
top,
|
||||||
|
left + currentBounds.width(),
|
||||||
|
top + currentBounds.height())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,12 +139,7 @@ class DoubleLineTileLayout(
|
|||||||
}
|
}
|
||||||
tilesToShow = actualColumns * NUM_LINES
|
tilesToShow = actualColumns * NUM_LINES
|
||||||
|
|
||||||
val interTileSpace = if (actualColumns <= 2) {
|
val spacePerTile = availableWidth / actualColumns
|
||||||
// Extra "column" of padding to be distributed on each end
|
|
||||||
(availableWidth - actualColumns * smallTileSize) / actualColumns
|
|
||||||
} else {
|
|
||||||
(availableWidth - actualColumns * smallTileSize) / (actualColumns - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (index in 0 until mRecords.size) {
|
for (index in 0 until mRecords.size) {
|
||||||
val tileView = mRecords[index].tileView
|
val tileView = mRecords[index].tileView
|
||||||
@@ -154,15 +149,16 @@ class DoubleLineTileLayout(
|
|||||||
tileView.visibility = View.VISIBLE
|
tileView.visibility = View.VISIBLE
|
||||||
if (index > 0) tileView.updateAccessibilityOrder(mRecords[index - 1].tileView)
|
if (index > 0) tileView.updateAccessibilityOrder(mRecords[index - 1].tileView)
|
||||||
val column = index % actualColumns
|
val column = index % actualColumns
|
||||||
val left = getLeftForColumn(column, interTileSpace, actualColumns <= 2)
|
val left = getLeftForColumn(column, spacePerTile)
|
||||||
val top = if (index < actualColumns) 0 else getTopBottomRow()
|
val top = if (index < actualColumns) 0 else getTopBottomRow()
|
||||||
tileView.layout(left, top, left + smallTileSize, top + smallTileSize)
|
tileView.layout(left, top, left + smallTileSize, top + smallTileSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLeftForColumn(column: Int, interSpace: Int, sideMargin: Boolean): Int {
|
private fun getLeftForColumn(column: Int, spacePerTile: Int): Int {
|
||||||
return (if (sideMargin) interSpace / 2 else 0) + column * (smallTileSize + interSpace)
|
// Distribute the space evenly among all tiles.
|
||||||
|
return (column * spacePerTile + spacePerTile / 2.0f - smallTileSize / 2.0f).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTopBottomRow() = smallTileSize + cellMarginVertical
|
private fun getTopBottomRow() = smallTileSize + cellMarginVertical
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ package com.android.systemui.qs;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
import android.view.ViewParent;
|
||||||
import android.widget.ScrollView;
|
import android.widget.ScrollView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,8 +27,12 @@ import android.widget.ScrollView;
|
|||||||
*/
|
*/
|
||||||
public class NonInterceptingScrollView extends ScrollView {
|
public class NonInterceptingScrollView extends ScrollView {
|
||||||
|
|
||||||
|
private final int mTouchSlop;
|
||||||
|
private float mDownY;
|
||||||
|
|
||||||
public NonInterceptingScrollView(Context context, AttributeSet attrs) {
|
public NonInterceptingScrollView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -34,10 +41,52 @@ public class NonInterceptingScrollView extends ScrollView {
|
|||||||
switch (action) {
|
switch (action) {
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
if (canScrollVertically(1)) {
|
if (canScrollVertically(1)) {
|
||||||
requestDisallowInterceptTouchEvent(true);
|
// If we can scroll down, make sure we're not intercepted by the parent
|
||||||
|
final ViewParent parent = getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
parent.requestDisallowInterceptTouchEvent(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return super.onTouchEvent(ev);
|
return super.onTouchEvent(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||||
|
// If there's a touch on this view and we can scroll down, we don't want to be intercepted
|
||||||
|
int action = ev.getActionMasked();
|
||||||
|
switch (action) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
// If we can scroll down, make sure non of our parents intercepts us.
|
||||||
|
if (canScrollVertically(1)) {
|
||||||
|
final ViewParent parent = getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
parent.requestDisallowInterceptTouchEvent(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mDownY = ev.getY();
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_MOVE: {
|
||||||
|
final int y = (int) ev.getY();
|
||||||
|
final float yDiff = y - mDownY;
|
||||||
|
if (yDiff < -mTouchSlop && !canScrollVertically(1)) {
|
||||||
|
// Don't intercept touches that are overscrolling.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onInterceptTouchEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getScrollRange() {
|
||||||
|
int scrollRange = 0;
|
||||||
|
if (getChildCount() > 0) {
|
||||||
|
View child = getChildAt(0);
|
||||||
|
scrollRange = Math.max(0,
|
||||||
|
child.getHeight() - (getHeight() - mPaddingBottom - mPaddingTop));
|
||||||
|
}
|
||||||
|
return scrollRange;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
|||||||
private int mHorizontalClipBound;
|
private int mHorizontalClipBound;
|
||||||
private final Rect mClippingRect;
|
private final Rect mClippingRect;
|
||||||
private final UiEventLogger mUiEventLogger = QSEvents.INSTANCE.getQsUiEventsLogger();
|
private final UiEventLogger mUiEventLogger = QSEvents.INSTANCE.getQsUiEventsLogger();
|
||||||
|
private int mExcessHeight;
|
||||||
|
private int mLastExcessHeight;
|
||||||
|
private int mMinRows = 1;
|
||||||
|
private int mMaxColumns = TileLayout.NO_MAX_COLUMNS;
|
||||||
|
|
||||||
public PagedTileLayout(Context context, AttributeSet attrs) {
|
public PagedTileLayout(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
@@ -195,11 +199,18 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
|||||||
@Override
|
@Override
|
||||||
protected void onFinishInflate() {
|
protected void onFinishInflate() {
|
||||||
super.onFinishInflate();
|
super.onFinishInflate();
|
||||||
mPages.add((TilePage) LayoutInflater.from(getContext())
|
mPages.add(createTilePage());
|
||||||
.inflate(R.layout.qs_paged_page, this, false));
|
|
||||||
mAdapter.notifyDataSetChanged();
|
mAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TilePage createTilePage() {
|
||||||
|
TilePage page = (TilePage) LayoutInflater.from(getContext())
|
||||||
|
.inflate(R.layout.qs_paged_page, this, false);
|
||||||
|
page.setMinRows(mMinRows);
|
||||||
|
page.setMaxColumns(mMaxColumns);
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
public void setPageIndicator(PageIndicator indicator) {
|
public void setPageIndicator(PageIndicator indicator) {
|
||||||
mPageIndicator = indicator;
|
mPageIndicator = indicator;
|
||||||
mPageIndicator.setNumPages(mPages.size());
|
mPageIndicator.setNumPages(mPages.size());
|
||||||
@@ -298,8 +309,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
|||||||
}
|
}
|
||||||
while (mPages.size() < numPages) {
|
while (mPages.size() < numPages) {
|
||||||
if (DEBUG) Log.d(TAG, "Adding page");
|
if (DEBUG) Log.d(TAG, "Adding page");
|
||||||
mPages.add((TilePage) LayoutInflater.from(getContext())
|
mPages.add(createTilePage());
|
||||||
.inflate(R.layout.qs_paged_page, this, false));
|
|
||||||
}
|
}
|
||||||
while (mPages.size() > numPages) {
|
while (mPages.size() > numPages) {
|
||||||
if (DEBUG) Log.d(TAG, "Removing page");
|
if (DEBUG) Log.d(TAG, "Removing page");
|
||||||
@@ -341,18 +351,55 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
|||||||
setClipBounds(mClippingRect);
|
setClipBounds(mClippingRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setMinRows(int minRows) {
|
||||||
|
mMinRows = minRows;
|
||||||
|
boolean changed = false;
|
||||||
|
for (int i = 0; i < mPages.size(); i++) {
|
||||||
|
if (mPages.get(i).setMinRows(minRows)) {
|
||||||
|
changed = true;
|
||||||
|
mDistributeTiles = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setMaxColumns(int maxColumns) {
|
||||||
|
mMaxColumns = maxColumns;
|
||||||
|
boolean changed = false;
|
||||||
|
for (int i = 0; i < mPages.size(); i++) {
|
||||||
|
if (mPages.get(i).setMaxColumns(maxColumns)) {
|
||||||
|
changed = true;
|
||||||
|
mDistributeTiles = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the amount of excess space that we gave this view compared to the actual available
|
||||||
|
* height. This is because this view is in a scrollview.
|
||||||
|
*/
|
||||||
|
public void setExcessHeight(int excessHeight) {
|
||||||
|
mExcessHeight = excessHeight;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
|
||||||
final int nTiles = mTiles.size();
|
final int nTiles = mTiles.size();
|
||||||
// If we have no reason to recalculate the number of rows, skip this step. In particular,
|
// If we have no reason to recalculate the number of rows, skip this step. In particular,
|
||||||
// if the height passed by its parent is the same as the last time, we try not to remeasure.
|
// if the height passed by its parent is the same as the last time, we try not to remeasure.
|
||||||
if (mDistributeTiles || mLastMaxHeight != MeasureSpec.getSize(heightMeasureSpec)) {
|
if (mDistributeTiles || mLastMaxHeight != MeasureSpec.getSize(heightMeasureSpec)
|
||||||
|
|| mLastExcessHeight != mExcessHeight) {
|
||||||
|
|
||||||
mLastMaxHeight = MeasureSpec.getSize(heightMeasureSpec);
|
mLastMaxHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
mLastExcessHeight = mExcessHeight;
|
||||||
// Only change the pages if the number of rows or columns (from updateResources) has
|
// Only change the pages if the number of rows or columns (from updateResources) has
|
||||||
// changed or the tiles have changed
|
// changed or the tiles have changed
|
||||||
if (mPages.get(0).updateMaxRows(heightMeasureSpec, nTiles) || mDistributeTiles) {
|
int availableHeight = mLastMaxHeight - mExcessHeight;
|
||||||
|
if (mPages.get(0).updateMaxRows(availableHeight, nTiles) || mDistributeTiles) {
|
||||||
mDistributeTiles = false;
|
mDistributeTiles = false;
|
||||||
distributeTiles();
|
distributeTiles();
|
||||||
}
|
}
|
||||||
@@ -485,14 +532,6 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
|||||||
// up.
|
// up.
|
||||||
return Math.max(mColumns * mRows, 1);
|
return Math.max(mColumns * mRows, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean updateResources() {
|
|
||||||
final int sidePadding = getContext().getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.notification_side_paddings);
|
|
||||||
setPadding(sidePadding, 0, sidePadding, 0);
|
|
||||||
return super.updateResources();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final PagerAdapter mAdapter = new PagerAdapter() {
|
private final PagerAdapter mAdapter = new PagerAdapter() {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import android.util.Log;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnAttachStateChangeListener;
|
import android.view.View.OnAttachStateChangeListener;
|
||||||
import android.view.View.OnLayoutChangeListener;
|
import android.view.View.OnLayoutChangeListener;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
|
||||||
import com.android.systemui.Dependency;
|
import com.android.systemui.Dependency;
|
||||||
import com.android.systemui.plugins.qs.QS;
|
import com.android.systemui.plugins.qs.QS;
|
||||||
@@ -30,7 +31,6 @@ import com.android.systemui.qs.TouchAnimator.Builder;
|
|||||||
import com.android.systemui.qs.TouchAnimator.Listener;
|
import com.android.systemui.qs.TouchAnimator.Listener;
|
||||||
import com.android.systemui.tuner.TunerService;
|
import com.android.systemui.tuner.TunerService;
|
||||||
import com.android.systemui.tuner.TunerService.Tunable;
|
import com.android.systemui.tuner.TunerService.Tunable;
|
||||||
import com.android.systemui.util.Utils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -66,6 +66,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
|||||||
private TouchAnimator mNonfirstPageAnimator;
|
private TouchAnimator mNonfirstPageAnimator;
|
||||||
private TouchAnimator mNonfirstPageDelayedAnimator;
|
private TouchAnimator mNonfirstPageDelayedAnimator;
|
||||||
private TouchAnimator mBrightnessAnimator;
|
private TouchAnimator mBrightnessAnimator;
|
||||||
|
private boolean mNeedsAnimatorUpdate = false;
|
||||||
|
|
||||||
private boolean mOnKeyguard;
|
private boolean mOnKeyguard;
|
||||||
|
|
||||||
@@ -98,6 +99,12 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
|||||||
updateAnimators();
|
updateAnimators();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onQsScrollingChanged() {
|
||||||
|
// Lazily update animators whenever the scrolling changes
|
||||||
|
mNeedsAnimatorUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
public void setOnKeyguard(boolean onKeyguard) {
|
public void setOnKeyguard(boolean onKeyguard) {
|
||||||
mOnKeyguard = onKeyguard;
|
mOnKeyguard = onKeyguard;
|
||||||
updateQQSVisibility();
|
updateQQSVisibility();
|
||||||
@@ -172,6 +179,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateAnimators() {
|
private void updateAnimators() {
|
||||||
|
mNeedsAnimatorUpdate = false;
|
||||||
TouchAnimator.Builder firstPageBuilder = new Builder();
|
TouchAnimator.Builder firstPageBuilder = new Builder();
|
||||||
TouchAnimator.Builder translationXBuilder = new Builder();
|
TouchAnimator.Builder translationXBuilder = new Builder();
|
||||||
TouchAnimator.Builder translationYBuilder = new Builder();
|
TouchAnimator.Builder translationYBuilder = new Builder();
|
||||||
@@ -286,13 +294,16 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
|||||||
.setListener(this)
|
.setListener(this)
|
||||||
.build();
|
.build();
|
||||||
// Fade in the tiles/labels as we reach the final position.
|
// Fade in the tiles/labels as we reach the final position.
|
||||||
mFirstPageDelayedAnimator = new TouchAnimator.Builder()
|
Builder builder = new Builder()
|
||||||
.setStartDelay(EXPANDED_TILE_DELAY)
|
.setStartDelay(EXPANDED_TILE_DELAY)
|
||||||
.addFloat(tileLayout, "alpha", 0, 1)
|
.addFloat(tileLayout, "alpha", 0, 1);
|
||||||
.addFloat(mQsPanel.getDivider(), "alpha", 0, 1)
|
if (mQsPanel.getSecurityFooter() != null) {
|
||||||
.addFloat(mQsPanel.getFooter().getView(), "alpha", 0, 1).build();
|
builder.addFloat(mQsPanel.getSecurityFooter().getView(), "alpha", 0, 1);
|
||||||
mAllViews.add(mQsPanel.getDivider());
|
}
|
||||||
mAllViews.add(mQsPanel.getFooter().getView());
|
mFirstPageDelayedAnimator = builder.build();
|
||||||
|
if (mQsPanel.getSecurityFooter() != null) {
|
||||||
|
mAllViews.add(mQsPanel.getSecurityFooter().getView());
|
||||||
|
}
|
||||||
float px = 0;
|
float px = 0;
|
||||||
float py = 1;
|
float py = 1;
|
||||||
if (tiles.size() <= 3) {
|
if (tiles.size() <= 3) {
|
||||||
@@ -308,7 +319,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
|||||||
}
|
}
|
||||||
mNonfirstPageAnimator = new TouchAnimator.Builder()
|
mNonfirstPageAnimator = new TouchAnimator.Builder()
|
||||||
.addFloat(mQuickQsPanel, "alpha", 1, 0)
|
.addFloat(mQuickQsPanel, "alpha", 1, 0)
|
||||||
.addFloat(mQsPanel.getDivider(), "alpha", 0, 1)
|
|
||||||
.setListener(mNonFirstPageListener)
|
.setListener(mNonFirstPageListener)
|
||||||
.setEndDelay(.5f)
|
.setEndDelay(.5f)
|
||||||
.build();
|
.build();
|
||||||
@@ -339,10 +349,18 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
|||||||
loc1[0] += view.getLeft();
|
loc1[0] += view.getLeft();
|
||||||
loc1[1] += view.getTop();
|
loc1[1] += view.getTop();
|
||||||
}
|
}
|
||||||
|
if (!(view instanceof PagedTileLayout)) {
|
||||||
|
// Remove the scrolling position of all scroll views other than the viewpager
|
||||||
|
loc1[0] -= view.getScrollX();
|
||||||
|
loc1[1] -= view.getScrollY();
|
||||||
|
}
|
||||||
getRelativePositionInt(loc1, (View) view.getParent(), parent);
|
getRelativePositionInt(loc1, (View) view.getParent(), parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(float position) {
|
public void setPosition(float position) {
|
||||||
|
if (mNeedsAnimatorUpdate) {
|
||||||
|
updateAnimators();
|
||||||
|
}
|
||||||
if (mFirstPageAnimator == null) return;
|
if (mFirstPageAnimator == null) return;
|
||||||
if (mOnKeyguard) {
|
if (mOnKeyguard) {
|
||||||
if (mShowCollapsedOnKeyguard) {
|
if (mShowCollapsedOnKeyguard) {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class QSContainerImpl extends FrameLayout {
|
|||||||
private float mQsExpansion;
|
private float mQsExpansion;
|
||||||
private QSCustomizer mQSCustomizer;
|
private QSCustomizer mQSCustomizer;
|
||||||
private View mDragHandle;
|
private View mDragHandle;
|
||||||
|
private View mQSPanelContainer;
|
||||||
|
|
||||||
private View mBackground;
|
private View mBackground;
|
||||||
private View mBackgroundGradient;
|
private View mBackgroundGradient;
|
||||||
@@ -61,6 +62,7 @@ public class QSContainerImpl extends FrameLayout {
|
|||||||
protected void onFinishInflate() {
|
protected void onFinishInflate() {
|
||||||
super.onFinishInflate();
|
super.onFinishInflate();
|
||||||
mQSPanel = findViewById(R.id.quick_settings_panel);
|
mQSPanel = findViewById(R.id.quick_settings_panel);
|
||||||
|
mQSPanelContainer = findViewById(R.id.expanded_qs_scroll_view);
|
||||||
mQSDetail = findViewById(R.id.qs_detail);
|
mQSDetail = findViewById(R.id.qs_detail);
|
||||||
mHeader = findViewById(R.id.header);
|
mHeader = findViewById(R.id.header);
|
||||||
mQSCustomizer = findViewById(R.id.qs_customize);
|
mQSCustomizer = findViewById(R.id.qs_customize);
|
||||||
@@ -95,7 +97,7 @@ public class QSContainerImpl extends FrameLayout {
|
|||||||
Configuration config = getResources().getConfiguration();
|
Configuration config = getResources().getConfiguration();
|
||||||
boolean navBelow = config.smallestScreenWidthDp >= 600
|
boolean navBelow = config.smallestScreenWidthDp >= 600
|
||||||
|| config.orientation != Configuration.ORIENTATION_LANDSCAPE;
|
|| config.orientation != Configuration.ORIENTATION_LANDSCAPE;
|
||||||
MarginLayoutParams layoutParams = (MarginLayoutParams) mQSPanel.getLayoutParams();
|
MarginLayoutParams layoutParams = (MarginLayoutParams) mQSPanelContainer.getLayoutParams();
|
||||||
|
|
||||||
// The footer is pinned to the bottom of QSPanel (same bottoms), therefore we don't need to
|
// 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.
|
// subtract its height. We do not care if the collapsed notifications fit in the screen.
|
||||||
@@ -109,12 +111,11 @@ public class QSContainerImpl extends FrameLayout {
|
|||||||
+ layoutParams.rightMargin;
|
+ layoutParams.rightMargin;
|
||||||
final int qsPanelWidthSpec = getChildMeasureSpec(widthMeasureSpec, padding,
|
final int qsPanelWidthSpec = getChildMeasureSpec(widthMeasureSpec, padding,
|
||||||
layoutParams.width);
|
layoutParams.width);
|
||||||
// Measure with EXACTLY. That way, PagedTileLayout will only use excess height and will be
|
mQSPanelContainer.measure(qsPanelWidthSpec,
|
||||||
// measured last, after other views and padding is accounted for.
|
MeasureSpec.makeMeasureSpec(maxQs, MeasureSpec.AT_MOST));
|
||||||
mQSPanel.measure(qsPanelWidthSpec, MeasureSpec.makeMeasureSpec(maxQs, MeasureSpec.EXACTLY));
|
int width = mQSPanelContainer.getMeasuredWidth() + padding;
|
||||||
int width = mQSPanel.getMeasuredWidth() + padding;
|
|
||||||
int height = layoutParams.topMargin + layoutParams.bottomMargin
|
int height = layoutParams.topMargin + layoutParams.bottomMargin
|
||||||
+ mQSPanel.getMeasuredHeight() + getPaddingBottom();
|
+ mQSPanelContainer.getMeasuredHeight() + getPaddingBottom();
|
||||||
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
||||||
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
|
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
|
||||||
// QSCustomizer will always be the height of the screen, but do this after
|
// QSCustomizer will always be the height of the screen, but do this after
|
||||||
@@ -130,7 +131,7 @@ public class QSContainerImpl extends FrameLayout {
|
|||||||
// Do not measure QSPanel again when doing super.onMeasure.
|
// Do not measure QSPanel again when doing super.onMeasure.
|
||||||
// This prevents the pages in PagedTileLayout to be remeasured with a different (incorrect)
|
// This prevents the pages in PagedTileLayout to be remeasured with a different (incorrect)
|
||||||
// size to the one used for determining the number of rows and then the number of pages.
|
// size to the one used for determining the number of rows and then the number of pages.
|
||||||
if (child != mQSPanel) {
|
if (child != mQSPanelContainer) {
|
||||||
super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
|
super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
|
||||||
parentHeightMeasureSpec, heightUsed);
|
parentHeightMeasureSpec, heightUsed);
|
||||||
}
|
}
|
||||||
@@ -151,10 +152,10 @@ public class QSContainerImpl extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateResources() {
|
private void updateResources() {
|
||||||
LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
|
LayoutParams layoutParams = (LayoutParams) mQSPanelContainer.getLayoutParams();
|
||||||
layoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
|
layoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
|
||||||
com.android.internal.R.dimen.quick_qs_offset_height);
|
com.android.internal.R.dimen.quick_qs_offset_height);
|
||||||
mQSPanel.setLayoutParams(layoutParams);
|
mQSPanelContainer.setLayoutParams(layoutParams);
|
||||||
|
|
||||||
mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
|
mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
|
||||||
mContentPaddingStart = getResources().getDimensionPixelSize(
|
mContentPaddingStart = getResources().getDimensionPixelSize(
|
||||||
@@ -185,7 +186,7 @@ public class QSContainerImpl extends FrameLayout {
|
|||||||
mQSDetail.setBottom(getTop() + height);
|
mQSDetail.setBottom(getTop() + height);
|
||||||
// Pin the drag handle to the bottom of the panel.
|
// Pin the drag handle to the bottom of the panel.
|
||||||
mDragHandle.setTranslationY(height - mDragHandle.getHeight());
|
mDragHandle.setTranslationY(height - mDragHandle.getHeight());
|
||||||
mBackground.setTop(mQSPanel.getTop());
|
mBackground.setTop(mQSPanelContainer.getTop());
|
||||||
mBackground.setBottom(height);
|
mBackground.setBottom(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +224,7 @@ public class QSContainerImpl extends FrameLayout {
|
|||||||
LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||||
lp.rightMargin = mSideMargins;
|
lp.rightMargin = mSideMargins;
|
||||||
lp.leftMargin = mSideMargins;
|
lp.leftMargin = mSideMargins;
|
||||||
if (view == mQSPanel) {
|
if (view == mQSPanelContainer) {
|
||||||
// QS panel lays out some of its content full width
|
// QS panel lays out some of its content full width
|
||||||
mQSPanel.setContentMargins(mContentPaddingStart, mContentPaddingEnd);
|
mQSPanel.setContentMargins(mContentPaddingStart, mContentPaddingEnd);
|
||||||
} else if (view == mHeader) {
|
} else if (view == mHeader) {
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import android.os.Bundle;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -72,6 +71,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
protected QuickStatusBarHeader mHeader;
|
protected QuickStatusBarHeader mHeader;
|
||||||
private QSCustomizer mQSCustomizer;
|
private QSCustomizer mQSCustomizer;
|
||||||
protected QSPanel mQSPanel;
|
protected QSPanel mQSPanel;
|
||||||
|
protected NonInterceptingScrollView mQSPanelScrollView;
|
||||||
private QSDetail mQSDetail;
|
private QSDetail mQSDetail;
|
||||||
private boolean mListening;
|
private boolean mListening;
|
||||||
private QSContainerImpl mContainer;
|
private QSContainerImpl mContainer;
|
||||||
@@ -122,8 +122,20 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
mQSPanel = view.findViewById(R.id.quick_settings_panel);
|
mQSPanel = view.findViewById(R.id.quick_settings_panel);
|
||||||
|
mQSPanelScrollView = view.findViewById(R.id.expanded_qs_scroll_view);
|
||||||
|
mQSPanelScrollView.addOnLayoutChangeListener(
|
||||||
|
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
|
||||||
|
updateQsBounds();
|
||||||
|
});
|
||||||
|
mQSPanelScrollView.setOnScrollChangeListener(
|
||||||
|
(v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
|
||||||
|
// Lazily update animators whenever the scrolling changes
|
||||||
|
mQSAnimator.onQsScrollingChanged();
|
||||||
|
mHeader.setExpandedScrollAmount(scrollY);
|
||||||
|
});
|
||||||
mQSDetail = view.findViewById(R.id.qs_detail);
|
mQSDetail = view.findViewById(R.id.qs_detail);
|
||||||
mHeader = view.findViewById(R.id.header);
|
mHeader = view.findViewById(R.id.header);
|
||||||
|
mQSPanel.setHeaderContainer(view.findViewById(R.id.header_text_container));
|
||||||
mFooter = view.findViewById(R.id.qs_footer);
|
mFooter = view.findViewById(R.id.qs_footer);
|
||||||
mContainer = view.findViewById(id.quick_settings_container);
|
mContainer = view.findViewById(id.quick_settings_container);
|
||||||
|
|
||||||
@@ -133,8 +145,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
|
|
||||||
|
|
||||||
mQSDetail.setQsPanel(mQSPanel, mHeader, (View) mFooter);
|
mQSDetail.setQsPanel(mQSPanel, mHeader, (View) mFooter);
|
||||||
mQSAnimator = new QSAnimator(this,
|
mQSAnimator = new QSAnimator(this, mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
|
||||||
mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
|
|
||||||
|
|
||||||
mQSCustomizer = view.findViewById(R.id.qs_customize);
|
mQSCustomizer = view.findViewById(R.id.qs_customize);
|
||||||
mQSCustomizer.setQs(this);
|
mQSCustomizer.setQs(this);
|
||||||
@@ -318,11 +330,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
return mQSPanel.isShowingCustomize() || mQSDetail.isShowingDetail();
|
return mQSPanel.isShowingCustomize() || mQSDetail.isShowingDetail();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
|
||||||
return isCustomizing();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHeaderClickable(boolean clickable) {
|
public void setHeaderClickable(boolean clickable) {
|
||||||
if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable);
|
if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable);
|
||||||
@@ -394,7 +401,9 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
mLastViewHeight = currentHeight;
|
mLastViewHeight = currentHeight;
|
||||||
|
|
||||||
boolean fullyExpanded = expansion == 1;
|
boolean fullyExpanded = expansion == 1;
|
||||||
int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom();
|
boolean fullyCollapsed = expansion == 0.0f;
|
||||||
|
int heightDiff = mQSPanelScrollView.getBottom() - mHeader.getBottom()
|
||||||
|
+ mHeader.getPaddingBottom();
|
||||||
float panelTranslationY = translationScaleY * heightDiff;
|
float panelTranslationY = translationScaleY * heightDiff;
|
||||||
|
|
||||||
// Let the views animate their contents correctly by giving them the necessary context.
|
// Let the views animate their contents correctly by giving them the necessary context.
|
||||||
@@ -403,19 +412,19 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion);
|
mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion);
|
||||||
mQSPanel.getQsTileRevealController().setExpansion(expansion);
|
mQSPanel.getQsTileRevealController().setExpansion(expansion);
|
||||||
mQSPanel.getTileLayout().setExpansion(expansion);
|
mQSPanel.getTileLayout().setExpansion(expansion);
|
||||||
mQSPanel.setTranslationY(translationScaleY * heightDiff);
|
mQSPanelScrollView.setTranslationY(translationScaleY * heightDiff);
|
||||||
|
if (fullyCollapsed) {
|
||||||
|
mQSPanelScrollView.setScrollY(0);
|
||||||
|
}
|
||||||
mQSDetail.setFullyExpanded(fullyExpanded);
|
mQSDetail.setFullyExpanded(fullyExpanded);
|
||||||
|
|
||||||
if (fullyExpanded) {
|
if (!fullyExpanded) {
|
||||||
// Always draw within the bounds of the view when fully expanded.
|
|
||||||
mQSPanel.setClipBounds(null);
|
|
||||||
} else {
|
|
||||||
// Set bounds on the QS panel so it doesn't run over the header when animating.
|
// Set bounds on the QS panel so it doesn't run over the header when animating.
|
||||||
mQsBounds.top = (int) -mQSPanel.getTranslationY();
|
mQsBounds.top = (int) -mQSPanelScrollView.getTranslationY();
|
||||||
mQsBounds.right = mQSPanel.getWidth();
|
mQsBounds.right = mQSPanelScrollView.getWidth();
|
||||||
mQsBounds.bottom = mQSPanel.getHeight();
|
mQsBounds.bottom = mQSPanelScrollView.getHeight();
|
||||||
mQSPanel.setClipBounds(mQsBounds);
|
|
||||||
}
|
}
|
||||||
|
updateQsBounds();
|
||||||
|
|
||||||
if (mQSAnimator != null) {
|
if (mQSAnimator != null) {
|
||||||
mQSAnimator.setPosition(expansion);
|
mQSAnimator.setPosition(expansion);
|
||||||
@@ -423,31 +432,63 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
updateMediaPositions();
|
updateMediaPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateQsBounds() {
|
||||||
|
if (mLastQSExpansion == 1.0f) {
|
||||||
|
// Fully expanded, let's set the layout bounds as clip bounds. This is necessary because
|
||||||
|
// it's a scrollview and otherwise wouldn't be clipped.
|
||||||
|
mQsBounds.set(0, 0, mQSPanelScrollView.getWidth(), mQSPanelScrollView.getHeight());
|
||||||
|
}
|
||||||
|
mQSPanelScrollView.setClipBounds(mQsBounds);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateMediaPositions() {
|
private void updateMediaPositions() {
|
||||||
if (Utils.useQsMediaPlayer(getContext())) {
|
if (Utils.useQsMediaPlayer(getContext())) {
|
||||||
mContainer.getLocationOnScreen(mTmpLocation);
|
mContainer.getLocationOnScreen(mTmpLocation);
|
||||||
float absoluteBottomPosition = mTmpLocation[1] + mContainer.getHeight();
|
float absoluteBottomPosition = mTmpLocation[1] + mContainer.getHeight();
|
||||||
pinToBottom(absoluteBottomPosition, mQSPanel.getMediaHost());
|
// The Media can be scrolled off screen by default, let's offset it
|
||||||
pinToBottom(absoluteBottomPosition - mHeader.getPaddingBottom(),
|
float expandedMediaPosition = absoluteBottomPosition - mQSPanelScrollView.getScrollY()
|
||||||
mHeader.getHeaderQsPanel().getMediaHost());
|
+ mQSPanelScrollView.getScrollRange();
|
||||||
|
// The expanded media host should never move below the laid out position
|
||||||
|
pinToBottom(expandedMediaPosition, mQSPanel.getMediaHost(), true /* expanded */);
|
||||||
|
// The expanded media host should never move above the laid out position
|
||||||
|
pinToBottom(absoluteBottomPosition, mHeader.getHeaderQsPanel().getMediaHost(),
|
||||||
|
false /* expanded */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pinToBottom(float absoluteBottomPosition, MediaHost mediaHost) {
|
private void pinToBottom(float absoluteBottomPosition, MediaHost mediaHost, boolean expanded) {
|
||||||
View hostView = mediaHost.getHostView();
|
View hostView = mediaHost.getHostView();
|
||||||
if (mLastQSExpansion > 0) {
|
if (mLastQSExpansion > 0) {
|
||||||
ViewGroup.MarginLayoutParams params =
|
float targetPosition = absoluteBottomPosition - getTotalBottomMargin(hostView)
|
||||||
(ViewGroup.MarginLayoutParams) hostView.getLayoutParams();
|
|
||||||
float targetPosition = absoluteBottomPosition - params.bottomMargin
|
|
||||||
- hostView.getHeight();
|
- hostView.getHeight();
|
||||||
float currentPosition = mediaHost.getCurrentBounds().top
|
float currentPosition = mediaHost.getCurrentBounds().top
|
||||||
- hostView.getTranslationY();
|
- hostView.getTranslationY();
|
||||||
hostView.setTranslationY(targetPosition - currentPosition);
|
float translationY = targetPosition - currentPosition;
|
||||||
|
if (expanded) {
|
||||||
|
// Never go below the laid out position. This is necessary since the qs panel can
|
||||||
|
// change in height and we don't want to ever go below it's position
|
||||||
|
translationY = Math.min(translationY, 0);
|
||||||
|
} else {
|
||||||
|
translationY = Math.max(translationY, 0);
|
||||||
|
}
|
||||||
|
hostView.setTranslationY(translationY);
|
||||||
} else {
|
} else {
|
||||||
hostView.setTranslationY(0);
|
hostView.setTranslationY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float getTotalBottomMargin(View startView) {
|
||||||
|
int result = 0;
|
||||||
|
View child = startView;
|
||||||
|
View parent = (View) startView.getParent();
|
||||||
|
while (!(parent instanceof QSContainerImpl) && parent != null) {
|
||||||
|
result += parent.getHeight() - child.getBottom();
|
||||||
|
child = parent;
|
||||||
|
parent = (View) parent.getParent();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean headerWillBeAnimating() {
|
private boolean headerWillBeAnimating() {
|
||||||
return mState == StatusBarState.KEYGUARD && mShowCollapsedOnKeyguard
|
return mState == StatusBarState.KEYGUARD && mShowCollapsedOnKeyguard
|
||||||
&& !isKeyguardShowing();
|
&& !isKeyguardShowing();
|
||||||
@@ -504,7 +545,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
public void notifyCustomizeChanged() {
|
public void notifyCustomizeChanged() {
|
||||||
// The customize state changed, so our height changed.
|
// The customize state changed, so our height changed.
|
||||||
mContainer.updateExpansion();
|
mContainer.updateExpansion();
|
||||||
mQSPanel.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
|
mQSPanelScrollView.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE
|
||||||
|
: View.INVISIBLE);
|
||||||
mFooter.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
|
mFooter.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
|
||||||
// Let the panel know the position changed and it needs to update where notifications
|
// Let the panel know the position changed and it needs to update where notifications
|
||||||
// and whatnot are.
|
// and whatnot are.
|
||||||
@@ -521,9 +563,9 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
return getView().getHeight();
|
return getView().getHeight();
|
||||||
}
|
}
|
||||||
if (mQSDetail.isClosingDetail()) {
|
if (mQSDetail.isClosingDetail()) {
|
||||||
LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
|
LayoutParams layoutParams = (LayoutParams) mQSPanelScrollView.getLayoutParams();
|
||||||
int panelHeight = layoutParams.topMargin + layoutParams.bottomMargin +
|
int panelHeight = layoutParams.topMargin + layoutParams.bottomMargin +
|
||||||
+ mQSPanel.getMeasuredHeight();
|
+ mQSPanelScrollView.getMeasuredHeight();
|
||||||
return panelHeight + getView().getPaddingBottom();
|
return panelHeight + getView().getPaddingBottom();
|
||||||
} else {
|
} else {
|
||||||
return getView().getMeasuredHeight();
|
return getView().getMeasuredHeight();
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package com.android.systemui.qs;
|
package com.android.systemui.qs;
|
||||||
|
|
||||||
import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState;
|
|
||||||
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
|
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
|
||||||
import static com.android.systemui.util.Utils.useQsMediaPlayer;
|
import static com.android.systemui.util.Utils.useQsMediaPlayer;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -29,8 +29,8 @@ import android.metrics.LogMaker;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.service.quicksettings.Tile;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -39,7 +39,7 @@ import android.widget.LinearLayout;
|
|||||||
import com.android.internal.logging.MetricsLogger;
|
import com.android.internal.logging.MetricsLogger;
|
||||||
import com.android.internal.logging.UiEventLogger;
|
import com.android.internal.logging.UiEventLogger;
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.settingslib.Utils;
|
import com.android.internal.widget.RemeasuringLinearLayout;
|
||||||
import com.android.systemui.Dependency;
|
import com.android.systemui.Dependency;
|
||||||
import com.android.systemui.Dumpable;
|
import com.android.systemui.Dumpable;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
@@ -83,38 +83,65 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
|
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
|
||||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||||
protected final MediaHost mMediaHost;
|
protected final MediaHost mMediaHost;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index where the content starts that needs to be moved between parents
|
||||||
|
*/
|
||||||
|
private final int mMovableContentStartIndex;
|
||||||
private String mCachedSpecs = "";
|
private String mCachedSpecs = "";
|
||||||
protected final View mBrightnessView;
|
|
||||||
|
@Nullable
|
||||||
|
protected View mBrightnessView;
|
||||||
|
@Nullable
|
||||||
|
private BrightnessController mBrightnessController;
|
||||||
|
|
||||||
private final H mHandler = new H();
|
private final H mHandler = new H();
|
||||||
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
|
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
|
||||||
private final QSTileRevealController mQsTileRevealController;
|
private QSTileRevealController mQsTileRevealController;
|
||||||
/** Whether or not the QS media player feature is enabled. */
|
/** Whether or not the QS media player feature is enabled. */
|
||||||
protected boolean mUsingMediaPlayer;
|
protected boolean mUsingMediaPlayer;
|
||||||
|
private int mVisualMarginStart;
|
||||||
|
private int mVisualMarginEnd;
|
||||||
|
|
||||||
protected boolean mExpanded;
|
protected boolean mExpanded;
|
||||||
protected boolean mListening;
|
protected boolean mListening;
|
||||||
|
|
||||||
private QSDetail.Callback mCallback;
|
private QSDetail.Callback mCallback;
|
||||||
private BrightnessController mBrightnessController;
|
|
||||||
private final DumpManager mDumpManager;
|
private final DumpManager mDumpManager;
|
||||||
private final QSLogger mQSLogger;
|
private final QSLogger mQSLogger;
|
||||||
protected final UiEventLogger mUiEventLogger;
|
protected final UiEventLogger mUiEventLogger;
|
||||||
protected QSTileHost mHost;
|
protected QSTileHost mHost;
|
||||||
|
|
||||||
protected QSSecurityFooter mFooter;
|
@Nullable
|
||||||
|
protected QSSecurityFooter mSecurityFooter;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected View mFooter;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private ViewGroup mHeaderContainer;
|
||||||
private PageIndicator mFooterPageIndicator;
|
private PageIndicator mFooterPageIndicator;
|
||||||
private boolean mGridContentVisible = true;
|
private boolean mGridContentVisible = true;
|
||||||
private int mContentMarginStart;
|
private int mContentMarginStart;
|
||||||
private int mContentMarginEnd;
|
private int mContentMarginEnd;
|
||||||
private int mVisualTilePadding;
|
private int mVisualTilePadding;
|
||||||
|
private boolean mUsingHorizontalLayout;
|
||||||
protected QSTileLayout mTileLayout;
|
|
||||||
|
|
||||||
private QSCustomizer mCustomizePanel;
|
private QSCustomizer mCustomizePanel;
|
||||||
private Record mDetailRecord;
|
private Record mDetailRecord;
|
||||||
|
|
||||||
private BrightnessMirrorController mBrightnessMirrorController;
|
private BrightnessMirrorController mBrightnessMirrorController;
|
||||||
private View mDivider;
|
private LinearLayout mHorizontalLinearLayout;
|
||||||
|
private LinearLayout mHorizontalContentContainer;
|
||||||
|
|
||||||
|
// Only used with media
|
||||||
|
private QSTileLayout mHorizontalTileLayout;
|
||||||
|
protected QSTileLayout mRegularTileLayout;
|
||||||
|
protected QSTileLayout mTileLayout;
|
||||||
|
private int mLastOrientation = -1;
|
||||||
|
private int mMediaTotalBottomMargin;
|
||||||
|
private int mFooterMarginStartHorizontal;
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public QSPanel(
|
public QSPanel(
|
||||||
@@ -128,7 +155,13 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
) {
|
) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
mUsingMediaPlayer = useQsMediaPlayer(context);
|
mUsingMediaPlayer = useQsMediaPlayer(context);
|
||||||
|
mMediaTotalBottomMargin = getResources().getDimensionPixelSize(
|
||||||
|
R.dimen.quick_settings_bottom_margin_media);
|
||||||
mMediaHost = mediaHost;
|
mMediaHost = mediaHost;
|
||||||
|
mMediaHost.setVisibleChangedListener((visible) -> {
|
||||||
|
switchTileLayout();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mQSLogger = qsLogger;
|
mQSLogger = qsLogger;
|
||||||
mDumpManager = dumpManager;
|
mDumpManager = dumpManager;
|
||||||
@@ -137,71 +170,97 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
|
|
||||||
setOrientation(VERTICAL);
|
setOrientation(VERTICAL);
|
||||||
|
|
||||||
|
addViewsAboveTiles();
|
||||||
|
mMovableContentStartIndex = getChildCount();
|
||||||
|
mRegularTileLayout = createRegularTileLayout();
|
||||||
|
|
||||||
|
if (mUsingMediaPlayer) {
|
||||||
|
mHorizontalLinearLayout = new RemeasuringLinearLayout(mContext);
|
||||||
|
mHorizontalLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
mHorizontalLinearLayout.setClipChildren(false);
|
||||||
|
mHorizontalLinearLayout.setClipToPadding(false);
|
||||||
|
|
||||||
|
mHorizontalContentContainer = new RemeasuringLinearLayout(mContext);
|
||||||
|
mHorizontalContentContainer.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
mHorizontalContentContainer.setClipChildren(false);
|
||||||
|
mHorizontalContentContainer.setClipToPadding(false);
|
||||||
|
|
||||||
|
mHorizontalTileLayout = createHorizontalTileLayout();
|
||||||
|
LayoutParams lp = new LayoutParams(0, LayoutParams.WRAP_CONTENT, 1);
|
||||||
|
int marginSize = (int) mContext.getResources().getDimension(R.dimen.qqs_media_spacing);
|
||||||
|
lp.setMarginStart(0);
|
||||||
|
lp.setMarginEnd(marginSize);
|
||||||
|
lp.gravity = Gravity.CENTER_VERTICAL;
|
||||||
|
mHorizontalLinearLayout.addView(mHorizontalContentContainer, lp);
|
||||||
|
|
||||||
|
lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0, 1);
|
||||||
|
addView(mHorizontalLinearLayout, lp);
|
||||||
|
|
||||||
|
initMediaHostState();
|
||||||
|
}
|
||||||
|
addSecurityFooter();
|
||||||
|
if (mRegularTileLayout instanceof PagedTileLayout) {
|
||||||
|
mQsTileRevealController = new QSTileRevealController(mContext, this,
|
||||||
|
(PagedTileLayout) mRegularTileLayout);
|
||||||
|
}
|
||||||
|
mQSLogger.logAllTilesChangeListening(mListening, getDumpableTag(), mCachedSpecs);
|
||||||
|
updateResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addSecurityFooter() {
|
||||||
|
mSecurityFooter = new QSSecurityFooter(this, mContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addViewsAboveTiles() {
|
||||||
mBrightnessView = LayoutInflater.from(mContext).inflate(
|
mBrightnessView = LayoutInflater.from(mContext).inflate(
|
||||||
R.layout.quick_settings_brightness_dialog, this, false);
|
R.layout.quick_settings_brightness_dialog, this, false);
|
||||||
addView(mBrightnessView);
|
addView(mBrightnessView);
|
||||||
|
|
||||||
mTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
|
|
||||||
R.layout.qs_paged_tile_layout, this, false);
|
|
||||||
mQSLogger.logAllTilesChangeListening(mListening, getDumpableTag(), mCachedSpecs);
|
|
||||||
mTileLayout.setListening(mListening);
|
|
||||||
addView((View) mTileLayout);
|
|
||||||
|
|
||||||
mQsTileRevealController = new QSTileRevealController(mContext, this,
|
|
||||||
(PagedTileLayout) mTileLayout);
|
|
||||||
|
|
||||||
addDivider();
|
|
||||||
|
|
||||||
mFooter = new QSSecurityFooter(this, context);
|
|
||||||
addView(mFooter.getView());
|
|
||||||
|
|
||||||
updateResources();
|
|
||||||
|
|
||||||
mBrightnessController = new BrightnessController(getContext(),
|
mBrightnessController = new BrightnessController(getContext(),
|
||||||
findViewById(R.id.brightness_slider), mBroadcastDispatcher);
|
findViewById(R.id.brightness_slider), mBroadcastDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected QSTileLayout createRegularTileLayout() {
|
||||||
protected void onFinishInflate() {
|
if (mRegularTileLayout == null) {
|
||||||
super.onFinishInflate();
|
mRegularTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
|
||||||
// Add media carousel at the end
|
R.layout.qs_paged_tile_layout, this, false);
|
||||||
if (useQsMediaPlayer(getContext())) {
|
|
||||||
addMediaHostView();
|
|
||||||
}
|
}
|
||||||
|
return mRegularTileLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addMediaHostView() {
|
|
||||||
|
protected QSTileLayout createHorizontalTileLayout() {
|
||||||
|
return createRegularTileLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initMediaHostState() {
|
||||||
mMediaHost.setExpansion(1.0f);
|
mMediaHost.setExpansion(1.0f);
|
||||||
mMediaHost.setShowsOnlyActiveMedia(false);
|
mMediaHost.setShowsOnlyActiveMedia(false);
|
||||||
mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
|
mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
|
||||||
ViewGroup hostView = mMediaHost.getHostView();
|
|
||||||
addView(hostView);
|
|
||||||
int bottomPadding = getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.quick_settings_expanded_bottom_margin);
|
|
||||||
MarginLayoutParams layoutParams = (MarginLayoutParams) hostView.getLayoutParams();
|
|
||||||
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
|
||||||
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
|
|
||||||
layoutParams.bottomMargin = bottomPadding;
|
|
||||||
hostView.setLayoutParams(layoutParams);
|
|
||||||
updateMediaHostContentMargins();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addDivider() {
|
|
||||||
mDivider = LayoutInflater.from(mContext).inflate(R.layout.qs_divider, this, false);
|
|
||||||
mDivider.setBackgroundColor(Utils.applyAlpha(mDivider.getAlpha(),
|
|
||||||
getColorForState(mContext, Tile.STATE_ACTIVE)));
|
|
||||||
addView(mDivider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
|
||||||
|
if (mTileLayout instanceof PagedTileLayout) {
|
||||||
|
// Allow the UI to be as big as it want's to, we're in a scroll view
|
||||||
|
int newHeight = 10000;
|
||||||
|
int availableHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
int excessHeight = newHeight - availableHeight;
|
||||||
|
// Measure with EXACTLY. That way, The content will only use excess height and will
|
||||||
|
// be measured last, after other views and padding is accounted for. This only
|
||||||
|
// works because our Layouts in here remeasure themselves with the exact content
|
||||||
|
// height.
|
||||||
|
heightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY);
|
||||||
|
((PagedTileLayout) mTileLayout).setExcessHeight(excessHeight);
|
||||||
|
}
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
|
||||||
// We want all the logic of LinearLayout#onMeasure, and for it to assign the excess space
|
// We want all the logic of LinearLayout#onMeasure, and for it to assign the excess space
|
||||||
// not used by the other children to PagedTileLayout. However, in this case, LinearLayout
|
// not used by the other children to PagedTileLayout. However, in this case, LinearLayout
|
||||||
// assumes that PagedTileLayout would use all the excess space. This is not the case as
|
// assumes that PagedTileLayout would use all the excess space. This is not the case as
|
||||||
// PagedTileLayout height is quantized (because it shows a certain number of rows).
|
// PagedTileLayout height is quantized (because it shows a certain number of rows).
|
||||||
// Therefore, after everything is measured, we need to make sure that we add up the correct
|
// Therefore, after everything is measured, we need to make sure that we add up the correct
|
||||||
// total height
|
// total height
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
||||||
int height = getPaddingBottom() + getPaddingTop();
|
int height = getPaddingBottom() + getPaddingTop();
|
||||||
int numChildren = getChildCount();
|
int numChildren = getChildCount();
|
||||||
for (int i = 0; i < numChildren; i++) {
|
for (int i = 0; i < numChildren; i++) {
|
||||||
@@ -215,10 +274,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
setMeasuredDimension(getMeasuredWidth(), height);
|
setMeasuredDimension(getMeasuredWidth(), height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public View getDivider() {
|
|
||||||
return mDivider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QSTileRevealController getQsTileRevealController() {
|
public QSTileRevealController getQsTileRevealController() {
|
||||||
return mQsTileRevealController;
|
return mQsTileRevealController;
|
||||||
}
|
}
|
||||||
@@ -273,7 +328,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTuningChanged(String key, String newValue) {
|
public void onTuningChanged(String key, String newValue) {
|
||||||
if (QS_SHOW_BRIGHTNESS.equals(key)) {
|
if (QS_SHOW_BRIGHTNESS.equals(key) && mBrightnessView != null) {
|
||||||
updateViewVisibilityForTuningValue(mBrightnessView, newValue);
|
updateViewVisibilityForTuningValue(mBrightnessView, newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,6 +371,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
updateBrightnessMirror();
|
updateBrightnessMirror();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
View getBrightnessView() {
|
View getBrightnessView() {
|
||||||
return mBrightnessView;
|
return mBrightnessView;
|
||||||
}
|
}
|
||||||
@@ -328,7 +384,9 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
mHost = host;
|
mHost = host;
|
||||||
mHost.addCallback(this);
|
mHost.addCallback(this);
|
||||||
setTiles(mHost.getTiles());
|
setTiles(mHost.getTiles());
|
||||||
mFooter.setHostEnvironment(host);
|
if (mSecurityFooter != null) {
|
||||||
|
mSecurityFooter.setHostEnvironment(host);
|
||||||
|
}
|
||||||
mCustomizePanel = customizer;
|
mCustomizePanel = customizer;
|
||||||
if (mCustomizePanel != null) {
|
if (mCustomizePanel != null) {
|
||||||
mCustomizePanel.setHost(mHost);
|
mCustomizePanel.setHost(mHost);
|
||||||
@@ -341,18 +399,18 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
* @param pageIndicator indicator to use for page scrolling
|
* @param pageIndicator indicator to use for page scrolling
|
||||||
*/
|
*/
|
||||||
public void setFooterPageIndicator(PageIndicator pageIndicator) {
|
public void setFooterPageIndicator(PageIndicator pageIndicator) {
|
||||||
if (mTileLayout instanceof PagedTileLayout) {
|
if (mRegularTileLayout instanceof PagedTileLayout) {
|
||||||
mFooterPageIndicator = pageIndicator;
|
mFooterPageIndicator = pageIndicator;
|
||||||
updatePageIndicator();
|
updatePageIndicator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePageIndicator() {
|
private void updatePageIndicator() {
|
||||||
if (mTileLayout instanceof PagedTileLayout) {
|
if (mRegularTileLayout instanceof PagedTileLayout) {
|
||||||
if (mFooterPageIndicator != null) {
|
if (mFooterPageIndicator != null) {
|
||||||
mFooterPageIndicator.setVisibility(View.GONE);
|
mFooterPageIndicator.setVisibility(View.GONE);
|
||||||
|
|
||||||
((PagedTileLayout) mTileLayout).setPageIndicator(mFooterPageIndicator);
|
((PagedTileLayout) mRegularTileLayout).setPageIndicator(mFooterPageIndicator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,6 +422,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
public void updateResources() {
|
public void updateResources() {
|
||||||
int tileSize = getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
|
int tileSize = getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
|
||||||
int tileBg = getResources().getDimensionPixelSize(R.dimen.qs_tile_background_size);
|
int tileBg = getResources().getDimensionPixelSize(R.dimen.qs_tile_background_size);
|
||||||
|
mFooterMarginStartHorizontal = getResources().getDimensionPixelSize(
|
||||||
|
R.dimen.qs_footer_horizontal_margin);
|
||||||
mVisualTilePadding = (int) ((tileSize - tileBg) / 2.0f);
|
mVisualTilePadding = (int) ((tileSize - tileBg) / 2.0f);
|
||||||
updatePadding();
|
updatePadding();
|
||||||
|
|
||||||
@@ -379,8 +439,15 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
|
|
||||||
protected void updatePadding() {
|
protected void updatePadding() {
|
||||||
final Resources res = mContext.getResources();
|
final Resources res = mContext.getResources();
|
||||||
|
int padding = res.getDimensionPixelSize(R.dimen.qs_panel_padding_top);
|
||||||
|
if (mUsingHorizontalLayout) {
|
||||||
|
// When using the horizontal layout, our space is quite constrained. We therefore
|
||||||
|
// reduce some of the padding on the top, which makes the brightness bar overlapp,
|
||||||
|
// but since that has naturally quite a bit of built in padding, that's fine.
|
||||||
|
padding = (int) (padding * 0.6f);
|
||||||
|
}
|
||||||
setPaddingRelative(getPaddingStart(),
|
setPaddingRelative(getPaddingStart(),
|
||||||
res.getDimensionPixelSize(R.dimen.qs_panel_padding_top),
|
padding,
|
||||||
getPaddingEnd(),
|
getPaddingEnd(),
|
||||||
res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom));
|
res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom));
|
||||||
}
|
}
|
||||||
@@ -388,10 +455,165 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
@Override
|
@Override
|
||||||
protected void onConfigurationChanged(Configuration newConfig) {
|
protected void onConfigurationChanged(Configuration newConfig) {
|
||||||
super.onConfigurationChanged(newConfig);
|
super.onConfigurationChanged(newConfig);
|
||||||
mFooter.onConfigurationChanged();
|
if (mSecurityFooter != null) {
|
||||||
|
mSecurityFooter.onConfigurationChanged();
|
||||||
|
}
|
||||||
updateResources();
|
updateResources();
|
||||||
|
|
||||||
updateBrightnessMirror();
|
updateBrightnessMirror();
|
||||||
|
|
||||||
|
if (newConfig.orientation != mLastOrientation) {
|
||||||
|
mLastOrientation = newConfig.orientation;
|
||||||
|
switchTileLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFinishInflate() {
|
||||||
|
super.onFinishInflate();
|
||||||
|
mFooter = findViewById(R.id.qs_footer);
|
||||||
|
switchTileLayout(true /* force */);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean switchTileLayout() {
|
||||||
|
return switchTileLayout(false /* force */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean switchTileLayout(boolean force) {
|
||||||
|
/** Whether or not the QuickQSPanel currently contains a media player. */
|
||||||
|
boolean horizontal = shouldUseHorizontalLayout();
|
||||||
|
if (horizontal != mUsingHorizontalLayout || force) {
|
||||||
|
mUsingHorizontalLayout = horizontal;
|
||||||
|
View visibleView = horizontal ? mHorizontalLinearLayout : (View) mRegularTileLayout;
|
||||||
|
View hiddenView = horizontal ? (View) mRegularTileLayout : mHorizontalLinearLayout;
|
||||||
|
ViewGroup newParent = horizontal ? mHorizontalContentContainer : this;
|
||||||
|
QSTileLayout newLayout = horizontal ? mHorizontalTileLayout : mRegularTileLayout;
|
||||||
|
if (hiddenView != null &&
|
||||||
|
(mRegularTileLayout != mHorizontalTileLayout ||
|
||||||
|
hiddenView != mRegularTileLayout)) {
|
||||||
|
// Only hide the view if the horizontal and the regular view are different,
|
||||||
|
// otherwise its reattached.
|
||||||
|
hiddenView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
visibleView.setVisibility(View.VISIBLE);
|
||||||
|
switchAllContentToParent(newParent, newLayout);
|
||||||
|
reAttachMediaHost();
|
||||||
|
if (mTileLayout != null) {
|
||||||
|
mTileLayout.setListening(false);
|
||||||
|
for (TileRecord record : mRecords) {
|
||||||
|
mTileLayout.removeTile(record);
|
||||||
|
record.tile.removeCallback(record.callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mTileLayout = newLayout;
|
||||||
|
if (mHost != null) setTiles(mHost.getTiles());
|
||||||
|
newLayout.setListening(mListening);
|
||||||
|
if (needsDynamicRowsAndColumns()) {
|
||||||
|
newLayout.setMinRows(horizontal ? 2 : 1);
|
||||||
|
// Let's use 3 columns to match the current layout
|
||||||
|
newLayout.setMaxColumns(horizontal ? 3 : TileLayout.NO_MAX_COLUMNS);
|
||||||
|
}
|
||||||
|
updateTileLayoutMargins();
|
||||||
|
updateFooterMargin();
|
||||||
|
updateMediaHostContentMargins();
|
||||||
|
updateHorizontalLinearLayoutMargins();
|
||||||
|
updatePadding();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateHorizontalLinearLayoutMargins() {
|
||||||
|
if (mHorizontalLinearLayout != null && !displayMediaMarginsOnMedia()) {
|
||||||
|
LayoutParams lp = (LayoutParams) mHorizontalLinearLayout.getLayoutParams();
|
||||||
|
lp.bottomMargin = mMediaTotalBottomMargin - getPaddingBottom();
|
||||||
|
mHorizontalLinearLayout.setLayoutParams(lp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the margin bottom of the media view should be on the media host or false
|
||||||
|
* if they should be on the HorizontalLinearLayout. Returning {@code false} is useful
|
||||||
|
* to visually center the tiles in the Media view, which doesn't work when the
|
||||||
|
* expanded panel actually scrolls.
|
||||||
|
*/
|
||||||
|
protected boolean displayMediaMarginsOnMedia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean needsDynamicRowsAndColumns() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchAllContentToParent(ViewGroup parent, QSTileLayout newLayout) {
|
||||||
|
int index = parent == this ? mMovableContentStartIndex : 0;
|
||||||
|
|
||||||
|
// Let's first move the tileLayout to the new parent, since that should come first.
|
||||||
|
switchToParent((View) newLayout, parent, index);
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (mSecurityFooter != null) {
|
||||||
|
View view = mSecurityFooter.getView();
|
||||||
|
LinearLayout.LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
|
||||||
|
if (mUsingHorizontalLayout && mHeaderContainer != null) {
|
||||||
|
// Adding the security view to the header, that enables us to avoid scrolling
|
||||||
|
layoutParams.width = 0;
|
||||||
|
layoutParams.weight = 1.6f;
|
||||||
|
switchToParent(view, mHeaderContainer, 1 /* always in second place */);
|
||||||
|
} else {
|
||||||
|
layoutParams.width = LayoutParams.WRAP_CONTENT;
|
||||||
|
layoutParams.weight = 0;
|
||||||
|
switchToParent(view, parent, index);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
view.setLayoutParams(layoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFooter != null) {
|
||||||
|
// Then the footer with the settings
|
||||||
|
switchToParent(mFooter, parent, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchToParent(View child, ViewGroup parent, int index) {
|
||||||
|
ViewGroup currentParent = (ViewGroup) child.getParent();
|
||||||
|
if (currentParent != parent || currentParent.indexOfChild(child) != index) {
|
||||||
|
if (currentParent != null) {
|
||||||
|
currentParent.removeView(child);
|
||||||
|
}
|
||||||
|
parent.addView(child, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldUseHorizontalLayout() {
|
||||||
|
return mUsingMediaPlayer && mMediaHost.getVisible()
|
||||||
|
&& getResources().getConfiguration().orientation
|
||||||
|
== Configuration.ORIENTATION_LANDSCAPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reAttachMediaHost() {
|
||||||
|
if (!mUsingMediaPlayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean horizontal = shouldUseHorizontalLayout();
|
||||||
|
ViewGroup host = mMediaHost.getHostView();
|
||||||
|
ViewGroup newParent = horizontal ? mHorizontalLinearLayout : this;
|
||||||
|
ViewGroup currentParent = (ViewGroup) host.getParent();
|
||||||
|
if (currentParent != newParent) {
|
||||||
|
if (currentParent != null) {
|
||||||
|
currentParent.removeView(host);
|
||||||
|
}
|
||||||
|
newParent.addView(host);
|
||||||
|
LinearLayout.LayoutParams layoutParams = (LayoutParams) host.getLayoutParams();
|
||||||
|
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||||
|
layoutParams.width = horizontal ? 0 : ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
|
layoutParams.weight = horizontal ? 1.2f : 0;
|
||||||
|
// Add any bottom margin, such that the total spacing is correct. This is only
|
||||||
|
// necessary if the view isn't horizontal, since otherwise the padding is
|
||||||
|
// carried in the parent of this view (to ensure correct vertical alignment)
|
||||||
|
layoutParams.bottomMargin = !horizontal || displayMediaMarginsOnMedia()
|
||||||
|
? mMediaTotalBottomMargin - getPaddingBottom() : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateBrightnessMirror() {
|
public void updateBrightnessMirror() {
|
||||||
@@ -457,13 +679,18 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
|
|
||||||
public void setListening(boolean listening, boolean expanded) {
|
public void setListening(boolean listening, boolean expanded) {
|
||||||
setListening(listening && expanded);
|
setListening(listening && expanded);
|
||||||
getFooter().setListening(listening);
|
if (mSecurityFooter != null) {
|
||||||
|
mSecurityFooter.setListening(listening);
|
||||||
|
}
|
||||||
// Set the listening as soon as the QS fragment starts listening regardless of the expansion,
|
// Set the listening as soon as the QS fragment starts listening regardless of the expansion,
|
||||||
// so it will update the current brightness before the slider is visible.
|
// so it will update the current brightness before the slider is visible.
|
||||||
setBrightnessListening(listening);
|
setBrightnessListening(listening);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBrightnessListening(boolean listening) {
|
public void setBrightnessListening(boolean listening) {
|
||||||
|
if (mBrightnessController == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (listening) {
|
if (listening) {
|
||||||
mBrightnessController.registerCallbacks();
|
mBrightnessController.registerCallbacks();
|
||||||
} else {
|
} else {
|
||||||
@@ -472,11 +699,15 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void refreshAllTiles() {
|
public void refreshAllTiles() {
|
||||||
mBrightnessController.checkRestrictionAndSetEnabled();
|
if (mBrightnessController != null) {
|
||||||
|
mBrightnessController.checkRestrictionAndSetEnabled();
|
||||||
|
}
|
||||||
for (TileRecord r : mRecords) {
|
for (TileRecord r : mRecords) {
|
||||||
r.tile.refreshState();
|
r.tile.refreshState();
|
||||||
}
|
}
|
||||||
mFooter.refreshState();
|
if (mSecurityFooter != null) {
|
||||||
|
mSecurityFooter.refreshState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showDetailAdapter(boolean show, DetailAdapter adapter, int[] locationInWindow) {
|
public void showDetailAdapter(boolean show, DetailAdapter adapter, int[] locationInWindow) {
|
||||||
@@ -728,12 +959,15 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public QSSecurityFooter getFooter() {
|
@Nullable
|
||||||
return mFooter;
|
public QSSecurityFooter getSecurityFooter() {
|
||||||
|
return mSecurityFooter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showDeviceMonitoringDialog() {
|
public void showDeviceMonitoringDialog() {
|
||||||
mFooter.showDeviceMonitoringDialog();
|
if (mSecurityFooter != null) {
|
||||||
|
mSecurityFooter.showDeviceMonitoringDialog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContentMargins(int startMargin, int endMargin) {
|
public void setContentMargins(int startMargin, int endMargin) {
|
||||||
@@ -744,6 +978,24 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
updateTileLayoutMargins(mContentMarginStart - mVisualTilePadding,
|
updateTileLayoutMargins(mContentMarginStart - mVisualTilePadding,
|
||||||
mContentMarginEnd - mVisualTilePadding);
|
mContentMarginEnd - mVisualTilePadding);
|
||||||
updateMediaHostContentMargins();
|
updateMediaHostContentMargins();
|
||||||
|
updateFooterMargin();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateFooterMargin() {
|
||||||
|
if (mFooter != null) {
|
||||||
|
int footerMargin = 0;
|
||||||
|
int indicatorMargin = 0;
|
||||||
|
if (mUsingHorizontalLayout) {
|
||||||
|
footerMargin = mFooterMarginStartHorizontal;
|
||||||
|
indicatorMargin = footerMargin - mVisualMarginEnd;
|
||||||
|
}
|
||||||
|
updateMargins(mFooter, footerMargin, 0);
|
||||||
|
// The page indicator isn't centered anymore because of the visual positioning.
|
||||||
|
// Let's fix it by adding some margin
|
||||||
|
if (mFooterPageIndicator != null) {
|
||||||
|
updateMargins(mFooterPageIndicator, 0, indicatorMargin);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -754,16 +1006,30 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
* @param visualMarginEnd the visual end margin of the tile, adjusted for local insets
|
* @param visualMarginEnd the visual end margin of the tile, adjusted for local insets
|
||||||
* to the tile. This can be set on a tileLayout
|
* to the tile. This can be set on a tileLayout
|
||||||
*/
|
*/
|
||||||
protected void updateTileLayoutMargins(int visualMarginStart, int visualMarginEnd) {
|
private void updateTileLayoutMargins(int visualMarginStart, int visualMarginEnd) {
|
||||||
updateMargins((View) mTileLayout, visualMarginStart, visualMarginEnd);
|
mVisualMarginStart = visualMarginStart;
|
||||||
|
mVisualMarginEnd = visualMarginEnd;
|
||||||
|
updateTileLayoutMargins();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTileLayoutMargins() {
|
||||||
|
int marginEnd = mVisualMarginEnd;
|
||||||
|
if (mUsingHorizontalLayout) {
|
||||||
|
marginEnd = 0;
|
||||||
|
}
|
||||||
|
updateMargins((View) mTileLayout, mVisualMarginStart, marginEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the margins of the media hosts
|
* Update the margins of the media hosts
|
||||||
*/
|
*/
|
||||||
protected void updateMediaHostContentMargins() {
|
protected void updateMediaHostContentMargins() {
|
||||||
if (mUsingMediaPlayer && mMediaHost != null) {
|
if (mUsingMediaPlayer) {
|
||||||
updateMargins(mMediaHost.getHostView(), mContentMarginStart, mContentMarginEnd);
|
int marginStart = mContentMarginStart;
|
||||||
|
if (mUsingHorizontalLayout) {
|
||||||
|
marginStart = 0;
|
||||||
|
}
|
||||||
|
updateMargins(mMediaHost.getHostView(), marginStart, mContentMarginEnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,6 +1051,13 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
return mMediaHost;
|
return mMediaHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the header container of quick settings.
|
||||||
|
*/
|
||||||
|
public void setHeaderContainer(@NonNull ViewGroup headerContainer) {
|
||||||
|
mHeaderContainer = headerContainer;
|
||||||
|
}
|
||||||
|
|
||||||
private class H extends Handler {
|
private class H extends Handler {
|
||||||
private static final int SHOW_DETAIL = 1;
|
private static final int SHOW_DETAIL = 1;
|
||||||
private static final int SET_TILE_VISIBILITY = 2;
|
private static final int SET_TILE_VISIBILITY = 2;
|
||||||
@@ -812,6 +1085,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected static class Record {
|
protected static class Record {
|
||||||
DetailAdapter detailAdapter;
|
DetailAdapter detailAdapter;
|
||||||
int x;
|
int x;
|
||||||
@@ -841,6 +1115,26 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
|||||||
|
|
||||||
void setListening(boolean listening);
|
void setListening(boolean listening);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the minimum number of rows to show
|
||||||
|
*
|
||||||
|
* @param minRows the minimum.
|
||||||
|
*/
|
||||||
|
default boolean setMinRows(int minRows) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the max number of collums to show
|
||||||
|
*
|
||||||
|
* @param maxColumns the maximum
|
||||||
|
*
|
||||||
|
* @return true if the number of visible columns has changed.
|
||||||
|
*/
|
||||||
|
default boolean setMaxColumns(int maxColumns) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
default void setExpansion(float expansion) {}
|
default void setExpansion(float expansion) {}
|
||||||
|
|
||||||
int getNumVisibleTiles();
|
int getNumVisibleTiles();
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import com.android.systemui.statusbar.policy.SecurityController;
|
|||||||
public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
|
public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
|
||||||
protected static final String TAG = "QSSecurityFooter";
|
protected static final String TAG = "QSSecurityFooter";
|
||||||
protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
private static final boolean DEBUG_FORCE_VISIBLE = false;
|
||||||
|
|
||||||
private final View mRootView;
|
private final View mRootView;
|
||||||
private final TextView mFooterText;
|
private final TextView mFooterText;
|
||||||
@@ -60,7 +61,6 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic
|
|||||||
private final SecurityController mSecurityController;
|
private final SecurityController mSecurityController;
|
||||||
private final ActivityStarter mActivityStarter;
|
private final ActivityStarter mActivityStarter;
|
||||||
private final Handler mMainHandler;
|
private final Handler mMainHandler;
|
||||||
private final View mDivider;
|
|
||||||
|
|
||||||
private final UserManager mUm;
|
private final UserManager mUm;
|
||||||
|
|
||||||
@@ -85,7 +85,6 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic
|
|||||||
mActivityStarter = Dependency.get(ActivityStarter.class);
|
mActivityStarter = Dependency.get(ActivityStarter.class);
|
||||||
mSecurityController = Dependency.get(SecurityController.class);
|
mSecurityController = Dependency.get(SecurityController.class);
|
||||||
mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
|
mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
|
||||||
mDivider = qsPanel == null ? null : qsPanel.getDivider();
|
|
||||||
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +176,7 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic
|
|||||||
boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
|
boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
|
||||||
String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
|
String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
|
||||||
CharSequence workProfileName) {
|
CharSequence workProfileName) {
|
||||||
if (isDeviceManaged) {
|
if (isDeviceManaged || DEBUG_FORCE_VISIBLE) {
|
||||||
if (hasCACerts || hasCACertsInWorkProfile || isNetworkLoggingEnabled) {
|
if (hasCACerts || hasCACertsInWorkProfile || isNetworkLoggingEnabled) {
|
||||||
if (organizationName == null) {
|
if (organizationName == null) {
|
||||||
return mContext.getString(
|
return mContext.getString(
|
||||||
@@ -451,8 +450,7 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic
|
|||||||
if (mFooterTextContent != null) {
|
if (mFooterTextContent != null) {
|
||||||
mFooterText.setText(mFooterTextContent);
|
mFooterText.setText(mFooterTextContent);
|
||||||
}
|
}
|
||||||
mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
|
mRootView.setVisibility(mIsVisible || DEBUG_FORCE_VISIBLE ? View.VISIBLE : View.GONE);
|
||||||
if (mDivider != null) mDivider.setVisibility(mIsVisible ? View.GONE : View.VISIBLE);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import android.graphics.Rect;
|
|||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import com.android.internal.logging.UiEventLogger;
|
import com.android.internal.logging.UiEventLogger;
|
||||||
@@ -61,15 +60,7 @@ public class QuickQSPanel extends QSPanel {
|
|||||||
private boolean mDisabledByPolicy;
|
private boolean mDisabledByPolicy;
|
||||||
private int mMaxTiles;
|
private int mMaxTiles;
|
||||||
protected QSPanel mFullPanel;
|
protected QSPanel mFullPanel;
|
||||||
/** Whether or not the QuickQSPanel currently contains a media player. */
|
|
||||||
private boolean mShowHorizontalTileLayout;
|
|
||||||
private LinearLayout mHorizontalLinearLayout;
|
|
||||||
|
|
||||||
// Only used with media
|
|
||||||
private QSTileLayout mHorizontalTileLayout;
|
|
||||||
private QSTileLayout mRegularTileLayout;
|
|
||||||
private int mLastOrientation = -1;
|
|
||||||
private int mMediaBottomMargin;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public QuickQSPanel(
|
public QuickQSPanel(
|
||||||
@@ -82,59 +73,8 @@ public class QuickQSPanel extends QSPanel {
|
|||||||
UiEventLogger uiEventLogger
|
UiEventLogger uiEventLogger
|
||||||
) {
|
) {
|
||||||
super(context, attrs, dumpManager, broadcastDispatcher, qsLogger, mediaHost, uiEventLogger);
|
super(context, attrs, dumpManager, broadcastDispatcher, qsLogger, mediaHost, uiEventLogger);
|
||||||
if (mFooter != null) {
|
sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
|
||||||
removeView(mFooter.getView());
|
applyBottomMargin((View) mRegularTileLayout);
|
||||||
}
|
|
||||||
if (mTileLayout != null) {
|
|
||||||
for (int i = 0; i < mRecords.size(); i++) {
|
|
||||||
mTileLayout.removeTile(mRecords.get(i));
|
|
||||||
}
|
|
||||||
removeView((View) mTileLayout);
|
|
||||||
}
|
|
||||||
mMediaBottomMargin = getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.quick_settings_media_extra_bottom_margin);
|
|
||||||
if (mUsingMediaPlayer) {
|
|
||||||
mHorizontalLinearLayout = new LinearLayout(mContext);
|
|
||||||
mHorizontalLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
|
|
||||||
mHorizontalLinearLayout.setClipChildren(false);
|
|
||||||
mHorizontalLinearLayout.setClipToPadding(false);
|
|
||||||
|
|
||||||
DoubleLineTileLayout horizontalTileLayout = new DoubleLineTileLayout(context,
|
|
||||||
mUiEventLogger);
|
|
||||||
horizontalTileLayout.setPaddingRelative(
|
|
||||||
horizontalTileLayout.getPaddingStart(),
|
|
||||||
horizontalTileLayout.getPaddingTop(),
|
|
||||||
horizontalTileLayout.getPaddingEnd(),
|
|
||||||
mContext.getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.qqs_horizonal_tile_padding_bottom));
|
|
||||||
mHorizontalTileLayout = horizontalTileLayout;
|
|
||||||
mRegularTileLayout = new HeaderTileLayout(context, mUiEventLogger);
|
|
||||||
LayoutParams lp = new LayoutParams(0, LayoutParams.WRAP_CONTENT, 1);
|
|
||||||
int marginSize = (int) mContext.getResources().getDimension(R.dimen.qqs_media_spacing);
|
|
||||||
lp.setMarginStart(0);
|
|
||||||
lp.setMarginEnd(marginSize);
|
|
||||||
lp.gravity = Gravity.CENTER_VERTICAL;
|
|
||||||
mHorizontalLinearLayout.addView((View) mHorizontalTileLayout, lp);
|
|
||||||
|
|
||||||
sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
|
|
||||||
|
|
||||||
boolean useHorizontal = shouldUseHorizontalTileLayout();
|
|
||||||
mTileLayout = useHorizontal ? mHorizontalTileLayout : mRegularTileLayout;
|
|
||||||
mTileLayout.setListening(mListening);
|
|
||||||
addView(mHorizontalLinearLayout, 0 /* Between brightness and footer */);
|
|
||||||
((View) mRegularTileLayout).setVisibility(!useHorizontal ? View.VISIBLE : View.GONE);
|
|
||||||
mHorizontalLinearLayout.setVisibility(useHorizontal ? View.VISIBLE : View.GONE);
|
|
||||||
addView((View) mRegularTileLayout, 0);
|
|
||||||
super.setPadding(0, 0, 0, 0);
|
|
||||||
applyBottomMargin((View) mRegularTileLayout);
|
|
||||||
} else {
|
|
||||||
sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
|
|
||||||
mTileLayout = new HeaderTileLayout(context, mUiEventLogger);
|
|
||||||
mTileLayout.setListening(mListening);
|
|
||||||
addView((View) mTileLayout, 0 /* Between brightness and footer */);
|
|
||||||
super.setPadding(0, 0, 0, 0);
|
|
||||||
applyBottomMargin((View) mTileLayout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyBottomMargin(View view) {
|
private void applyBottomMargin(View view) {
|
||||||
@@ -144,48 +84,42 @@ public class QuickQSPanel extends QSPanel {
|
|||||||
view.setLayoutParams(layoutParams);
|
view.setLayoutParams(layoutParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reAttachMediaHost() {
|
@Override
|
||||||
if (mMediaHost == null) {
|
protected void addSecurityFooter() {
|
||||||
return;
|
// No footer needed
|
||||||
}
|
|
||||||
boolean horizontal = shouldUseHorizontalTileLayout();
|
|
||||||
ViewGroup host = mMediaHost.getHostView();
|
|
||||||
ViewGroup newParent = horizontal ? mHorizontalLinearLayout : this;
|
|
||||||
ViewGroup currentParent = (ViewGroup) host.getParent();
|
|
||||||
if (currentParent != newParent) {
|
|
||||||
if (currentParent != null) {
|
|
||||||
currentParent.removeView(host);
|
|
||||||
}
|
|
||||||
newParent.addView(host);
|
|
||||||
LinearLayout.LayoutParams layoutParams = (LayoutParams) host.getLayoutParams();
|
|
||||||
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
|
||||||
layoutParams.width = horizontal ? 0 : ViewGroup.LayoutParams.MATCH_PARENT;
|
|
||||||
layoutParams.weight = horizontal ? 1.5f : 0;
|
|
||||||
layoutParams.bottomMargin = mMediaBottomMargin;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addMediaHostView() {
|
protected void addViewsAboveTiles() {
|
||||||
mMediaHost.setVisibleChangedListener((visible) -> {
|
// Nothing to add above the tiles
|
||||||
switchTileLayout();
|
}
|
||||||
return null;
|
|
||||||
});
|
@Override
|
||||||
|
protected TileLayout createRegularTileLayout() {
|
||||||
|
return new QuickQSPanel.HeaderTileLayout(mContext, mUiEventLogger);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected QSTileLayout createHorizontalTileLayout() {
|
||||||
|
return new DoubleLineTileLayout(mContext, mUiEventLogger);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initMediaHostState() {
|
||||||
mMediaHost.setExpansion(0.0f);
|
mMediaHost.setExpansion(0.0f);
|
||||||
mMediaHost.setShowsOnlyActiveMedia(true);
|
mMediaHost.setShowsOnlyActiveMedia(true);
|
||||||
mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
|
mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
|
||||||
reAttachMediaHost();
|
|
||||||
updateMediaHostContentMargins();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateTileLayoutMargins(int visualMarginStart, int visualMarginEnd) {
|
protected boolean needsDynamicRowsAndColumns() {
|
||||||
if (mUsingMediaPlayer) {
|
return false; // QQS always have the same layout
|
||||||
updateMargins((View) mRegularTileLayout, visualMarginStart, visualMarginEnd);
|
}
|
||||||
updateMargins((View) mHorizontalTileLayout, visualMarginStart, 0);
|
|
||||||
} else {
|
@Override
|
||||||
updateMargins((View) mTileLayout, visualMarginStart, visualMarginEnd);
|
protected boolean displayMediaMarginsOnMedia() {
|
||||||
}
|
// Margins should be on the container to visually center the view
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -193,10 +127,6 @@ public class QuickQSPanel extends QSPanel {
|
|||||||
// QS Panel is setting a top padding by default, which we don't need.
|
// QS Panel is setting a top padding by default, which we don't need.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addDivider() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAttachedToWindow() {
|
protected void onAttachedToWindow() {
|
||||||
super.onAttachedToWindow();
|
super.onAttachedToWindow();
|
||||||
@@ -236,60 +166,6 @@ public class QuickQSPanel extends QSPanel {
|
|||||||
super.drawTile(r, state);
|
super.drawTile(r, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onConfigurationChanged(Configuration newConfig) {
|
|
||||||
super.onConfigurationChanged(newConfig);
|
|
||||||
if (newConfig.orientation != mLastOrientation) {
|
|
||||||
mLastOrientation = newConfig.orientation;
|
|
||||||
switchTileLayout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean switchTileLayout() {
|
|
||||||
if (!mUsingMediaPlayer) return false;
|
|
||||||
mShowHorizontalTileLayout = shouldUseHorizontalTileLayout();
|
|
||||||
if (mShowHorizontalTileLayout && mHorizontalLinearLayout.getVisibility() == View.GONE) {
|
|
||||||
mHorizontalLinearLayout.setVisibility(View.VISIBLE);
|
|
||||||
((View) mRegularTileLayout).setVisibility(View.GONE);
|
|
||||||
mTileLayout.setListening(false);
|
|
||||||
for (TileRecord record : mRecords) {
|
|
||||||
mTileLayout.removeTile(record);
|
|
||||||
record.tile.removeCallback(record.callback);
|
|
||||||
}
|
|
||||||
mTileLayout = mHorizontalTileLayout;
|
|
||||||
if (mHost != null) setTiles(mHost.getTiles());
|
|
||||||
mTileLayout.setListening(mListening);
|
|
||||||
reAttachMediaHost();
|
|
||||||
return true;
|
|
||||||
} else if (!mShowHorizontalTileLayout
|
|
||||||
&& mHorizontalLinearLayout.getVisibility() == View.VISIBLE) {
|
|
||||||
mHorizontalLinearLayout.setVisibility(View.GONE);
|
|
||||||
((View) mRegularTileLayout).setVisibility(View.VISIBLE);
|
|
||||||
mTileLayout.setListening(false);
|
|
||||||
for (TileRecord record : mRecords) {
|
|
||||||
mTileLayout.removeTile(record);
|
|
||||||
record.tile.removeCallback(record.callback);
|
|
||||||
}
|
|
||||||
mTileLayout = mRegularTileLayout;
|
|
||||||
if (mHost != null) setTiles(mHost.getTiles());
|
|
||||||
mTileLayout.setListening(mListening);
|
|
||||||
reAttachMediaHost();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean shouldUseHorizontalTileLayout() {
|
|
||||||
return mMediaHost.getVisible()
|
|
||||||
&& getResources().getConfiguration().orientation
|
|
||||||
== Configuration.ORIENTATION_LANDSCAPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns true if this panel currently uses a horizontal tile layout. */
|
|
||||||
public boolean usesHorizontalLayout() {
|
|
||||||
return mShowHorizontalTileLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHost(QSTileHost host, QSCustomizer customizer) {
|
public void setHost(QSTileHost host, QSCustomizer customizer) {
|
||||||
super.setHost(host, customizer);
|
super.setHost(host, customizer);
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ import android.service.notification.ZenModeConfig;
|
|||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.MathUtils;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.DisplayCutout;
|
import android.view.DisplayCutout;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@@ -55,6 +55,7 @@ import androidx.lifecycle.LifecycleRegistry;
|
|||||||
import com.android.settingslib.Utils;
|
import com.android.settingslib.Utils;
|
||||||
import com.android.systemui.BatteryMeterView;
|
import com.android.systemui.BatteryMeterView;
|
||||||
import com.android.systemui.DualToneHandler;
|
import com.android.systemui.DualToneHandler;
|
||||||
|
import com.android.systemui.Interpolators;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher;
|
import com.android.systemui.plugins.DarkIconDispatcher;
|
||||||
@@ -149,6 +150,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements
|
|||||||
private int mWaterfallTopInset;
|
private int mWaterfallTopInset;
|
||||||
private int mCutOutPaddingLeft;
|
private int mCutOutPaddingLeft;
|
||||||
private int mCutOutPaddingRight;
|
private int mCutOutPaddingRight;
|
||||||
|
private float mExpandedHeaderAlpha = 1.0f;
|
||||||
|
private float mKeyguardExpansionFraction;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
|
public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
|
||||||
@@ -356,7 +359,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
|
|||||||
|
|
||||||
private void updateHeaderTextContainerAlphaAnimator() {
|
private void updateHeaderTextContainerAlphaAnimator() {
|
||||||
mHeaderTextContainerAlphaAnimator = new TouchAnimator.Builder()
|
mHeaderTextContainerAlphaAnimator = new TouchAnimator.Builder()
|
||||||
.addFloat(mHeaderTextContainerView, "alpha", 0, 0, 1)
|
.addFloat(mHeaderTextContainerView, "alpha", 0, 0, mExpandedHeaderAlpha)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,6 +406,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
|
|||||||
updateResources();
|
updateResources();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mKeyguardExpansionFraction = keyguardExpansionFraction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disable(int state1, int state2, boolean animate) {
|
public void disable(int state1, int state2, boolean animate) {
|
||||||
@@ -596,4 +600,22 @@ public class QuickStatusBarHeader extends RelativeLayout implements
|
|||||||
}
|
}
|
||||||
updateClockPadding();
|
updateClockPadding();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setExpandedScrollAmount(int scrollY) {
|
||||||
|
// The scrolling of the expanded qs has changed. Since the header text isn't part of it,
|
||||||
|
// but would overlap content, we're fading it out.
|
||||||
|
float newAlpha = 1.0f;
|
||||||
|
if (mHeaderTextContainerView.getHeight() > 0) {
|
||||||
|
newAlpha = MathUtils.map(0, mHeaderTextContainerView.getHeight() / 2.0f, 1.0f, 0.0f,
|
||||||
|
scrollY);
|
||||||
|
newAlpha = Interpolators.ALPHA_OUT.getInterpolation(newAlpha);
|
||||||
|
}
|
||||||
|
mHeaderTextContainerView.setScrollY(scrollY);
|
||||||
|
if (newAlpha != mExpandedHeaderAlpha) {
|
||||||
|
mExpandedHeaderAlpha = newAlpha;
|
||||||
|
mHeaderTextContainerView.setAlpha(MathUtils.lerp(0.0f, mExpandedHeaderAlpha,
|
||||||
|
mKeyguardExpansionFraction));
|
||||||
|
updateHeaderTextContainerAlphaAnimator();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
public class TileLayout extends ViewGroup implements QSTileLayout {
|
public class TileLayout extends ViewGroup implements QSTileLayout {
|
||||||
|
|
||||||
|
public static final int NO_MAX_COLUMNS = 100;
|
||||||
private static final float TILE_ASPECT = 1.2f;
|
private static final float TILE_ASPECT = 1.2f;
|
||||||
|
|
||||||
private static final String TAG = "TileLayout";
|
private static final String TAG = "TileLayout";
|
||||||
@@ -36,6 +37,9 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
|
|||||||
|
|
||||||
// Prototyping with less rows
|
// Prototyping with less rows
|
||||||
private final boolean mLessRows;
|
private final boolean mLessRows;
|
||||||
|
private int mMinRows = 1;
|
||||||
|
private int mMaxColumns = NO_MAX_COLUMNS;
|
||||||
|
private int mResourceColumns;
|
||||||
|
|
||||||
public TileLayout(Context context) {
|
public TileLayout(Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
@@ -64,6 +68,22 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setMinRows(int minRows) {
|
||||||
|
if (mMinRows != minRows) {
|
||||||
|
mMinRows = minRows;
|
||||||
|
updateResources();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setMaxColumns(int maxColumns) {
|
||||||
|
mMaxColumns = maxColumns;
|
||||||
|
return updateColumns();
|
||||||
|
}
|
||||||
|
|
||||||
public void addTile(TileRecord tile) {
|
public void addTile(TileRecord tile) {
|
||||||
mRecords.add(tile);
|
mRecords.add(tile);
|
||||||
tile.tile.setListening(this, mListening);
|
tile.tile.setListening(this, mListening);
|
||||||
@@ -91,21 +111,26 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
|
|||||||
|
|
||||||
public boolean updateResources() {
|
public boolean updateResources() {
|
||||||
final Resources res = mContext.getResources();
|
final Resources res = mContext.getResources();
|
||||||
final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
|
mResourceColumns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
|
||||||
mCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
|
mCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
|
||||||
mCellMarginHorizontal = res.getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal);
|
mCellMarginHorizontal = res.getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal);
|
||||||
mCellMarginVertical= res.getDimensionPixelSize(R.dimen.qs_tile_margin_vertical);
|
mCellMarginVertical= res.getDimensionPixelSize(R.dimen.qs_tile_margin_vertical);
|
||||||
mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
|
mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
|
||||||
mMaxAllowedRows = Math.max(1, getResources().getInteger(R.integer.quick_settings_max_rows));
|
mMaxAllowedRows = Math.max(1, getResources().getInteger(R.integer.quick_settings_max_rows));
|
||||||
if (mLessRows) mMaxAllowedRows = Math.max(1, mMaxAllowedRows - 1);
|
if (mLessRows) mMaxAllowedRows = Math.max(mMinRows, mMaxAllowedRows - 1);
|
||||||
if (mColumns != columns) {
|
if (updateColumns()) {
|
||||||
mColumns = columns;
|
|
||||||
requestLayout();
|
requestLayout();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean updateColumns() {
|
||||||
|
int oldColumns = mColumns;
|
||||||
|
mColumns = Math.min(mResourceColumns, mMaxColumns);
|
||||||
|
return oldColumns != mColumns;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
// If called with AT_MOST, it will limit the number of rows. If called with UNSPECIFIED
|
// If called with AT_MOST, it will limit the number of rows. If called with UNSPECIFIED
|
||||||
@@ -142,18 +167,19 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
|
|||||||
* Determines the maximum number of rows that can be shown based on height. Clips at a minimum
|
* Determines the maximum number of rows that can be shown based on height. Clips at a minimum
|
||||||
* of 1 and a maximum of mMaxAllowedRows.
|
* of 1 and a maximum of mMaxAllowedRows.
|
||||||
*
|
*
|
||||||
* @param heightMeasureSpec Available height.
|
* @param allowedHeight The height this view has visually available
|
||||||
* @param tilesCount Upper limit on the number of tiles to show. to prevent empty rows.
|
* @param tilesCount Upper limit on the number of tiles to show. to prevent empty rows.
|
||||||
*/
|
*/
|
||||||
public boolean updateMaxRows(int heightMeasureSpec, int tilesCount) {
|
public boolean updateMaxRows(int allowedHeight, int tilesCount) {
|
||||||
final int availableHeight = MeasureSpec.getSize(heightMeasureSpec) - mCellMarginTop
|
final int availableHeight = allowedHeight - mCellMarginTop
|
||||||
|
// Add the cell margin in order to divide easily by the height + the margin below
|
||||||
+ mCellMarginVertical;
|
+ mCellMarginVertical;
|
||||||
final int previousRows = mRows;
|
final int previousRows = mRows;
|
||||||
mRows = availableHeight / (mCellHeight + mCellMarginVertical);
|
mRows = availableHeight / (mCellHeight + mCellMarginVertical);
|
||||||
if (mRows >= mMaxAllowedRows) {
|
if (mRows < mMinRows) {
|
||||||
|
mRows = mMinRows;
|
||||||
|
} else if (mRows >= mMaxAllowedRows) {
|
||||||
mRows = mMaxAllowedRows;
|
mRows = mMaxAllowedRows;
|
||||||
} else if (mRows <= 1) {
|
|
||||||
mRows = 1;
|
|
||||||
}
|
}
|
||||||
if (mRows > (tilesCount + mColumns - 1) / mColumns) {
|
if (mRows > (tilesCount + mColumns - 1) / mColumns) {
|
||||||
mRows = (tilesCount + mColumns - 1) / mColumns;
|
mRows = (tilesCount + mColumns - 1) / mColumns;
|
||||||
|
|||||||
@@ -3071,7 +3071,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
return new TouchHandler() {
|
return new TouchHandler() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
public boolean onInterceptTouchEvent(MotionEvent event) {
|
||||||
if (mBlockTouches || mQsFullyExpanded && mQs.onInterceptTouchEvent(event)) {
|
if (mBlockTouches || mQsFullyExpanded && mQs.disallowPanelTouches()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
initDownStates(event);
|
initDownStates(event);
|
||||||
@@ -3098,7 +3098,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouch(View v, MotionEvent event) {
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
if (mBlockTouches || (mQs != null && mQs.isCustomizing())) {
|
if (mBlockTouches || (mQsFullyExpanded && mQs != null
|
||||||
|
&& mQs.disallowPanelTouches())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basically a normal linear layout but doesn't grow its children with weight 1 even when its
|
||||||
|
* measured with exactly.
|
||||||
|
*/
|
||||||
|
class NeverExactlyLinearLayout @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||||
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
|
|
||||||
|
val (widthExactly, usedWidthSpec, width) = getNonExactlyMeasureSpec(widthMeasureSpec)
|
||||||
|
val (heightExactly, usedHeightSpec, height) = getNonExactlyMeasureSpec(heightMeasureSpec)
|
||||||
|
|
||||||
|
super.onMeasure(usedWidthSpec, usedHeightSpec)
|
||||||
|
if (widthExactly || heightExactly) {
|
||||||
|
val newWidth = if (widthExactly) width else measuredWidth
|
||||||
|
val newHeight = if (heightExactly) height else measuredHeight
|
||||||
|
setMeasuredDimension(newWidth, newHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a measurespec that's not exactly
|
||||||
|
*
|
||||||
|
* @return a triple, where we return 1. if this was exactly, 2. the new measurespec, 3. the size
|
||||||
|
* of the measurespec
|
||||||
|
*/
|
||||||
|
private fun getNonExactlyMeasureSpec(measureSpec: Int): Triple<Boolean, Int, Int> {
|
||||||
|
var newSpec = measureSpec
|
||||||
|
val isExactly = MeasureSpec.getMode(measureSpec) == MeasureSpec.EXACTLY
|
||||||
|
val size = MeasureSpec.getSize(measureSpec)
|
||||||
|
if (isExactly) {
|
||||||
|
newSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST)
|
||||||
|
}
|
||||||
|
return Triple(isExactly, newSpec, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,6 +51,7 @@ import com.android.systemui.qs.logging.QSLogger;
|
|||||||
import com.android.systemui.qs.tileimpl.QSTileImpl;
|
import com.android.systemui.qs.tileimpl.QSTileImpl;
|
||||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||||
import com.android.systemui.statusbar.policy.SecurityController;
|
import com.android.systemui.statusbar.policy.SecurityController;
|
||||||
|
import com.android.systemui.util.animation.UniqueObjectHostView;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -108,12 +109,14 @@ public class QSPanelTest extends SysuiTestCase {
|
|||||||
mDependency.injectMockDependency(SecurityController.class);
|
mDependency.injectMockDependency(SecurityController.class);
|
||||||
mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
|
mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
|
||||||
mContext.addMockSystemService(Context.USER_SERVICE, mock(UserManager.class));
|
mContext.addMockSystemService(Context.USER_SERVICE, mock(UserManager.class));
|
||||||
|
when(mMediaHost.getHostView()).thenReturn(new UniqueObjectHostView(getContext()));
|
||||||
|
|
||||||
mUiEventLogger = new UiEventLoggerFake();
|
mUiEventLogger = new UiEventLoggerFake();
|
||||||
mTestableLooper.runWithLooper(() -> {
|
mTestableLooper.runWithLooper(() -> {
|
||||||
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
|
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
|
||||||
mQsPanel = new QSPanel(mContext, null, mDumpManager, mBroadcastDispatcher,
|
mQsPanel = new QSPanel(mContext, null, mDumpManager, mBroadcastDispatcher,
|
||||||
mQSLogger, mMediaHost, mUiEventLogger);
|
mQSLogger, mMediaHost, mUiEventLogger);
|
||||||
|
mQsPanel.onFinishInflate();
|
||||||
// Provides a parent with non-zero size for QSPanel
|
// Provides a parent with non-zero size for QSPanel
|
||||||
mParentView = new FrameLayout(mContext);
|
mParentView = new FrameLayout(mContext);
|
||||||
mParentView.addView(mQsPanel);
|
mParentView.addView(mQsPanel);
|
||||||
|
|||||||
Reference in New Issue
Block a user