Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Golden Tiles samples #450

Merged
merged 20 commits into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright 2022 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
*
* https://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.example.wear.tiles.golden

import android.content.Context
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import com.example.wear.tiles.R
import com.example.wear.tiles.emptyClickable
import com.example.wear.tiles.tools.WearSmallRoundDevicePreview
import com.google.android.horologist.compose.tools.LayoutRootPreview
import com.google.android.horologist.compose.tools.buildDeviceParameters
import com.google.android.horologist.tiles.images.drawableResToImageResource

@WearSmallRoundDevicePreview
ataulm marked this conversation as resolved.
Show resolved Hide resolved
@Composable
fun Goal() {
val context = LocalContext.current
LayoutRootPreview(
Goal.layout(context, context.deviceParams(), steps = 5168, goal = 8000)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any parameter that could change if used as a real tile is exposed.

)
}

@WearSmallRoundDevicePreview
@Composable
fun WorkoutButtons() {
val context = LocalContext.current
LayoutRootPreview(
Workout.buttonsLayout(
context,
context.deviceParams(),
weekSummary = "1 run this week",
button1Clickable = emptyClickable,
button2Clickable = emptyClickable,
button3Clickable = emptyClickable,
chipClickable = emptyClickable,
)
) {
addIdToImageMapping(
Workout.BUTTON_1_ICON_ID,
drawableResToImageResource(R.drawable.ic_run_24)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can/should we add an ext function to whatever receiver this is?

Foo.addIdToImageMapping(String, @DrawableRes Int)

drawableResToImageResource(@DrawableRes Int) exists in Horologist already. Is the Foo only used for preview or is it the same code that would be used in a renderer?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea.

)
addIdToImageMapping(
Workout.BUTTON_2_ICON_ID,
drawableResToImageResource(R.drawable.ic_yoga_24)
)
addIdToImageMapping(
Workout.BUTTON_3_ICON_ID,
drawableResToImageResource(R.drawable.ic_cycling_24)
)
}
}

@WearSmallRoundDevicePreview
@Composable
fun WorkoutLargeChip() {
val context = LocalContext.current
LayoutRootPreview(
Workout.largeChipLayout(
context,
context.deviceParams(),
emptyClickable,
title = "Power Yoga",
chipText = "Start",
lastWorkoutSummary = "Last session 45m"
)
)
}

private fun Context.deviceParams() = buildDeviceParameters(resources)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FF00FF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>
21 changes: 21 additions & 0 deletions WearTilesKotlin/app/src/debug/res/values/colors.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2021 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
~
~ https://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>
<color name="yellow">#FFCF48</color>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file will likely be deleted since we're moving away from color resources in Compose-era.

<color name="black">#000</color>
<color name="dark_gray">#414A4C</color>
<color name="white">#FFF</color>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2022 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
*
* https://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.example.wear.tiles.golden

import android.content.Context
import androidx.wear.tiles.ColorBuilders
import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters
import androidx.wear.tiles.material.CircularProgressIndicator
import androidx.wear.tiles.material.ProgressIndicatorColors
import androidx.wear.tiles.material.Text
import androidx.wear.tiles.material.Typography
import androidx.wear.tiles.material.layouts.EdgeContentLayout

object Goal {
fun layout(context: Context, deviceParameters: DeviceParameters, steps: Int, goal: Int) =
EdgeContentLayout.Builder(deviceParameters)
.setEdgeContent(
CircularProgressIndicator.Builder()
.setProgress(steps.toFloat() / goal)
.setCircularProgressIndicatorColors(blueOnTranslucentWhite())
.build()
)
.setPrimaryLabelTextContent(
Text.Builder(context, "Steps")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(ColorBuilders.argb(GoldenTilesColors.Blue))
.build()
)
.setSecondaryLabelTextContent(
Text.Builder(context, "/ $goal")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(ColorBuilders.argb(GoldenTilesColors.White))
.build()
)
.setContent(
Text.Builder(context, "$steps")
.setTypography(Typography.TYPOGRAPHY_DISPLAY1)
.setColor(ColorBuilders.argb(GoldenTilesColors.White))
.build()
)
.build()
}

private fun blueOnTranslucentWhite() = ProgressIndicatorColors(
/* indicatorColor = */ ColorBuilders.argb(GoldenTilesColors.Blue),
/* trackColor = */ ColorBuilders.argb(GoldenTilesColors.White10Pc)
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.wear.tiles.util
package com.example.wear.tiles.golden

import android.content.Context
import androidx.wear.tiles.RequestBuilders
import androidx.wear.tiles.ResourceBuilders.Resources
import androidx.wear.tiles.TileBuilders
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb

abstract class TileRenderer<T, R>(val context: Context) {
abstract fun renderTile(
tileState: T,
requestParams: RequestBuilders.TileRequest,
): TileBuilders.Tile

abstract fun produceRequestedResources(
resourceResults: R,
requestParams: RequestBuilders.ResourcesRequest,
): Resources
object GoldenTilesColors {
val Black = Color.Black.toArgb()
val Blue = android.graphics.Color.parseColor("#AECBFA")
val BlueGray = android.graphics.Color.parseColor("#2B333E")
val White = Color.White.toArgb()
val White10Pc = Color(1f, 1f, 1f, 0.1f).toArgb()
val Yellow = android.graphics.Color.parseColor("#FDE293")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright 2022 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
*
* https://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.example.wear.tiles.golden

import android.content.Context
import androidx.wear.tiles.ColorBuilders
import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters
import androidx.wear.tiles.ModifiersBuilders.Clickable
import androidx.wear.tiles.material.Button
import androidx.wear.tiles.material.ChipColors
import androidx.wear.tiles.material.CompactChip
import androidx.wear.tiles.material.Text
import androidx.wear.tiles.material.TitleChip
import androidx.wear.tiles.material.Typography
import androidx.wear.tiles.material.layouts.MultiButtonLayout
import androidx.wear.tiles.material.layouts.PrimaryLayout

object Workout {
const val BUTTON_1_ICON_ID = "1"
const val BUTTON_2_ICON_ID = "2"
const val BUTTON_3_ICON_ID = "3"

fun buttonsLayout(
context: Context,
deviceParameters: DeviceParameters,
weekSummary: String,
button1Clickable: Clickable,
button2Clickable: Clickable,
button3Clickable: Clickable,
chipClickable: Clickable
) =
PrimaryLayout.Builder(deviceParameters)
.setPrimaryLabelTextContent(
Text.Builder(context, weekSummary)
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(ColorBuilders.argb(GoldenTilesColors.Blue))
.build()
)
.setContent(
MultiButtonLayout.Builder()
.addButtonContent(
Button.Builder(context, button1Clickable).setIconContent(BUTTON_1_ICON_ID)
.build()
)
.addButtonContent(
Button.Builder(context, button2Clickable).setIconContent(BUTTON_2_ICON_ID)
.build()
)
.addButtonContent(
Button.Builder(context, button3Clickable).setIconContent(BUTTON_3_ICON_ID)
.build()
)
.build()
)
.setPrimaryChipContent(
CompactChip.Builder(context, "More", chipClickable, deviceParameters)
.setChipColors(
ChipColors(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bordering on the don't review for content, but would it be helpful to implement these designs using themes using Colors? then using primary or secondary ChipColors factories?

Copy link
Contributor Author

@ataulm ataulm Jul 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment for this elsewhere. I'm not sure themes for tiles is worth it - as I was implementing all of these, I found it easier to specify colors explicitly.

In a real project, I imagine it'll be even less worth it:

  • a real project won't have many tiles
  • themes aren't directly reusable between Compose/this
  • even if they were reusable, it's not guaranteed that we'd want the same combination of colors
  • tiles (/wear?) is always dark mode and doesn't support dynamic theming (afaik)

I'm not sure what it provides.

Copy link
Contributor Author

@ataulm ataulm Jul 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The link you provided here to an example project does help show some utility - https://github.com/yschimke/rememberwear/blob/main/wear/src/main/kotlin/com/google/wear/soyted/tile/RememberWearTileRenderer.kt#L116


I think we should not introduce themes for the Golden Tiles from themes because it'll only serve to showcase the overhead without any of the benefit; unlike your RememberTheMilk project which is sharing a theme with the main app, each Golden Tile is distinct and has its own theme.

There's an example of a theme being created in ComponentAudit.kt which we can leave as-is / improve, since it's used throughout the whole file (there's no requirements/designs for different colors).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IF we want people to be able to take these tiles and copy and paste them, I think it's useful. Or maybe a library of reference tile designs, "templates" that we provide. But your call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave it for now and we'll revisit if there's feedback. I think these samples should facilitate understanding and we shouldn't necessarily be encouraging copy and pasting.

ataulm marked this conversation as resolved.
Show resolved Hide resolved
/*backgroundColor=*/ ColorBuilders.argb(GoldenTilesColors.BlueGray),
/*contentColor=*/ ColorBuilders.argb(GoldenTilesColors.White)
)
)
.build()
)
.build()

fun largeChipLayout(
context: Context,
deviceParameters: DeviceParameters,
clickable: Clickable,
title: String,
chipText: String,
lastWorkoutSummary: String
) = PrimaryLayout.Builder(deviceParameters)
.setPrimaryLabelTextContent(
Text.Builder(context, title)
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(ColorBuilders.argb(GoldenTilesColors.Yellow))
.build()
)
.setContent(
TitleChip.Builder(context, chipText, clickable, deviceParameters)
.setChipColors(
ChipColors(
/*backgroundColor=*/ ColorBuilders.argb(GoldenTilesColors.Yellow),
/*contentColor=*/ ColorBuilders.argb(GoldenTilesColors.Black)
)
)
.build()
)
.setSecondaryLabelTextContent(
Text.Builder(context, lastWorkoutSummary)
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(ColorBuilders.argb(GoldenTilesColors.White))
.build()
)
.build()
}
4 changes: 4 additions & 0 deletions WearTilesKotlin/app/src/main/res/drawable/ic_cycling_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="26"
android:viewportWidth="26" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF00FF" android:fillType="evenOdd" android:pathData="M18.958,3.792C18.958,4.983 17.983,5.958 16.792,5.958C15.6,5.958 14.625,4.983 14.625,3.792C14.625,2.6 15.6,1.625 16.792,1.625C17.983,1.625 18.958,2.6 18.958,3.792ZM0,18.417C0,15.383 2.383,13 5.417,13C8.45,13 10.833,15.383 10.833,18.417C10.833,21.45 8.45,23.833 5.417,23.833C2.383,23.833 0,21.45 0,18.417ZM5.417,22.208C3.358,22.208 1.625,20.475 1.625,18.417C1.625,16.358 3.358,14.625 5.417,14.625C7.475,14.625 9.208,16.358 9.208,18.417C9.208,20.475 7.475,22.208 5.417,22.208ZM20.692,11.917C18.417,11.917 16.575,11.05 15.167,9.642L14.3,8.775L11.7,11.375L14.083,13.867V20.583H11.917V15.167L8.45,12.133C8.017,11.808 7.8,11.267 7.8,10.617C7.8,10.075 8.017,9.533 8.45,9.1L11.483,6.067C11.808,5.633 12.35,5.417 13,5.417C13.65,5.417 14.192,5.633 14.733,6.067L16.792,8.125C17.767,9.1 19.067,9.75 20.692,9.75V11.917ZM20.583,13C17.55,13 15.167,15.383 15.167,18.417C15.167,21.45 17.55,23.833 20.583,23.833C23.617,23.833 26,21.45 26,18.417C26,15.383 23.617,13 20.583,13ZM16.792,18.417C16.792,20.475 18.525,22.208 20.583,22.208C22.642,22.208 24.375,20.475 24.375,18.417C24.375,16.358 22.642,14.625 20.583,14.625C18.525,14.625 16.792,16.358 16.792,18.417Z"/>
</vector>
5 changes: 5 additions & 0 deletions WearTilesKotlin/app/src/main/res/drawable/ic_run_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#FF00FF" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M13.49,5.48c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM9.89,19.38l1,-4.4 2.1,2v6h2v-7.5l-2.1,-2 0.6,-3c1.3,1.5 3.3,2.5 5.5,2.5v-2c-1.9,0 -3.5,-1 -4.3,-2.4l-1,-1.6c-0.4,-0.6 -1,-1 -1.7,-1 -0.3,0 -0.5,0.1 -0.8,0.1l-5.2,2.2v4.7h2v-3.4l1.8,-0.7 -1.6,8.1 -4.9,-1 -0.4,2 7,1.4z"/>
</vector>
4 changes: 4 additions & 0 deletions WearTilesKotlin/app/src/main/res/drawable/ic_yoga_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="26"
android:viewportWidth="26" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF00FF" android:fillType="evenOdd" android:pathData="M13,7.583C16.066,7.583 19.381,7.258 22.208,6.5L22.75,8.667C20.735,9.208 18.417,9.566 16.25,9.75L15.167,9.822V14.531L18.417,16.628V24.753H16.25V18.253L12.892,16.086L7.692,24.753H5.417L10.833,14.583V9.822L9.75,9.75C7.583,9.566 5.265,9.208 3.25,8.667L3.792,6.5C6.619,7.258 9.934,7.583 13,7.583ZM15.167,4.333C15.167,5.525 14.192,6.5 13,6.5C11.808,6.5 10.833,5.525 10.833,4.333C10.833,3.142 11.808,2.167 13,2.167C14.192,2.167 15.167,3.142 15.167,4.333Z"/>
</vector>
3 changes: 2 additions & 1 deletion WearTilesKotlin/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ androidx-activity = "1.4.0"
androidx-lifecycle = "2.4.1"
androidx-test = "1.4.0"
androidx-wear-compose = "1.0.0-rc02"
androidx-wear-tiles = "1.1.0-alpha09"
# TODO: Remove the snapshot repo from settings.gradle when this is updated to stable
androidx-wear-tiles = '1.1.0-SNAPSHOT'
compose = "1.2.0-rc03"
horologist = "0.0.27"
ktlint = "0.41.0"
Expand Down
1 change: 1 addition & 0 deletions WearTilesKotlin/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url 'https://androidx.dev/snapshots/builds/8814432/artifacts/repository' }
}
}

Expand Down