Merge "Controls UI - Support detail panels" into rvc-dev am: 47709f0e8b am: 091d515656

Change-Id: I6a041696fdfd9ce99223de8a9f3fbabe241e14ba
This commit is contained in:
TreeHugger Robot
2020-04-10 21:16:01 +00:00
committed by Automerger Merge Worker
12 changed files with 312 additions and 73 deletions

View File

@@ -0,0 +1,26 @@
<?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
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@*android:anim/accelerate_decelerate_interpolator"
android:zAdjustment="top">
<translate android:fromYDelta="100%"
android:toYDelta="0"
android:startOffset="@android:integer/config_shortAnimTime"
android:duration="@*android:integer/config_mediumAnimTime"/>
</set>

View File

@@ -0,0 +1,25 @@
<?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
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@*android:anim/accelerate_interpolator"
android:zAdjustment="top">
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromYDelta="0"
android:toYDelta="100%"
android:duration="@*android:integer/config_shortAnimTime" />
</set>

View File

@@ -0,0 +1,22 @@
<?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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?android:attr/colorPrimaryDark" />
<corners
android:topLeftRadius="?android:attr/dialogCornerRadius"
android:topRightRadius="?android:attr/dialogCornerRadius" />
</shape>

View File

@@ -15,9 +15,76 @@
limitations under the License. limitations under the License.
--> -->
<FrameLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/control_detail_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/controls_activity_view_top_offset"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="10dp">
<ImageView
android:id="@+id/control_detail_close"
android:contentDescription="@string/accessibility_desc_close"
android:src="@drawable/ic_close"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:tint="@color/control_primary_text"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp" />
<Space
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="1dp" />
<ImageView
android:id="@+id/control_detail_open_in_app"
android:src="@drawable/ic_open_in_new"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:tint="@color/control_primary_text"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/controls_activity_view_top_padding"
android:paddingLeft="@dimen/controls_activity_view_side_padding"
android:paddingRight="@dimen/controls_activity_view_side_padding"
android:background="@drawable/rounded_bg_top"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.ControlDialog"
android:clickable="false"
android:focusable="false"
android:maxLines="1"
android:ellipsize="end" />
<TextView
android:id="@+id/subtitle"
android:layout_marginTop="6dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.ControlDialog"
android:clickable="false"
android:focusable="false"
android:maxLines="1"
android:ellipsize="end" />
<FrameLayout
android:id="@+id/controls_activity_view" android:id="@+id/controls_activity_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="0dp"
android:layout_marginTop="10dp"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>

View File

@@ -1250,6 +1250,12 @@
<dimen name="control_base_item_margin">2dp</dimen> <dimen name="control_base_item_margin">2dp</dimen>
<dimen name="control_status_padding">3dp</dimen> <dimen name="control_status_padding">3dp</dimen>
<!-- Home Controls activity view detail panel-->
<dimen name="controls_activity_view_top_padding">25dp</dimen>
<dimen name="controls_activity_view_side_padding">12dp</dimen>
<dimen name="controls_activity_view_top_offset">200dp</dimen>
<dimen name="controls_activity_view_text_size">17sp</dimen>
<!-- Home Controls management screens --> <!-- Home Controls management screens -->
<dimen name="controls_management_top_padding">48dp</dimen> <dimen name="controls_management_top_padding">48dp</dimen>
<dimen name="controls_management_side_padding">8dp</dimen> <dimen name="controls_management_side_padding">8dp</dimen>

View File

@@ -671,6 +671,19 @@
<item name="android:fontFamily">@*android:string/config_bodyFontFamily</item> <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
</style> </style>
<style name="Theme.SystemUI.Dialog.Control.DetailPanel" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar">
<item name="android:windowAnimationStyle">@style/Animation.Bottomsheet</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowIsFloating">false</item>
<item name="android:windowBackground">@null</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
<style name="Animation.Bottomsheet">
<item name="android:windowEnterAnimation">@anim/bottomsheet_in</item>
<item name="android:windowExitAnimation">@anim/bottomsheet_out</item>
</style>
<style name="Control" /> <style name="Control" />
<style name="Control.MenuItem"> <style name="Control.MenuItem">
@@ -713,6 +726,11 @@
<item name="android:textSize">@dimen/control_text_size</item> <item name="android:textSize">@dimen/control_text_size</item>
<item name="android:textColor">@color/control_secondary_text</item> <item name="android:textColor">@color/control_secondary_text</item>
</style> </style>
<style name="TextAppearance.ControlDialog">
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
<item name="android:textSize">@dimen/controls_activity_view_text_size</item>
<item name="android:textColor">@color/control_primary_text</item>
</style>
<style name="Control.ListPopupWindow" parent="@*android:style/Widget.DeviceDefault.ListPopupWindow"> <style name="Control.ListPopupWindow" parent="@*android:style/Widget.DeviceDefault.ListPopupWindow">
<item name="android:overlapAnchor">true</item> <item name="android:overlapAnchor">true</item>

View File

@@ -16,19 +16,27 @@
package com.android.systemui.controls.ui package com.android.systemui.controls.ui
import android.app.Dialog
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Intent import android.content.Intent
import android.provider.Settings import android.service.controls.Control
import android.service.controls.actions.BooleanAction import android.service.controls.actions.BooleanAction
import android.service.controls.actions.CommandAction import android.service.controls.actions.CommandAction
import android.util.Log import android.util.Log
import android.view.HapticFeedbackConstants import android.view.HapticFeedbackConstants
import com.android.systemui.R
object ControlActionCoordinator { object ControlActionCoordinator {
public const val MIN_LEVEL = 0 public const val MIN_LEVEL = 0
public const val MAX_LEVEL = 10000 public const val MAX_LEVEL = 10000
private var useDetailDialog: Boolean? = null private var dialog: Dialog? = null
fun closeDialog() {
dialog?.dismiss()
dialog = null
}
fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) { fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) {
cvh.action(BooleanAction(templateId, !isChecked)) cvh.action(BooleanAction(templateId, !isChecked))
@@ -37,31 +45,39 @@ object ControlActionCoordinator {
cvh.clipLayer.setLevel(nextLevel) cvh.clipLayer.setLevel(nextLevel)
} }
fun touch(cvh: ControlViewHolder, templateId: String) { fun touch(cvh: ControlViewHolder, templateId: String, control: Control) {
if (cvh.usePanel()) {
showDialog(cvh, control.getAppIntent().getIntent())
} else {
cvh.action(CommandAction(templateId)) cvh.action(CommandAction(templateId))
} }
}
/**
* Allow apps to specify whether they would like to appear in a detail panel or within
* the full activity by setting the {@link Control#EXTRA_USE_PANEL} flag. In order for
* activities to determine how they are being launched, they should inspect the
* {@link Control#EXTRA_USE_PANEL} flag for a value of true.
*/
fun longPress(cvh: ControlViewHolder) { fun longPress(cvh: ControlViewHolder) {
// Long press snould only be called when there is valid control state, otherwise ignore // Long press snould only be called when there is valid control state, otherwise ignore
cvh.cws.control?.let { cvh.cws.control?.let {
if (useDetailDialog == null) {
useDetailDialog = Settings.Secure.getInt(cvh.context.getContentResolver(),
"systemui.controls_use_detail_panel", 0) != 0
}
try { try {
cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
if (useDetailDialog!!) {
DetailDialog(cvh.context, it.getAppIntent()).show()
} else {
it.getAppIntent().send() it.getAppIntent().send()
val closeDialog = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
cvh.context.sendBroadcast(closeDialog) cvh.context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
}
} catch (e: PendingIntent.CanceledException) { } catch (e: PendingIntent.CanceledException) {
Log.e(ControlsUiController.TAG, "Error sending pending intent", e) Log.e(ControlsUiController.TAG, "Error sending pending intent", e)
cvh.setTransientStatus("Error opening application") cvh.setTransientStatus(
cvh.context.resources.getString(R.string.controls_error_failed))
} }
} }
} }
private fun showDialog(cvh: ControlViewHolder, intent: Intent) {
dialog = DetailDialog(cvh, intent).also {
it.setOnDismissListener { _ -> dialog = null }
it.show()
}
}
} }

View File

@@ -39,16 +39,29 @@ import com.android.systemui.R
import kotlin.reflect.KClass import kotlin.reflect.KClass
private const val UPDATE_DELAY_IN_MILLIS = 3000L /**
private const val ALPHA_ENABLED = (255.0 * 0.2).toInt() * Wraps the widgets that make up the UI representation of a {@link Control}. Updates to the view
private const val ALPHA_DISABLED = 255 * are signaled via calls to {@link #bindData}. Similar to the ViewHolder concept used in
* RecyclerViews.
*/
class ControlViewHolder( class ControlViewHolder(
val layout: ViewGroup, val layout: ViewGroup,
val controlsController: ControlsController, val controlsController: ControlsController,
val uiExecutor: DelayableExecutor, val uiExecutor: DelayableExecutor,
val bgExecutor: DelayableExecutor val bgExecutor: DelayableExecutor,
val usePanels: Boolean
) { ) {
companion object {
private const val UPDATE_DELAY_IN_MILLIS = 3000L
private const val ALPHA_ENABLED = (255.0 * 0.2).toInt()
private const val ALPHA_DISABLED = 255
private val FORCE_PANEL_DEVICES = setOf(
DeviceTypes.TYPE_THERMOSTAT,
DeviceTypes.TYPE_CAMERA
)
}
val icon: ImageView = layout.requireViewById(R.id.icon) val icon: ImageView = layout.requireViewById(R.id.icon)
val status: TextView = layout.requireViewById(R.id.status) val status: TextView = layout.requireViewById(R.id.status)
val title: TextView = layout.requireViewById(R.id.title) val title: TextView = layout.requireViewById(R.id.title)
@@ -59,6 +72,8 @@ class ControlViewHolder(
var cancelUpdate: Runnable? = null var cancelUpdate: Runnable? = null
var behavior: Behavior? = null var behavior: Behavior? = null
var lastAction: ControlAction? = null var lastAction: ControlAction? = null
val deviceType: Int
get() = cws.control?.let { it.getDeviceType() } ?: cws.ci.deviceType
init { init {
val ld = layout.getBackground() as LayerDrawable val ld = layout.getBackground() as LayerDrawable
@@ -76,7 +91,7 @@ class ControlViewHolder(
val (controlStatus, template) = cws.control?.let { val (controlStatus, template) = cws.control?.let {
title.setText(it.getTitle()) title.setText(it.getTitle())
subtitle.setText(it.getSubtitle()) subtitle.setText(it.getSubtitle())
Pair(it.getStatus(), it.getControlTemplate()) Pair(it.status, it.controlTemplate)
} ?: run { } ?: run {
title.setText(cws.ci.controlTitle) title.setText(cws.ci.controlTitle)
subtitle.setText(cws.ci.controlSubtitle) subtitle.setText(cws.ci.controlSubtitle)
@@ -91,7 +106,7 @@ class ControlViewHolder(
}) })
} }
val clazz = findBehavior(controlStatus, template) val clazz = findBehavior(controlStatus, template, deviceType)
if (behavior == null || behavior!!::class != clazz) { if (behavior == null || behavior!!::class != clazz) {
// Behavior changes can signal a change in template from the app or // Behavior changes can signal a change in template from the app or
// first time setup // first time setup
@@ -126,9 +141,17 @@ class ControlViewHolder(
controlsController.action(cws.componentName, cws.ci, action) controlsController.action(cws.componentName, cws.ci, action)
} }
private fun findBehavior(status: Int, template: ControlTemplate): KClass<out Behavior> { fun usePanel(): Boolean =
usePanels && deviceType in ControlViewHolder.FORCE_PANEL_DEVICES
private fun findBehavior(
status: Int,
template: ControlTemplate,
deviceType: Int
): KClass<out Behavior> {
return when { return when {
status == Control.STATUS_UNKNOWN -> UnknownBehavior::class status == Control.STATUS_UNKNOWN -> UnknownBehavior::class
deviceType == DeviceTypes.TYPE_CAMERA -> TouchBehavior::class
template is ToggleTemplate -> ToggleBehavior::class template is ToggleTemplate -> ToggleBehavior::class
template is StatelessTemplate -> TouchBehavior::class template is StatelessTemplate -> TouchBehavior::class
template is ToggleRangeTemplate -> ToggleRangeBehavior::class template is ToggleRangeTemplate -> ToggleRangeBehavior::class
@@ -140,7 +163,6 @@ class ControlViewHolder(
internal fun applyRenderInfo(enabled: Boolean, offset: Int = 0) { internal fun applyRenderInfo(enabled: Boolean, offset: Int = 0) {
setEnabled(enabled) setEnabled(enabled)
val deviceType = cws.control?.let { it.getDeviceType() } ?: cws.ci.deviceType
val ri = RenderInfo.lookup(context, cws.componentName, deviceType, enabled, offset) val ri = RenderInfo.lookup(context, cws.componentName, deviceType, enabled, offset)
val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme()) val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme())

View File

@@ -30,6 +30,7 @@ import android.content.res.Configuration
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.os.Process import android.os.Process
import android.provider.Settings
import android.service.controls.Control import android.service.controls.Control
import android.service.controls.actions.ControlAction import android.service.controls.actions.ControlAction
import android.util.TypedValue import android.util.TypedValue
@@ -85,6 +86,7 @@ class ControlsUiControllerImpl @Inject constructor (
private const val PREF_COMPONENT = "controls_component" private const val PREF_COMPONENT = "controls_component"
private const val PREF_STRUCTURE = "controls_structure" private const val PREF_STRUCTURE = "controls_structure"
private const val USE_PANELS = "systemui.controls_use_panel"
private const val FADE_IN_MILLIS = 225L private const val FADE_IN_MILLIS = 225L
private val EMPTY_COMPONENT = ComponentName("", "") private val EMPTY_COMPONENT = ComponentName("", "")
@@ -407,6 +409,9 @@ class ControlsUiControllerImpl @Inject constructor (
val maxColumns = findMaxColumns() val maxColumns = findMaxColumns()
// use flag only temporarily for testing
val usePanels = Settings.Secure.getInt(context.contentResolver, USE_PANELS, 0) == 1
val listView = parent.requireViewById(R.id.global_actions_controls_list) as ViewGroup val listView = parent.requireViewById(R.id.global_actions_controls_list) as ViewGroup
var lastRow: ViewGroup = createRow(inflater, listView) var lastRow: ViewGroup = createRow(inflater, listView)
selectedStructure.controls.forEach { selectedStructure.controls.forEach {
@@ -420,7 +425,8 @@ class ControlsUiControllerImpl @Inject constructor (
baseLayout, baseLayout,
controlsController.get(), controlsController.get(),
uiExecutor, uiExecutor,
bgExecutor bgExecutor,
usePanels
) )
val key = ControlKey(selectedStructure.componentName, it.controlId) val key = ControlKey(selectedStructure.componentName, it.controlId)
cvh.bindData(controlsById.getValue(key)) cvh.bindData(controlsById.getValue(key))
@@ -500,6 +506,7 @@ class ControlsUiControllerImpl @Inject constructor (
hidden = true hidden = true
popup?.dismiss() popup?.dismiss()
activeDialog?.dismiss() activeDialog?.dismiss()
ControlActionCoordinator.closeDialog()
controlsController.get().unsubscribe() controlsController.get().unsubscribe()

View File

@@ -17,18 +17,16 @@
package com.android.systemui.controls.ui package com.android.systemui.controls.ui
import android.app.ActivityView import android.app.ActivityView
import android.app.ActivityOptions
import android.app.Dialog import android.app.Dialog
import android.app.PendingIntent
import android.content.ComponentName import android.content.ComponentName
import android.content.Context
import android.content.Intent import android.content.Intent
import android.provider.Settings
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.WindowInsets
import android.view.Window
import android.view.WindowManager import android.view.WindowManager
import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS import android.widget.ImageView
import android.widget.TextView
import com.android.systemui.R import com.android.systemui.R
@@ -38,20 +36,26 @@ import com.android.systemui.R
* The activity being launched is specified by {@link android.service.controls.Control#getAppIntent}. * The activity being launched is specified by {@link android.service.controls.Control#getAppIntent}.
*/ */
class DetailDialog( class DetailDialog(
val parentContext: Context, val cvh: ControlViewHolder,
val intent: PendingIntent val intent: Intent
) : Dialog(parentContext) { ) : Dialog(cvh.context, R.style.Theme_SystemUI_Dialog_Control_DetailPanel) {
var activityView: ActivityView companion object {
private const val ALPHA = (0.8f * 255).toInt()
private const val PANEL_TOP_OFFSET = "systemui.controls_panel_top_offset"
}
lateinit var activityView: ActivityView
val stateCallback: ActivityView.StateCallback = object : ActivityView.StateCallback() { val stateCallback: ActivityView.StateCallback = object : ActivityView.StateCallback() {
override fun onActivityViewReady(view: ActivityView) { override fun onActivityViewReady(view: ActivityView) {
val fillInIntent = Intent() val launchIntent = Intent(intent)
// Apply flags to make behaviour match documentLaunchMode=always. // Apply flags to make behaviour match documentLaunchMode=always.
fillInIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
view.startActivity(intent, fillInIntent, ActivityOptions.makeBasic())
view.startActivity(launchIntent)
} }
override fun onActivityViewDestroyed(view: ActivityView) {} override fun onActivityViewDestroyed(view: ActivityView) {}
@@ -61,28 +65,8 @@ class DetailDialog(
override fun onTaskRemovalStarted(taskId: Int) {} override fun onTaskRemovalStarted(taskId: Int) {}
} }
@Suppress("DEPRECATION")
private fun Window.setWindowParams() {
requestFeature(Window.FEATURE_NO_TITLE)
// Inflate the decor view, so the attributes below are not overwritten by the theme.
decorView
attributes.systemUiVisibility =
(attributes.systemUiVisibility
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
setLayout(MATCH_PARENT, MATCH_PARENT)
clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
getAttributes().setFitInsetsTypes(0 /* types */)
}
init { init {
getWindow()?.setWindowParams() window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
setContentView(R.layout.controls_detail_dialog) setContentView(R.layout.controls_detail_dialog)
@@ -90,19 +74,61 @@ class DetailDialog(
requireViewById<ViewGroup>(R.id.controls_activity_view).apply { requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
addView(activityView) addView(activityView)
} }
requireViewById<ImageView>(R.id.control_detail_close).apply {
setOnClickListener { _: View -> dismiss() }
}
requireViewById<TextView>(R.id.title).apply {
setText(cvh.title.text)
}
requireViewById<TextView>(R.id.subtitle).apply {
setText(cvh.subtitle.text)
}
requireViewById<ImageView>(R.id.control_detail_open_in_app).apply {
setOnClickListener { v: View ->
dismiss()
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
v.context.startActivity(intent)
}
}
// consume all insets to achieve slide under effect
window.getDecorView().setOnApplyWindowInsetsListener {
v: View, insets: WindowInsets ->
activityView.apply {
val l = getPaddingLeft()
val t = getPaddingTop()
val r = getPaddingRight()
setPadding(l, t, r, insets.getSystemWindowInsets().bottom)
}
insets.consumeSystemWindowInsets()
}
requireViewById<ViewGroup>(R.id.control_detail_root).apply {
// use flag only temporarily for testing
val resolver = cvh.context.contentResolver
val defaultOffsetInPx = cvh.context.resources
.getDimensionPixelSize(R.dimen.controls_activity_view_top_offset)
val offsetInPx = Settings.Secure.getInt(resolver, PANEL_TOP_OFFSET, defaultOffsetInPx)
val lp = getLayoutParams() as ViewGroup.MarginLayoutParams
lp.topMargin = offsetInPx
setLayoutParams(lp)
}
} }
override fun show() { override fun show() {
val attrs = getWindow()?.attributes
attrs?.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
getWindow()?.attributes = attrs
activityView.setCallback(stateCallback) activityView.setCallback(stateCallback)
super.show() super.show()
} }
override fun dismiss() { override fun dismiss() {
if (!isShowing()) return
activityView.release() activityView.release()
super.dismiss() super.dismiss()

View File

@@ -33,6 +33,10 @@ class TemperatureControlBehavior : Behavior {
override fun initialize(cvh: ControlViewHolder) { override fun initialize(cvh: ControlViewHolder) {
this.cvh = cvh this.cvh = cvh
cvh.layout.setOnClickListener { _ ->
ControlActionCoordinator.touch(cvh, template.getTemplateId(), control)
}
} }
override fun bind(cws: ControlWithState) { override fun bind(cws: ControlWithState) {

View File

@@ -20,7 +20,7 @@ import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.view.View import android.view.View
import android.service.controls.Control import android.service.controls.Control
import android.service.controls.templates.StatelessTemplate import android.service.controls.templates.ControlTemplate
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL
@@ -31,7 +31,7 @@ import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL
*/ */
class TouchBehavior : Behavior { class TouchBehavior : Behavior {
lateinit var clipLayer: Drawable lateinit var clipLayer: Drawable
lateinit var template: StatelessTemplate lateinit var template: ControlTemplate
lateinit var control: Control lateinit var control: Control
lateinit var cvh: ControlViewHolder lateinit var cvh: ControlViewHolder
@@ -40,14 +40,14 @@ class TouchBehavior : Behavior {
cvh.applyRenderInfo(false) cvh.applyRenderInfo(false)
cvh.layout.setOnClickListener(View.OnClickListener() { cvh.layout.setOnClickListener(View.OnClickListener() {
ControlActionCoordinator.touch(cvh, template.getTemplateId()) ControlActionCoordinator.touch(cvh, template.getTemplateId(), control)
}) })
} }
override fun bind(cws: ControlWithState) { override fun bind(cws: ControlWithState) {
this.control = cws.control!! this.control = cws.control!!
cvh.status.setText(control.getStatusText()) cvh.status.setText(control.getStatusText())
template = control.getControlTemplate() as StatelessTemplate template = control.getControlTemplate()
val ld = cvh.layout.getBackground() as LayerDrawable val ld = cvh.layout.getBackground() as LayerDrawable
clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)