Slide 1

Slide 1 text

Building Accessible Apps with Jetpack Compose

Slide 2

Slide 2 text

Why Number increase dramatically if we take temporary and situational disabilities into our account 2

Slide 3

Slide 3 text

Why does it matter? It’s very important to do accessibility and then enforced by law in Europe Country 3

Slide 4

Slide 4 text

Minimal Touch/ Pointer Target 4 ● Minimal 48 x 48 dp ● minimumInteractiveComponentSize() modifier extension

Slide 5

Slide 5 text

README.md πŸ“ Blueprint Visualize the dimensions of your composables on a blueprint dependencies { debugImplementation("com.github.popovanton0.blueprint:blueprint:1.0.0-alpha04") releaseImplementation("com.github.popovanton0.blueprint:blueprint-no-op:1.0.0-alpha04") } 5 popovanto0/ Blueprint code issue pull-request

Slide 6

Slide 6 text

BluePrint Preview 6

Slide 7

Slide 7 text

Mouse Support 7

Slide 8

Slide 8 text

Font Scale 8

Slide 9

Slide 9 text

9 Font Scale ● @Preview (fontScale = 2f) ● Modifier.verticalScroll(rememberScrollState) ● maxLines = … ● overflow = TextOverflow.Ellipsis ● Or overflow = TextOverflow.Visible

Slide 10

Slide 10 text

TextOverFlow 10 Text( modifier = Modifier.background(Color.Cyan).size(20.dp), text = "Visible", overflow = TextOverflow.Visible, ) Text( modifier = Modifier.size(20.dp).background(Color.Yellow), text = "Ellipsis", overflow = TextOverflow.Ellipsis, ) Text( modifier = Modifier.background(Color.Green).size(20.dp), text = "Clip", overflow = TextOverflow.Clip, ) Vi si bl e El. Cli

Slide 11

Slide 11 text

Focus Order 11 To ensure that app is usable when the user navigates with such keystrokes, you have to check the focus order. Pressing the Tab or arrow keys should move the focus in a logical order. A focus can also move due to the IME (Input Method Editor) action on the on-screen keyboard.

Slide 12

Slide 12 text

Focus Order 12 ● Add focusRequester and focusProperties modifiers ● Adding the Next IME action won’t add reactions to Enter and Tab keystrokes. ● Alternatively, use the onPreviewKeyEvent

Slide 13

Slide 13 text

Focus Order 13 val (firstNameField, lastNameField, emailField) = remember { FocusRequester.createRefs() } TextField( modifier = Modifier .focusRequester(firstNameField) .focusProperties { next = lastNameField }, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), ) TextField( modifier = Modifier .focusRequester(lastNameField) .focusProperties { next = emailField }, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), ) TextField( modifier = Modifier .focusRequester(emailField) .focusProperties { next = firstNameField }, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), )

Slide 14

Slide 14 text

IME Actions 14 ● Next ● Send ● Search ● Previous ● Go

Slide 15

Slide 15 text

IME Actions 15 TextField( keyboardOptions = KeyboardOptions(imeAction = ImeAction.Send), keyboardActions = KeyboardActions( onSend = { // send the form to the server } ), onValueChange = {}, value = "First name", )

Slide 16

Slide 16 text

TalkBack 16 ● Drag, SIngle tap to move focus with Finger ● Double tap to click! ● Swipe right to move focus forward(left - backward) ● Swipe down then right (L-shape) to show TalkBack menu ● Many more gestures

Slide 17

Slide 17 text

Switch 17 var isEnabled by remember {mutableStateOf(false)} Row( modifier = Modifier ) { Text(text = "Newsletter") Switch(checked=isNewsletterEnabled) }

Slide 18

Slide 18 text

Accessible Switch 18 var isEnabled by remember {mutableStateOf(false)} Row( modifier = Modifier .toggleable( value = isNewsletterEnabled, onValueChange = {isEnabled = isChecked }, role = Role.Switch) ) { Switch(checked=isNewsletterEnabled) }

Slide 19

Slide 19 text

Anatomy of the label 19 Showing the announcing label procedure in Talkback

Slide 20

Slide 20 text

Modifier.semantics 20 Modifier.semantics { stateDescription = if (isNewsletterEnabled) "Enabled" else "Disabled" onClick( label = "toggle newsletter subscription", action = null ) }

Slide 21

Slide 21 text

Content description 21 Icon( imageVector = Icons.Filled.Check, contentDescription = "Access Granted" ) contentDescription = "" contentDescription = null Access granted, Image Unlabelled, Image Ignored by TalkBack

Slide 22

Slide 22 text

Image Labels 22 Green β†’ needs a label Red β†’ doesn’t need a label

Slide 23

Slide 23 text

Merging descendants 23 Row(modifier = Modifier){ Text(text = "Thaw") Spacer(Modifier.width(4.dp)) Icon( imageVector = Icons.Default.Check, contentDescription = null ) } Row( modifier = Modifier .semantics(mergeDescendants = true) {} ) Materials Materials

Slide 24

Slide 24 text

Custom Actions 24 .semantics { customActions = listOf( CustomAccessibilityAction( label = "Delete item", action = ::deleteItem ), CustomAccessibilityAction( label = "Archive item", action = ::archiveItem ) ) }

Slide 25

Slide 25 text

Live Regions 25 TalkBack announces live region on change even if it is not focused Row( Modifier = Modifier.semantics { liveRegion = LiveRegionMode.Polite contentDescription = dateFormatter.format(date) } ) { Text(text = date) // Next and Previous Button Code } January 2023 February 2023

Slide 26

Slide 26 text

Color blindness 26

Slide 27

Slide 27 text

Color blindness Preview 27

Slide 28

Slide 28 text

Color blindness 28

Slide 29

Slide 29 text

Color blindness 29

Slide 30

Slide 30 text

Use Material Design Guideline as much as possible 30

Slide 31

Slide 31 text

31 Thanks!

Slide 32

Slide 32 text

Learn more about Accessibility 32 ● Web content Accessibility guidelines ● Android Accessibility by tutorials - droidcon ● Universal Design Principles & Material Design Guidelines β—‹ Equitable of use β—‹ Flexibility of use β—‹ Simple and Intuitive use β—‹ Perceptible of information β—‹ Fault tolerant β—‹ Low physical effort β—‹ Size and space for approach

Slide 33

Slide 33 text

Thank you! Mobile Android Developer Thaw Zin Toe Pe Tut thawzintoe-ptut @thaw_zin_toe