Merge "Shape screen communication with the Launcher's app (1/2)" into main
diff --git a/res/layout/color_option2.xml b/res/layout/color_option2.xml
new file mode 100644
index 0000000..2605da9
--- /dev/null
+++ b/res/layout/color_option2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright (C) 2024 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.
+-->
+<!-- Content description is set programmatically on the parent FrameLayout -->
+<com.android.customization.picker.color.ui.view.ColorOptionIconView2
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@id/background"
+ android:layout_width="@dimen/floating_sheet_color_option_size"
+ android:layout_height="@dimen/floating_sheet_color_option_size"/>
+
diff --git a/res/layout/floating_sheet_colors.xml b/res/layout/floating_sheet_colors.xml
index 5834caa..f8cfc98 100644
--- a/res/layout/floating_sheet_colors.xml
+++ b/res/layout/floating_sheet_colors.xml
@@ -25,7 +25,8 @@
android:layout_height="wrap_content"
android:background="@drawable/floating_sheet_content_background"
android:paddingVertical="@dimen/floating_sheet_content_vertical_padding"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:clipChildren="false">
<TextView
android:id="@+id/color_type_tab_subhead"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index fe06735..c242fe9 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -191,5 +191,7 @@
<dimen name="floating_sheet_clock_edit_icon_size">48dp</dimen>
<dimen name="floating_sheet_clock_style_thumbnail_margin">12dp</dimen>
<dimen name="floating_sheet_clock_style_clock_size_text_margin_end">16dp</dimen>
+ <dimen name="floating_sheet_color_option_size">54dp</dimen>
+ <dimen name="floating_sheet_color_option_stroke_width">3dp</dimen>
<dimen name="customization_option_entry_shortcut_icon_size">20dp</dimen>
</resources>
diff --git a/src/com/android/customization/picker/color/ui/binder/ColorOptionIconBinder2.kt b/src/com/android/customization/picker/color/ui/binder/ColorOptionIconBinder2.kt
new file mode 100644
index 0000000..2c197ad
--- /dev/null
+++ b/src/com/android/customization/picker/color/ui/binder/ColorOptionIconBinder2.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 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.customization.picker.color.ui.binder
+
+import com.android.customization.picker.color.ui.view.ColorOptionIconView2
+import com.android.customization.picker.color.ui.viewmodel.ColorOptionIconViewModel
+
+object ColorOptionIconBinder2 {
+ fun bind(view: ColorOptionIconView2, viewModel: ColorOptionIconViewModel, darkTheme: Boolean) {
+ if (darkTheme) {
+ view.bindColor(
+ view.resources.getColor(android.R.color.system_primary_dark, view.context.theme),
+ viewModel.darkThemeColor0,
+ viewModel.darkThemeColor1,
+ viewModel.darkThemeColor2,
+ viewModel.darkThemeColor3,
+ )
+ } else {
+ view.bindColor(
+ view.resources.getColor(android.R.color.system_primary_light, view.context.theme),
+ viewModel.lightThemeColor0,
+ viewModel.lightThemeColor1,
+ viewModel.lightThemeColor2,
+ viewModel.lightThemeColor3,
+ )
+ }
+ }
+}
diff --git a/src/com/android/customization/picker/color/ui/view/ColorOptionIconView2.kt b/src/com/android/customization/picker/color/ui/view/ColorOptionIconView2.kt
new file mode 100644
index 0000000..3fc6324
--- /dev/null
+++ b/src/com/android/customization/picker/color/ui/view/ColorOptionIconView2.kt
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 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.customization.picker.color.ui.view
+
+import android.annotation.ColorInt
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.Path
+import android.util.AttributeSet
+import com.android.themepicker.R
+import com.android.wallpaper.picker.option.ui.view.OptionItemBackground
+
+/**
+ * Draw a color option icon, which is a quadrant circle that can show at most 4 different colors.
+ */
+class ColorOptionIconView2(context: Context, attrs: AttributeSet) :
+ OptionItemBackground(context, attrs) {
+
+ private val paint = Paint().apply { style = Paint.Style.FILL }
+
+ private val path = Path()
+
+ private var color0 = DEFAULT_PLACEHOLDER_COLOR
+ private var color1 = DEFAULT_PLACEHOLDER_COLOR
+ private var color2 = DEFAULT_PLACEHOLDER_COLOR
+ private var color3 = DEFAULT_PLACEHOLDER_COLOR
+ private var strokeColor = DEFAULT_PLACEHOLDER_COLOR
+ private val strokeWidth =
+ context.resources
+ .getDimensionPixelSize(R.dimen.floating_sheet_color_option_stroke_width)
+ .toFloat()
+
+ private var w = 0
+ private var h = 0
+
+ /**
+ * @param color0 the color in the top left quadrant
+ * @param color1 the color in the top right quadrant
+ * @param color2 the color in the bottom left quadrant
+ * @param color3 the color in the bottom right quadrant
+ */
+ fun bindColor(
+ @ColorInt strokeColor: Int,
+ @ColorInt color0: Int,
+ @ColorInt color1: Int,
+ @ColorInt color2: Int,
+ @ColorInt color3: Int,
+ ) {
+ this.strokeColor = strokeColor
+ this.color0 = color0
+ this.color1 = color1
+ this.color2 = color2
+ this.color3 = color3
+ invalidate()
+ }
+
+ override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
+ this.w = w
+ this.h = h
+ super.onSizeChanged(w, h, oldw, oldh)
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ // The w and h need to be an even number to avoid tiny pixel-level gaps between the pies
+ w = w.roundDownToEven()
+ h = h.roundDownToEven()
+
+ val width = w.toFloat()
+ val height = h.toFloat()
+
+ val left = 2 * strokeWidth
+ val right = width - 2 * strokeWidth
+ val top = 2 * strokeWidth
+ val bottom = height - 2 * strokeWidth
+ val cornerRadius = ((right - left) / 2) * (1f - 0.25f * progress)
+ val save = canvas.save()
+ path.reset()
+ path.addRoundRect(left, top, right, bottom, cornerRadius, cornerRadius, Path.Direction.CW)
+ path.close()
+ canvas.clipPath(path)
+
+ canvas.apply {
+ paint.style = Paint.Style.FILL
+ // top left
+ paint.color = color0
+ drawRect(0f, 0f, width / 2, height / 2, paint)
+ // top right
+ paint.color = color1
+ drawRect(width / 2, 0f, width, height / 2, paint)
+ // bottom left
+ paint.color = color2
+ drawRect(0f, height / 2, width / 2, height, paint)
+ // bottom right
+ paint.color = color3
+ drawRect(width / 2, height / 2, width, height, paint)
+ }
+
+ canvas.restoreToCount(save)
+ paint.style = Paint.Style.STROKE
+ paint.color = strokeColor
+ paint.alpha = (255 * progress).toInt()
+ paint.strokeWidth = this.strokeWidth
+ val strokeCornerRadius = ((width - strokeWidth) / 2) * (1f - 0.25f * progress)
+ val halfStrokeWidth = 0.5f * strokeWidth
+ // Stroke is centered along the path, so account for half strokeWidth to stay within View
+ canvas.drawRoundRect(
+ halfStrokeWidth,
+ halfStrokeWidth,
+ width - halfStrokeWidth,
+ height - halfStrokeWidth,
+ strokeCornerRadius,
+ strokeCornerRadius,
+ paint,
+ )
+ }
+
+ companion object {
+ const val DEFAULT_PLACEHOLDER_COLOR = Color.BLACK
+
+ fun Int.roundDownToEven(): Int {
+ return if (this % 2 == 0) this else this - 1
+ }
+ }
+}
diff --git a/src/com/android/wallpaper/customization/ui/binder/ColorsFloatingSheetBinder.kt b/src/com/android/wallpaper/customization/ui/binder/ColorsFloatingSheetBinder.kt
index 10bedb3..58a1fd9 100644
--- a/src/com/android/wallpaper/customization/ui/binder/ColorsFloatingSheetBinder.kt
+++ b/src/com/android/wallpaper/customization/ui/binder/ColorsFloatingSheetBinder.kt
@@ -25,13 +25,12 @@
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
-import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
-import com.android.customization.picker.color.ui.binder.ColorOptionIconBinder
-import com.android.customization.picker.color.ui.view.ColorOptionIconView
+import com.android.customization.picker.color.ui.binder.ColorOptionIconBinder2
+import com.android.customization.picker.color.ui.view.ColorOptionIconView2
import com.android.customization.picker.color.ui.viewmodel.ColorOptionIconViewModel
-import com.android.customization.picker.common.ui.view.DoubleRowListItemSpacing
+import com.android.customization.picker.common.ui.view.SingleRowListItemSpacing
import com.android.customization.picker.mode.ui.binder.DarkModeBinder
import com.android.themepicker.R
import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil.ThemePickerHomeCustomizationOption.COLORS
@@ -39,7 +38,7 @@
import com.android.wallpaper.picker.customization.ui.view.FloatingToolbar
import com.android.wallpaper.picker.customization.ui.view.adapter.FloatingToolbarTabAdapter
import com.android.wallpaper.picker.customization.ui.viewmodel.ColorUpdateViewModel
-import com.android.wallpaper.picker.option.ui.adapter.OptionItemAdapter
+import com.android.wallpaper.picker.option.ui.adapter.OptionItemAdapter2
import java.lang.ref.WeakReference
import kotlinx.coroutines.launch
@@ -110,35 +109,33 @@
private fun createOptionItemAdapter(
uiMode: Int,
lifecycleOwner: LifecycleOwner,
- ): OptionItemAdapter<ColorOptionIconViewModel> =
- OptionItemAdapter(
- layoutResourceId = R.layout.color_option,
+ ): OptionItemAdapter2<ColorOptionIconViewModel> =
+ OptionItemAdapter2(
+ layoutResourceId = R.layout.color_option2,
lifecycleOwner = lifecycleOwner,
- bindIcon = { foregroundView: View, colorIcon: ColorOptionIconViewModel ->
- val colorOptionIconView = foregroundView as? ColorOptionIconView
+ bindPayload = { itemView: View, colorIcon: ColorOptionIconViewModel ->
+ val colorOptionIconView =
+ itemView.requireViewById<ColorOptionIconView2>(
+ com.android.wallpaper.R.id.background
+ )
val night = uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES
- colorOptionIconView?.let { ColorOptionIconBinder.bind(it, colorIcon, night) }
+ ColorOptionIconBinder2.bind(colorOptionIconView, colorIcon, night)
},
)
private fun RecyclerView.initColorsList(
context: Context,
- adapter: OptionItemAdapter<ColorOptionIconViewModel>,
+ adapter: OptionItemAdapter2<ColorOptionIconViewModel>,
) {
apply {
this.adapter = adapter
- layoutManager = GridLayoutManager(context, 2, GridLayoutManager.HORIZONTAL, false)
+ layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
addItemDecoration(
- DoubleRowListItemSpacing(
+ SingleRowListItemSpacing(
context.resources.getDimensionPixelSize(
R.dimen.floating_sheet_content_horizontal_padding
),
- context.resources.getDimensionPixelSize(
- R.dimen.floating_sheet_list_item_horizontal_space
- ),
- context.resources.getDimensionPixelSize(
- R.dimen.floating_sheet_list_item_vertical_space
- ),
+ 0,
)
)
}
diff --git a/src/com/android/wallpaper/customization/ui/binder/ShortcutFloatingSheetBinder.kt b/src/com/android/wallpaper/customization/ui/binder/ShortcutFloatingSheetBinder.kt
index 0fdf931..4c72412 100644
--- a/src/com/android/wallpaper/customization/ui/binder/ShortcutFloatingSheetBinder.kt
+++ b/src/com/android/wallpaper/customization/ui/binder/ShortcutFloatingSheetBinder.kt
@@ -152,9 +152,10 @@
OptionItemAdapter2(
layoutResourceId = R.layout.quick_affordance_list_item2,
lifecycleOwner = lifecycleOwner,
- bindIcon = { foregroundView: View, gridIcon: Icon ->
- val imageView = foregroundView as? ImageView
- imageView?.let { IconViewBinder.bind(imageView, gridIcon) }
+ bindPayload = { itemView: View, gridIcon: Icon ->
+ val imageView =
+ itemView.requireViewById<ImageView>(com.android.wallpaper.R.id.foreground)
+ IconViewBinder.bind(imageView, gridIcon)
},
)