Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building for Wear OS “Workshop” - Introduction & Part1-

Building for Wear OS “Workshop” - Introduction & Part1-

The workshop slide "Building for Wear OS Workshop - Introduction & Part1"
#wearos #android #workshop

Kenichi Kambara

November 17, 2022
Tweet

More Decks by Kenichi Kambara

Other Decks in Technology

Transcript

  1. Building for Wear OS “Workshop” - Introduction & Part1- Kenichi

    Kambara (@korodroid) 17 November, 2022 2022
  2. Agenda •Part1 (Development) by Kenichi Kambara •Short Session: Developing Apps

    for Wear OS •Workshop: Developing Wear OS Apps •Part2 (Test) by Josh Murigi •Short Session: Writing tests for Wear OS Apps •Workshop: Testing Wear OS Compose Codelab App •Q&A
  3. 3 About me Kenichi Kambara (@korodroid) •Mobile App Development •Speeches

    (e.g. 12 International confs.) •Writings (e.g. 7 Dev Books) •[Of fi cial] Evangelist at NTT TechnoCross •[Private] iplatform.org
  4. About my product (Private works) Sekaiphone Pro(Android/iOS/Wear OS) Wear OS

    version: currently under development
  5. Part1. Workshop Material http://bit.ly/3UWME7M

  6. Wear OS Features  Overlay Noti fi cation Complication Based

    on Android & optimized for the wrist Tile 
  7.  Compose for Wear OS is now 1.0: time to

    build wearable apps with Compose! (27 July, 2022) ref: https://android-developers.googleblog.com/2022/07/compose-for-wear-os-10-stable.html Now Stable!!
  8. Wear OS Apps Development 8

  9.  @Composable fun ChipExample(){ Chip( modifier = Modifier .fillMaxWidth(), icon

    = { Image( painter = painterResource(id = R.drawable.flag_jp), contentDescription = "Japan", ) }, label = {Text(text = “Japan")}, secondaryLabel = {Text(text = "Tokyo")}, onClick = { /* do anything */ }, ) } Implementation Example (Chip)
  10. Very similar to mobile. What’s the difference? 10

  11. Optimized for the wrist: UI & UX Input components Dialogs

    Page Indicator Progress Indicator  Navigation
  12. Characteristics of Wear OS 

  13. Differences on Wear OS & Mobile  Wear OS 


    (androidx.wear.*) Mobile 
 (androidx.*) androidx.wear.compose:compose-material androidx.compose.foundation:foundation androidx.wear.compose:compose-foundation androidx.compose.material:material androidx.navigation:navigation-compose androidx.compose.foundation:foundation ref: https://developer.android.com/training/wearables/compose Material androidx.wear.compose:compose-navigation Navigation Foundation
  14. 14 Compose for Wear OS - Get Started

  15. 15 Wear OS Development Environment  Just my opinion

  16. 16 Wear OS Development Environment 

  17. 17 Create a Wear OS app project  for Jetpack

    Compose
  18. After creating the project 

  19. 19 Live Demo💪 

  20. 20 Preview 

  21. 21 More Previews 

  22. 22 Compose for Wear OS - Workshop

  23. Contact App (First Version)  @Composable fun ContactListScreenV0() { LazyColumn(

    horizontalAlignment = Alignment.CenterHorizontally ) { item { ListHeader { Text(text = "Contacts") } } items(model.data.size) { Chip( modifier = Modifier .fillMaxSize(), icon = { Icon( Icons.Rounded.Face, contentDescription = "faceIcon", ) }, label = { Text(model.data[it]) }, colors = ChipDefaults.primaryChipColors(), onClick = { }, ) } } }
  24. not BAD, but not GOOD… How to make better UI

    for Wear OS? 24
  25. Part1. Workshop (Development)  Start Goal

  26. 5 Steps for improving this App  •Step1. Replacing with

    ScalingLazyColumn •Step2. Using a Scaffold •Step3. Adding a new Screen •Step4. Implementing Navigation •Step5. Replacing with Wear Navigation 

  27. Let’s get started together!!💪 27

  28.  Compose for Wear OS - Get Started Summary

  29.  •Go future with Wear OS & Jetpack Compose🚀 


    •Important to optimize for Wearable Device⌚ •Let’s expand Wear OS World with making apps💪
  30. Please let me know if you have any requests 


    such as technical speeches, technical writings and so on. http://www.linkedin.com/in/korodroid Thank you so much http://fb.com/kanbara.kenichi @korodroid
  31. Let’s move on to Part2! 

  32. 32 Bonus Slides: for your study

  33. Step1. Replacing with ScalingLazyColumn  @Composable fun ContactListScreenV1() { ScalingLazyColumn(

    horizontalAlignment = Alignment.CenterHorizontally ) { item { ListHeader { Text(text = "Contacts") } } items(model.data.size) { Chip( modifier = Modifier .fillMaxSize(), icon = { Icon( Icons.Rounded.Face, contentDescription = "faceIcon", ) }, label = { Text(model.data[it]) }, colors = ChipDefaults.primaryChipColors(), onClick = { }, ) } } }
  34. How should we provide better UI/UX?  TimeText Vignette PositionIndicator

  35. How to implement them? 35

  36. Step2. Using a Scaffold  @Composable fun ContactListScreenV2() { val

    listState = rememberScalingLazyListState() Scaffold( timeText = { if (!listState.isScrollInProgress) { TimeText() } }, vignette = { Vignette( vignettePosition = VignettePosition.TopAndBottom ) }, positionIndicator = { PositionIndicator( scalingLazyListState = listState, ) } ) { ScalingLazyColumn(state = listState) { // … }
  37. Step2-1. TimeText  @Composable fun ContactListScreenV2() { val listState =

    rememberScalingLazyListState() Scaffold( timeText = { if (!listState.isScrollInProgress) { TimeText() } }, vignette = { Vignette( vignettePosition = VignettePosition.TopAndBottom ) }, positionIndicator = { PositionIndicator( scalingLazyListState = listState, ) } ) { ScalingLazyColumn(state = listState) { // … }
  38. Step2-2. Vignette  @Composable fun ContactListScreenV2() { val listState =

    rememberScalingLazyListState() Scaffold( timeText = { if (!listState.isScrollInProgress) { TimeText() } }, vignette = { Vignette( vignettePosition = VignettePosition.TopAndBottom ) }, positionIndicator = { PositionIndicator( scalingLazyListState = listState, ) } ) { ScalingLazyColumn(state = listState) { // … }
  39. Step2-3. PositionIndicator  @Composable fun ContactListScreenV2() { val listState =

    rememberScalingLazyListState() Scaffold( timeText = { if (!listState.isScrollInProgress) { TimeText() } }, vignette = { Vignette( vignettePosition = VignettePosition.TopAndBottom ) }, positionIndicator = { PositionIndicator( scalingLazyListState = listState, ) } ) { ScalingLazyColumn(state = listState) { // … }
  40. How to support multiple screens? 40 

  41. Step3. Adding a new Screen  @Composable fun ContactDetailScreen(id: Int)

    { Chip( modifier = Modifier .fillMaxSize(), icon = { Icon( Icons.Rounded.Face, contentDescription = "faceIcon", ) }, label = { Column( ) { Text(text = model.data[id].name,
 fontWeight = FontWeight.Bold) Text(text = model.data[id].phone) Text(text = model.data[id].nation) } }, colors = ChipDefaults.primaryChipColors(), onClick = { /* do anything */ }, ) }
  42. How to support navigation? 42 

  43. Step4. Implementing Navigation  @Composable fun ScreenNavigation_BadImpl( navController: NavHostController =

    rememberNavController() ) { NavHost( navController = navController, startDestination = "contact_list" ) { composable("contact_list") { ContactListScreenV3(navController = navController) } composable("contact_detail/{id}") { val id = it.arguments?.getString("id")!! ContactDetailScreen(id = id.toInt()) } } }
  44. Step4. Implementing Navigation  @Composable fun ContactListScreenV3(navController: NavHostController) { Scaffold(

    // just same ) { ScalingLazyColumn(state = listState) { item { // just same } items(model.data.size) { Chip( modifier = Modifier.fillMaxSize(), icon = { // just same }, label = { Text(model.data[it].name) }, colors = ChipDefaults.primaryChipColors(), onClick = { navController.navigate("contact_detail/$it") }, ) } } } }
  45. Looks perfect, but one problem remains… 45 

  46. Implementing with Wear Navigation  Wear OS 
 (androidx.wear.*) Mobile

    
 (androidx.*) androidx.navigation:navigation-compose ref: https://developer.android.com/training/wearables/compose/navigation androidx.wear.compose:compose-navigation Navigation <wear>/build.gradle dependencies { def wear_compose_version = "1.0.2" implementation "androidx.wear.compose:compose-navigation:$wear_compose_version" }
  47. Step5. Replacing with Wear Navigation  @Composable fun ScreenNavigation_GoodImpl( navController:

    NavHostController = rememberSwipeDismissableNavController() ) { SwipeDismissableNavHost( navController = navController, startDestination = "contact_list" ) { composable("contact_list") { ContactListScreenV3(navController = navController) } composable("contact_detail/{id}") { val id = it.arguments?.getString("id")!! ContactDetailScreen(id = id.toInt()) } } }