$30 off During Our Annual Pro Sale. View Details »

アクセシビリティが高いFlutterアプリケーションを開発する

100059
November 30, 2021

 アクセシビリティが高いFlutterアプリケーションを開発する

FlutterKaigi2021
2021/11/30 19:45〜 Live レギュラートーク(30分)
https://fortee.jp/flutterkaigi-2021/proposal/d80e1204-3fd5-4c55-b728-83ee1dbf1d01

100059

November 30, 2021
Tweet

More Decks by 100059

Other Decks in Technology

Transcript

  1. ΞΫηγϏϦςΟʔ͕ߴ͍ FlutterΞϓϦέʔγϣϯΛ ։ൃ͢Δ Flutter Kaigi 2021 Day2 1

  2. ࣗݾ঺հ • ઋੴ ߊٱ (Sengoku Akihisa) • גࣜձࣾαΠόʔΤʔδΣϯτ • 2018

    - 2021 Ξϝʔόϒϩά iOSΤϯδχΞ • 2021- ݱࡏ WINTICKET FlutterΤϯδχΞ 2
  3. WINTICKETͰͷΞΫηγϏϦςΟͷऔΓ૊Έ • WINTICKET͸ʮαʔϏεΛ௨ͯ͠୭Ͱ΋ެӦڝٕΛָ͠ΊΔΑ͏ɺ ΞΫηγϏϦςΟͷ޲্ʹ౒Ί͍ͯ·͢ɻʯ • WebͰ͸WCAGͷγϯάϧA΁ͷ४ڌΛ໨ඪͱ͍ͯ͠Δɻ • ݱࡏɺΞϓϦ͸Flutter੡ͷΞϓϦʹϦϓϨʔεΛߦͳ͓ͬͯΓɺͦΕ ʹ൐͍ΞϓϦͷΞΫηγϏϦςΟͷ޲্Λߦͳ͍ͬͯΔ •

    https://www.cyberagent.co.jp/way/csr/accessibility/ 3
  4. ΞδΣϯμ • Flutter ΞΫηγϏϦςΟ • Scale Factor • Suf fi

    cient Contrast • Screen Reader • ΞΫηγϏϦςΟରԠ 4
  5. ࿩͞ͳ͍͜ͱ • Flutter for WebͷΞΫηγϏϦςΟ 5

  6. Flutter ΞΫηγϏϦςΟ ࢀߟ • Flutter • Flutter.dev Accessibility • iOS

    • Human Interface Guideline Accessibility • Android • Material Design Accessibility 6
  7. Flutter ΞΫηγϏϦςΟ • Large Fonts • ϑΥϯταΠζ͕େ͖͘ͳͬͯ΋σβΠϯ่͕Εͳ͍Α͏ʹ͢Δ • σόΠεͰઃఆ͞Ε͍ͯΔϑΥϯτͷεέʔϧ஋Λ࢖༻ͯ͠ɺΞϓϦ಺ͷϑΥϯ ταΠζ͕ܾఆ͢Δ

    • Suf fi cient Contrast • ΞϓϦ಺ͷίϯςϯπ͕े෼ͳίϯτϥετൺ͕อͨΕ͍ͯΔ • Screen Reader • εΫϦʔϯϦʔμʔΛ࢖༻ͯ͠ɺΞϓϦͷίϯςϯπΛಡΈ্͛Δ͜ͱ͕Ͱ͖Δ 7
  8. Flutter Checklist • Active interactions:Ϣʔβͷಈ࡞ʹରͯ͠ͷϑΣʔυόοΫ΍ΞϓϦͷ࣮ߦ݁ՌͷϑΟʔυόοΫ͕͋Δ͔ʁ • Screen reader testing: εΫϦʔϯϦʔμʔΛ࢖༻ͯ͠ΞϓϦΛ࢖༻͢Δ͜ͱ͕Ͱ͖Δ͔ʁ

    • Contrast ratios: ίϯτϥετൺ͕े෼ʹอͨΕ͍ͯΔ͔ʁ • Context switching: Ϣʔβͷ֬ೝͳ͠ͰϢʔβͷίϯςϯπͷมߋ͍ͯ͠ͳ͍͔ʁ • Tappable targets: 48px *48px ͷλοϓྖҬ͕֬อ͞Ε͍ͯΔ͔ʁ • Errors: ΤϥʔͱҰॹʹमਖ਼ํ๏͕Θ͔Δ͔ʁ • Color vision de fi ciency testing: ৭֮ҟৗϞʔυͱάϨʔεέʔϧϞʔυͰ࢖༻ՄೳͰ͋Δ͔ʁ • Scale factors: ϑΥϯταΠζΛେ͖ͯ͘͠΋σβΠϯ่͕Εͳ͍͔ʁ 8
  9. iOSͱAndroidͷΞΫηγϏϦςΟ iOS 44px * 44px 3:1 Voice Over ̋ ×

    Android 48px * 48px 3:1 or 4.5:1(14ptະຬ) Talk Back ̋ ̋ λοϓྖҬ Boldίϯτϥετൺ Screen Reader ϑΥϯταΠζͷมߋ දࣔαΠζͷมߋ 9
  10. Flutter Framework Material • λοϓྖҬͷ࠷খ஋Ͱ͋Δ48px͕ఆٛ͞Ε͍ͯΔ • fl utter / lib

    / src / material / constant.dart • const double kMinInteractiveDimension = 48.0; • MaterialͷIconButtonͰ࢖༻͞Ε͓ͯΓɺσϑΥϧτͰ48pxͷλοϓྖҬ͕ ֬อ͞ΕΔ • fl utter / lib / src / material / icon_button.dart • BoxConstraints(minWidth: _kMinButtonSize, minHeight: _kMinButtonSize) 10
  11. Flutter Framework Cupertino • λοϓྖҬͷ࠷খ஋Ͱ͋Δ44px͕ఆٛ͞Ε͍ͯΔ • fl utter / lib

    / src / cupertino / constraints.dart • const double kMinInteractiveDimensionCupertino = 44.0; • CupertinoButtonͰ࢖༻͞Ε͓ͯΓɺσϑΥϧτͰ44pxͷλοϓྖҬ ͕֬อ͞ΕΔ • fl utter / lib / src / cupertino / button.dart 11
  12. σβΠϯσʔλͷαϯϓϧ • λοϓྖҬɿ40px * 40px • IconSizeɿ32px • Paddingɿ4px 4px

    • IconButton • padding: 4 • Icon: Icon() 12
  13. ࣮૷ ྫ 4px 13

  14. ࣮૷ ྫ IconButtonͷConstraint͸σϑΥϧτͰ48pxͷͨΊɺsizeͱ paddingͷࢦఆͷΈͰ͸࣮૷Ͱ͖ͣɺConstraintͷࢦఆ͕ඞཁ😢 14

  15. ΞΫηγϏϦςΟΛཧղ͓ͯ͘͜͠ͱ Ͱ ΞΫηγϒϧͳΞϓϦ։ൃΛ! 15

  16. ΞδΣϯμ • Flutter ΞΫηγϏϦςΟ • Scale Factor • Suf fi

    cient Contrast • Screen Reader • ΞΫηγϏϦςΟରԠ 16
  17. System Font Scale 17

  18. System Font Scale 18

  19. System Font Scale 19

  20. System Font Scale • MediaQueryData • ϝσΟΞʢγεςϜʣ৘ใʹ͍ͭͯ • MediaQueryData.textScaleFactor: ϑΥϯτͷεέʔϧൺ

    • MediaQueryData.size: ΞϓϦ͕දࣔ͞Ε͍ͯΔWindow Size • MediaQueryData.boldText: ϑΥϯτΛଠ͘͢Δࢦఆ • MediaQueryData.highContrast: ίϯτϥετΛ্͛Δࢦఆ 20
  21. App Bar Title͕`1.3ͱ2.0ͰมԽ͍ͯ͠ͳ͍ʁ 21

  22. App Bar • ࠷େαΠζʢkMaxTitleTextScaleFactor: 1.34ʣΛࢦఆͯ͠σβΠϯΛ ҡ͍࣋ͯ͠Δ 22

  23. App Bar σβΠϯ่͕Εͳ͍Α͏ʹ 23

  24. TextButton • test/material/text_butt • ϑΥϯτͷεέʔϧʹ ΑͬͯTextButtonͷScale ͕มΘΔͷ͔ͷςετ έʔε͕ଘࡏ 24

  25. Example • RowͱColumnͰ࡞ΒΕ ͨΑ͋͘Γͦ͏ͳWidget • ͺͬͱΈ໰୊ͳ͠🙆 25

  26. Widget Test Passed 26

  27. Widget Test Failed 27

  28. Error Message 28

  29. Error Message 29

  30. Error Message • SizedBoxͰߴ͕͞ࢦఆ͞ Ε͓ͯΓɺColumnׂ͕ Γ౰ͯΒΕͨεϖʔεΑ Γ΋޿͘ͳΔͨΊ 30

  31. Fix SizedBoxΛ࡟আ 31

  32. Widget Test Failed 32

  33. Widget Test Failed 33

  34. Error Message 34

  35. Fixed 35

  36. Widget Test Failed 36

  37. ࣮૷࣌ͷ஫ҙ఺ • ࣮ࡍʹtextScaleFactorΛมԽͤͯ֬͞ೝͯ͠ΈΔͷ͕Ұ൪ྑ͍😅 • TextͷදࣔྖҬͷߴ͞ or ԣ෯Λݻఆ͍ͯ͠Δ ← ΄΅͜Ε •

    → PaddingΛ࢖͏ͳͲͯ͠ಈతͳϨΠΞ΢τʹमਖ਼ • → MediaQueryͰWidgetΛWrapͯ͠maxͷtextScaleFactorΛࢦఆ • จݴ͕௕͍έʔε΍2ߦͷέʔε • ยଆͷPadding͕ਖ਼֬ʹઃఆ͞Ε͍ͯͳ͍ 37
  38. ิ଍ Display SizeͷରԠ • AndroidͰ͸දࣔαΠζΛมߋ͢Δ͜ͱ͕Ͱ ͖Δ • දࣔαΠζΛมߋ͢Δ͜ͱͰΞϓϦͷදࣔ ͞ΕΔWindowSize͕มΘΔ •

    Display Sizeখ͘͞ → WindowSize େ͖͘ • Display Sizeେ͖͘ → WindowSize খ͘͞ 38
  39. ϨεϙϯγϒͳUI • DisplaySizeΛେ͖͘ʢදࣔྖҬ͕খ͘͞ͳΔʣͱ͖ʹσβΠϯΛҡ࣋ • LayoutBuilder • ImageͷAspectൺͷҡ࣋ • AspectRatio •

    Document • https://docs. fl utter.dev/development/ui/layout/adaptive- responsive#creating-a-responsive- fl utter-app 39
  40. ΞδΣϯμ • Flutter ΞΫηγϏϦςΟ • Scale Factor • Suf fi

    cient Contrast • Screen Reader 40
  41. Su ffi cient Contrast • 4.5 : 1 • 18ptະຬ

    Regular Text,14ptະຬ Bold Text • 3: 1 • 18ptҎ্ Regular Text,14ptҎ্ ,Bold Text , จࣈը૾ • W3Cͷਪ঑ • https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast- contrast.html 41
  42. Contrast Check • Android Ϣʔβʔิॿݕূπʔϧ • https://play.google.com/store/ apps/details? id=com.google.android.apps.ac cessibility.auditor

    • λοϓྖҬͱίϯτϥετൺͷ֬ೝ ͕Մೳ 42
  43. meetsGuideline • widget͕ΞΫηγϏϦςΟΛຬ͍ͨͯ͠Δ͔Λ֬ೝ͢Δ͜ͱ͕Ͱ͖ΔMatcher • AsyncMatcher meetsGuideline(AccessibilityGuideline guideline) • AccessibilityGuideline •

    textContrastGuideline: ςΩετͷίϯτϥετ • androidTapTargetGuideline: AndroidͷλοϓྖҬ 48 * 48 • iOSTapTargetGuideline: iOSͷλοϓྖҬ 44 * 44 • labeledTapTargetGuideline: λοϓΤϦΞʹηϚϯςΟοΫϥϕϧͷ༗ແ 43
  44. textContrastGuideline 44

  45. textContrastGuideline 45

  46. meetsGuideline • FlutterGalleryͷDemoͷΞΫηγϏ ϦςΟͷςετʹ࢖ΘΕ͍ͯΔ • https://github.com/ fl utter/ fl utter/

    blob/ 24207183899d546983873dd6d6e 3b80a2825a982/dev/ integration_tests/ fl utter_gallery/ test/accessibility_test.dart 46
  47. ΞδΣϯμ • Flutter ΞΫηγϏϦςΟ • Scale Factor • Suf fi

    cient Contrast • Screen Reader • ΞΫηγϏϦςΟରԠ 47
  48. Screen Reader 48

  49. Semantics Widget • WidgetʹηϚϯςΟοΫʢҙຯʣ৘ใΛ෇༩͢Δ • VoiceOver΍TalkbackͳͲͷࢧԉπʔϧͰ༻͍ΒΕΔ • labelҎ֎ʹ΋༷ʑͳҙຯ৘ใΛ෇༩Մೳ 49

  50. Semantics Tree • WidgetTreeΛ࡞੒͢ΔͱSemanticsTree͕ੜ੒͞ΕΔ • WidgetTreeͱSemanticsTree͸1ର̍ͰରԠ͸͍ͯ͠ͳ͍ • Semantics৘ใΛอ͍࣋ͯ͠ͳ͍Widget΍ෳ਺ͷWidget͕Ϛʔδ͞ΕΔͨΊ WidgetTree SemanticsTree

    50
  51. Semantics Node • SemanticsWidgetΛ࢖͏͜ͱͰSemanticsNodeΛੜ੒͢Δ͜ͱ͕Ͱ͖Δ • SemanticsNodeʹ͸SemanticsWidgetͰ෇༩ͨ͠ҙຯ৘ใ͕ؔ࿈෇͚Β Ε͍ͯΔ SemanticsNode - Label:

    `Flutter` - Button: true - Enable: true 51
  52. Flutter Skelton Template • ύοέʔδͷதͰ͸ SemanticsͷWidget͸ ࢖ΘΕ͍ͯͳ͍ • ͏·͘εΫϦʔϯϦʔ μʔͰಡΈ্͛Մೳʁ

    52
  53. Material IconButton • Semantics͕࢖ΘΕ͓ͯΓɺ Semantic৘ใ͕෇༩͞Ε͍ͯΔ • ଞͷWidget΋IconButtonಉ༷ʹ ద੾ͳSemantic৘ใΛอ࣋ & ઃ

    ఆͰ͖ΔΑ͏ʹͳ͍ͬͯΔ 53
  54. Sample Code • Semantics͸Ͳ͏ͳΔ͔ʁ 54

  55. Sample Code 2 ᶃ ᶄ 55

  56. Widget Tree and Semantics Tree Card Text Text Button label:

    'FlutterKaigi' Label: 'Start' Button: true ɾɾɾলུ Text 56
  57. Semantics Widget Property • bool container (default false) • trueͷ৔߹ʹ৽͍͠SemanticsNodeΛੜ੒͢Δ

    • falseͷ৔߹͸਌ͷSemanticsNodeʹϚʔδ͞ΕΔʢ਌͕ڐՄ͍ͯ͠Δ৔߹ʣ • bool explicitChildNodes (default false) • trueͷ৔߹͸ࢠͷSemanticsNodeΛࣗ਎ͷSemanticsNodeʹϚʔδ͕ෆՄʹͳΔ • falseͷ৔߹͸Ϛʔδ͢Δ͜ͱ͕Մೳ • bool excludeSemantics (default false) • trueͷ৔߹ʹchildͷSemanticsNodeΛআ֎͢Δ 57
  58. Widget Tree and Semantics Tree Card container: true Text label

    'Flutter' label: 'FlutterKaigi' Button: true Label: 'Start' ɾɾɾলུ Text label 'Kaigi' Button container: true button: true Text label 'Start!' 58
  59. Widget Tree and Semantics Tree Card container: true Text label

    'Flutter' label: 'FlutterKaigi' ɾɾɾলུ Text label 'Kaigi' Button container: true button: true Text label 'Start!' merge merge Button: true Label: 'Start!' 59
  60. ExplicitChildNodes Card container: true explicitChildNodes: true Text label 'Flutter' Button:

    true Label: 'Start' ɾɾɾলུ Text label 'Kaigi' Button container: true button: true Text label 'Start!' Label: 'Kaigi' Label: 'Flutter' 60
  61. Semantics Class • MergeSemantics: childͷsemanticsΛϚʔδ • ExcludeSemantics: childͷsemanticsΛআ֎ • BlockSemantics:

    Widgetͷഎޙʹ͋ΔSemanticsΛແޮʢStackͷ WidgetΛҰॹʹ࢖༻Մೳʣ • OrdinalSortKey: ಡΈ্͛ॱংΛorderʹԠͯ͡ιʔτʢSemantics ͷsortKeyʹࢦఆʣ 61
  62. SemanticsͷLabelͷ෇͚ํ • WCAG΍WCAGͷୡ੒ํ๏ूΛࢀߟ • https://waic.jp/docs/WCAG21/ • https://waic.jp/docs/WCAG21/Techniques/ • ྫᶃ :

    ը૾಺ʹίϯςϯπΛཧղ͢ΔͨΊͷจࣈؚ͕·ΕΔ • ಉ͡จࣈΛSemanticsͷLabelʹ෇༩ • ྫᶄɿ૷০໨తͷը૾ • Semanticsͷ৘ใΛ෇༩͠ͳ͍ 62
  63. ࣮૷࣌ͷ஫ҙ఺ • ࣮ࡍʹ֬ೝͯ͠ΈΔͷ͕Ұ൪ྑ͍😅 • ը૾ • Exclude or Labelͷ෇༩ •

    CustomWidget • ଐੑͷ෇༩ʢButton, SelectedͳͲʣ • Mergeͯ͠1ͭͷSemanticsNodeͱͯ͠ಡΈ্͛Δ 63
  64. ΞδΣϯμ • Flutter ΞΫηγϏϦςΟ • Scale Factor • Suf fi

    cient Contrast • Screen Reader • ΞΫηγϏϦςΟରԠ 64
  65. ։ൃͰ͸ʁ ػೳ։ൃ ΞΫηγϏ ϦςΟͷ νΣοΫ ΞΫηγϏ ϦςΟͷ νΣοΫ ΞΫηγϏ ϦςΟͷ

    νΣοΫ ΞΫηγϏϦ ςΟରԠ ΞΫηγϏϦ ςΟରԠ ΞΫηγϏϦ ςΟରԠ • ݄ʹ1ճͷΞΫηγϏϦςΟΛߦͳ͍ͬͯΔ • ׬੒ͨ͠ػೳ΍ը໘ͷΞΫηγϏϦςΟΛνΣοΫͯ͠ɺͦͷޙ͙͢ ʹमਖ਼ͷରԠΛߦ͏ 65
  66. ྑ͔ͬͨ͜ͱ • νʔϜͷΞΫηγϏϦςΟͷϨϕϧ্͕͕Δ • ௨ৗͷ։ൃ͔ΒΞΫηγϏϦςΟΛҙࣝͨ͠ίʔυΛॻ͘͜ͱ͕Ͱ ͖ɺޙ͔ΒͷରԠίετ͕Լ͕Δ • ϨϏϡʔͰͷΞΫηγϏϦςΟͷࢦఠ͕Ͱ͖Δ • UIͷઃܭ࣌ʹΞΫηγϏϦςΟΛߟྀ͢Δ͜ͱ͕Ͱ͖Δ

    • ڞ௨ͷCustomWidge͸ΞΫηγϏϦςΟରԠࡁΈ 66
  67. ·ͱΊ • ։ൃதͷΞϓϦͷΞΫηγϏϦςΟΛνΣοΫͯ͠ΈΑ͏ • ೔ࠒ͔ΒΞΫηγϏϦςΟΛߟྀͨ͠։ൃΛߦ͏͜ͱͰɺগͳ͍ίε τͰΞΫηγϏϦςΟ͕ߴ͍ΞϓϦͷ։ൃ͕Մೳ 67