Merge "Controls UI - Marquee + dynamic column count" into rvc-dev am: f241f95205 am: 05aa82a9f8

Change-Id: I61b2eaf284b496bf42e79699dac07f40676f30f3
This commit is contained in:
TreeHugger Robot
2020-04-06 14:17:52 +00:00
committed by Automerger Merge Worker
10 changed files with 82 additions and 45 deletions

View File

@@ -40,29 +40,20 @@
<TextView <TextView
android:id="@+id/status" android:id="@+id/status"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Control.Status" android:textAppearance="@style/TextAppearance.Control.Status"
android:paddingTop="@dimen/control_padding_adjustment" android:paddingTop="@dimen/control_padding_adjustment"
android:paddingStart="@dimen/control_status_padding" android:paddingStart="@dimen/control_status_padding"
android:clickable="false" android:clickable="true"
android:focusable="false" android:focusable="false"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit = "marquee_forever"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@+id/icon" app:layout_constraintBottom_toBottomOf="@+id/icon"
app:layout_constraintStart_toEndOf="@+id/icon" /> app:layout_constraintStart_toEndOf="@+id/icon" />
<TextView
android:id="@+id/status_extra"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Control.Status"
android:paddingTop="@dimen/control_padding_adjustment"
android:paddingStart="@dimen/control_status_padding"
android:clickable="false"
android:focusable="false"
app:layout_constraintBottom_toBottomOf="@+id/icon"
app:layout_constraintStart_toEndOf="@+id/status" />
<TextView <TextView
android:id="@+id/title" android:id="@+id/title"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@@ -67,9 +67,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:layout_marginRight="@dimen/global_actions_grid_horizontal_padding"
android:layout_marginLeft="@dimen/global_actions_grid_horizontal_padding"
/> />
</LinearLayout> </LinearLayout>
</com.android.systemui.globalactions.MinHeightScrollView> </com.android.systemui.globalactions.MinHeightScrollView>
</LinearLayout> </LinearLayout>

View File

@@ -31,4 +31,7 @@
<!-- orientation of the dead zone when touches have recently occurred elsewhere on screen --> <!-- orientation of the dead zone when touches have recently occurred elsewhere on screen -->
<integer name="navigation_bar_deadzone_orientation">1</integer> <integer name="navigation_bar_deadzone_orientation">1</integer>
<!-- Max number of columns for quick controls area -->
<integer name="controls_max_columns">4</integer>
</resources> </resources>

View File

@@ -30,5 +30,7 @@
<dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen> <dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen>
<dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen> <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
<!-- Home Controls -->
<dimen name="controls_list_side_margin">10dp</dimen>
</resources> </resources>

View File

@@ -26,5 +26,7 @@
navigation_extra_key_width --> navigation_extra_key_width -->
<dimen name="navigation_side_padding">40dip</dimen> <dimen name="navigation_side_padding">40dip</dimen>
<!-- Home Controls -->
<dimen name="controls_list_side_margin">12dp</dimen>
</resources> </resources>

View File

@@ -30,5 +30,7 @@
<dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen> <dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen>
<dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen> <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
<!-- Home Controls -->
<dimen name="controls_list_side_margin">16dp</dimen>
</resources> </resources>

View File

@@ -533,4 +533,12 @@
This config value should contain the package name of that preferred application. This config value should contain the package name of that preferred application.
--> -->
<string translatable="false" name="config_controlsPreferredPackage"></string> <string translatable="false" name="config_controlsPreferredPackage"></string>
<!-- Max number of columns for quick controls area -->
<integer name="controls_max_columns">2</integer>
<!-- If the dp width of the available space is <= this value, potentially adjust the number
of columns-->
<integer name="controls_max_columns_adjust_below_width_dp">320</integer>
<!-- If the config font scale is >= this value, potentially adjust the number of columns-->
<item name="controls_max_columns_adjust_above_font_scale" translatable="false" format="float" type="dimen">1.25</item>
</resources> </resources>

View File

@@ -51,7 +51,6 @@ class ControlViewHolder(
) { ) {
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 statusExtra: TextView = layout.requireViewById(R.id.status_extra)
val title: TextView = layout.requireViewById(R.id.title) val title: TextView = layout.requireViewById(R.id.title)
val subtitle: TextView = layout.requireViewById(R.id.subtitle) val subtitle: TextView = layout.requireViewById(R.id.subtitle)
val context: Context = layout.getContext() val context: Context = layout.getContext()
@@ -65,6 +64,8 @@ class ControlViewHolder(
val ld = layout.getBackground() as LayerDrawable val ld = layout.getBackground() as LayerDrawable
ld.mutate() ld.mutate()
clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable
// needed for marquee to start
status.setSelected(true)
} }
fun bindData(cws: ControlWithState) { fun bindData(cws: ControlWithState) {
@@ -103,8 +104,7 @@ class ControlViewHolder(
behavior?.bind(cws) behavior?.bind(cws)
layout.setContentDescription( layout.setContentDescription("${title.text} ${subtitle.text} ${status.text}")
"${title.text} ${subtitle.text} ${status.text} ${statusExtra.text}")
} }
fun actionResponse(@ControlAction.ResponseResult response: Int) { fun actionResponse(@ControlAction.ResponseResult response: Int) {
@@ -113,15 +113,12 @@ class ControlViewHolder(
fun setTransientStatus(tempStatus: String) { fun setTransientStatus(tempStatus: String) {
val previousText = status.getText() val previousText = status.getText()
val previousTextExtra = statusExtra.getText()
cancelUpdate = uiExecutor.executeDelayed({ cancelUpdate = uiExecutor.executeDelayed({
status.setText(previousText) status.setText(previousText)
statusExtra.setText(previousTextExtra)
}, UPDATE_DELAY_IN_MILLIS) }, UPDATE_DELAY_IN_MILLIS)
status.setText(tempStatus) status.setText(tempStatus)
statusExtra.setText("")
} }
fun action(action: ControlAction) { fun action(action: ControlAction) {
@@ -154,7 +151,6 @@ class ControlViewHolder(
} }
status.setTextColor(fg) status.setTextColor(fg)
statusExtra.setTextColor(fg)
icon.setImageDrawable(ri.icon) icon.setImageDrawable(ri.icon)

View File

@@ -21,10 +21,12 @@ import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
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.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.Log import android.util.Log
import android.view.ContextThemeWrapper import android.view.ContextThemeWrapper
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -345,10 +347,12 @@ class ControlsUiControllerImpl @Inject constructor (
val inflater = LayoutInflater.from(context) val inflater = LayoutInflater.from(context)
inflater.inflate(R.layout.controls_with_favorites, parent, true) inflater.inflate(R.layout.controls_with_favorites, parent, true)
val maxColumns = findMaxColumns()
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 {
if (lastRow.getChildCount() == 2) { if (lastRow.getChildCount() == maxColumns) {
lastRow = createRow(inflater, listView) lastRow = createRow(inflater, listView)
} }
val baseLayout = inflater.inflate( val baseLayout = inflater.inflate(
@@ -365,12 +369,40 @@ class ControlsUiControllerImpl @Inject constructor (
controlViewsById.put(key, cvh) controlViewsById.put(key, cvh)
} }
// add spacer if necessary to keep control size consistent // add spacers if necessary to keep control size consistent
if ((selectedStructure.controls.size % 2) == 1) { var spacersToAdd = selectedStructure.controls.size % maxColumns
while (spacersToAdd > 0) {
lastRow.addView(Space(context), LinearLayout.LayoutParams(0, 0, 1f)) lastRow.addView(Space(context), LinearLayout.LayoutParams(0, 0, 1f))
spacersToAdd--
} }
} }
/**
* For low-dp width screens that also employ an increased font scale, adjust the
* number of columns. This helps prevent text truncation on these devices.
*/
private fun findMaxColumns(): Int {
val res = context.resources
var maxColumns = res.getInteger(R.integer.controls_max_columns)
val maxColumnsAdjustWidth =
res.getInteger(R.integer.controls_max_columns_adjust_below_width_dp)
val outValue = TypedValue()
res.getValue(R.dimen.controls_max_columns_adjust_above_font_scale, outValue, true)
val maxColumnsAdjustFontScale = outValue.getFloat()
val config = res.configuration
val isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT
if (isPortrait &&
config.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED &&
config.screenWidthDp <= maxColumnsAdjustWidth &&
config.fontScale >= maxColumnsAdjustFontScale) {
maxColumns--
}
return maxColumns
}
private fun loadPreference(structures: List<StructureInfo>): StructureInfo { private fun loadPreference(structures: List<StructureInfo>): StructureInfo {
if (structures.isEmpty()) return EMPTY_STRUCTURE if (structures.isEmpty()) return EMPTY_STRUCTURE

View File

@@ -47,9 +47,10 @@ class ToggleRangeBehavior : Behavior {
lateinit var control: Control lateinit var control: Control
lateinit var cvh: ControlViewHolder lateinit var cvh: ControlViewHolder
lateinit var rangeTemplate: RangeTemplate lateinit var rangeTemplate: RangeTemplate
lateinit var statusExtra: TextView
lateinit var status: TextView lateinit var status: TextView
lateinit var context: Context lateinit var context: Context
var currentStatusText: CharSequence = ""
var currentRangeValue: String = ""
companion object { companion object {
private const val DEFAULT_FORMAT = "%.1f" private const val DEFAULT_FORMAT = "%.1f"
@@ -83,8 +84,8 @@ class ToggleRangeBehavior : Behavior {
override fun bind(cws: ControlWithState) { override fun bind(cws: ControlWithState) {
this.control = cws.control!! this.control = cws.control!!
statusExtra = cvh.statusExtra currentStatusText = control.getStatusText()
status.setText(control.getStatusText()) status.setText(currentStatusText)
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)
@@ -96,7 +97,7 @@ class ToggleRangeBehavior : Behavior {
val checked = template.isChecked() val checked = template.isChecked()
val currentRatio = rangeTemplate.getCurrentValue() / val currentRatio = rangeTemplate.getCurrentValue() /
(rangeTemplate.getMaxValue() - rangeTemplate.getMinValue()) (rangeTemplate.getMaxValue() - rangeTemplate.getMinValue())
updateRange(currentRatio, checked) updateRange(currentRatio, checked, /* isDragging */ false)
cvh.applyRenderInfo(checked) cvh.applyRenderInfo(checked)
@@ -147,7 +148,7 @@ class ToggleRangeBehavior : Behavior {
AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE) AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE)
val ratioDiff = (value - rangeTemplate.getCurrentValue()) / val ratioDiff = (value - rangeTemplate.getCurrentValue()) /
(rangeTemplate.getMaxValue() - rangeTemplate.getMinValue()) (rangeTemplate.getMaxValue() - rangeTemplate.getMinValue())
updateRange(ratioDiff, template.isChecked()) updateRange(ratioDiff, template.isChecked(), /* isDragging */ false)
endUpdateRange() endUpdateRange()
true true
} }
@@ -167,26 +168,27 @@ class ToggleRangeBehavior : Behavior {
} }
fun beginUpdateRange() { fun beginUpdateRange() {
status.setVisibility(View.GONE) status.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
statusExtra.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
.getDimensionPixelSize(R.dimen.control_status_expanded).toFloat()) .getDimensionPixelSize(R.dimen.control_status_expanded).toFloat())
} }
fun updateRange(ratioDiff: Float, checked: Boolean) { fun updateRange(ratioDiff: Float, checked: Boolean, isDragging: Boolean) {
val changeAmount = if (checked) (MAX_LEVEL * ratioDiff).toInt() else MIN_LEVEL val changeAmount = if (checked) (MAX_LEVEL * ratioDiff).toInt() else MIN_LEVEL
val newLevel = Math.max(MIN_LEVEL, Math.min(MAX_LEVEL, clipLayer.getLevel() + changeAmount)) val newLevel = Math.max(MIN_LEVEL, Math.min(MAX_LEVEL, clipLayer.getLevel() + changeAmount))
clipLayer.setLevel(newLevel) clipLayer.setLevel(newLevel)
if (checked) { if (checked) {
val newValue = levelToRangeValue(clipLayer.getLevel()) val newValue = levelToRangeValue(clipLayer.getLevel())
val formattedNewValue = format(rangeTemplate.getFormatString().toString(), currentRangeValue = format(rangeTemplate.getFormatString().toString(),
DEFAULT_FORMAT, newValue) DEFAULT_FORMAT, newValue)
val text = if (isDragging) {
statusExtra.setText(formattedNewValue) currentRangeValue
statusExtra.setVisibility(View.VISIBLE) } else {
"$currentStatusText $currentRangeValue"
}
status.setText(text)
} else { } else {
statusExtra.setText("") status.setText(currentStatusText)
statusExtra.setVisibility(View.GONE)
} }
} }
@@ -210,9 +212,9 @@ class ToggleRangeBehavior : Behavior {
} }
fun endUpdateRange() { fun endUpdateRange() {
statusExtra.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources() status.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
.getDimensionPixelSize(R.dimen.control_status_normal).toFloat()) .getDimensionPixelSize(R.dimen.control_status_normal).toFloat())
status.setVisibility(View.VISIBLE) status.setText("$currentStatusText $currentRangeValue")
cvh.action(FloatAction(rangeTemplate.getTemplateId(), cvh.action(FloatAction(rangeTemplate.getTemplateId(),
findNearestStep(levelToRangeValue(clipLayer.getLevel())))) findNearestStep(levelToRangeValue(clipLayer.getLevel()))))
} }
@@ -260,7 +262,8 @@ class ToggleRangeBehavior : Behavior {
isDragging = true isDragging = true
} }
this@ToggleRangeBehavior.updateRange(-xDiff / v.getWidth(), true) this@ToggleRangeBehavior.updateRange(-xDiff / v.getWidth(),
/* checked */ true, /* isDragging */ true)
return true return true
} }