Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

ࣗݾ঺հ • ઋੴ ߊٱ (Sengoku Akihisa) • גࣜձࣾαΠόʔΤʔδΣϯτ • 2018 - 2021 Ξϝʔόϒϩά iOSΤϯδχΞ • 2021- ݱࡏ WINTICKET FlutterΤϯδχΞ 2

Slide 3

Slide 3 text

WINTICKETͰͷΞΫηγϏϦςΟͷऔΓ૊Έ • WINTICKET͸ʮαʔϏεΛ௨ͯ͠୭Ͱ΋ެӦڝٕΛָ͠ΊΔΑ͏ɺ ΞΫηγϏϦςΟͷ޲্ʹ౒Ί͍ͯ·͢ɻʯ • WebͰ͸WCAGͷγϯάϧA΁ͷ४ڌΛ໨ඪͱ͍ͯ͠Δɻ • ݱࡏɺΞϓϦ͸Flutter੡ͷΞϓϦʹϦϓϨʔεΛߦͳ͓ͬͯΓɺͦΕ ʹ൐͍ΞϓϦͷΞΫηγϏϦςΟͷ޲্Λߦͳ͍ͬͯΔ • https://www.cyberagent.co.jp/way/csr/accessibility/ 3

Slide 4

Slide 4 text

ΞδΣϯμ • Flutter ΞΫηγϏϦςΟ • Scale Factor • Suf fi cient Contrast • Screen Reader • ΞΫηγϏϦςΟରԠ 4

Slide 5

Slide 5 text

࿩͞ͳ͍͜ͱ • Flutter for WebͷΞΫηγϏϦςΟ 5

Slide 6

Slide 6 text

Flutter ΞΫηγϏϦςΟ ࢀߟ • Flutter • Flutter.dev Accessibility • iOS • Human Interface Guideline Accessibility • Android • Material Design Accessibility 6

Slide 7

Slide 7 text

Flutter ΞΫηγϏϦςΟ • Large Fonts • ϑΥϯταΠζ͕େ͖͘ͳͬͯ΋σβΠϯ่͕Εͳ͍Α͏ʹ͢Δ • σόΠεͰઃఆ͞Ε͍ͯΔϑΥϯτͷεέʔϧ஋Λ࢖༻ͯ͠ɺΞϓϦ಺ͷϑΥϯ ταΠζ͕ܾఆ͢Δ • Suf fi cient Contrast • ΞϓϦ಺ͷίϯςϯπ͕े෼ͳίϯτϥετൺ͕อͨΕ͍ͯΔ • Screen Reader • εΫϦʔϯϦʔμʔΛ࢖༻ͯ͠ɺΞϓϦͷίϯςϯπΛಡΈ্͛Δ͜ͱ͕Ͱ͖Δ 7

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

σβΠϯσʔλͷαϯϓϧ • λοϓྖҬɿ40px * 40px • IconSizeɿ32px • Paddingɿ4px 4px • IconButton • padding: 4 • Icon: Icon() 12

Slide 13

Slide 13 text

࣮૷ ྫ 4px 13

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

ΞδΣϯμ • Flutter ΞΫηγϏϦςΟ • Scale Factor • Suf fi cient Contrast • Screen Reader • ΞΫηγϏϦςΟରԠ 16

Slide 17

Slide 17 text

System Font Scale 17

Slide 18

Slide 18 text

System Font Scale 18

Slide 19

Slide 19 text

System Font Scale 19

Slide 20

Slide 20 text

System Font Scale • MediaQueryData • ϝσΟΞʢγεςϜʣ৘ใʹ͍ͭͯ • MediaQueryData.textScaleFactor: ϑΥϯτͷεέʔϧൺ • MediaQueryData.size: ΞϓϦ͕දࣔ͞Ε͍ͯΔWindow Size • MediaQueryData.boldText: ϑΥϯτΛଠ͘͢Δࢦఆ • MediaQueryData.highContrast: ίϯτϥετΛ্͛Δࢦఆ 20

Slide 21

Slide 21 text

App Bar Title͕`1.3ͱ2.0ͰมԽ͍ͯ͠ͳ͍ʁ 21

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

Widget Test Passed 26

Slide 27

Slide 27 text

Widget Test Failed 27

Slide 28

Slide 28 text

Error Message 28

Slide 29

Slide 29 text

Error Message 29

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

Fix SizedBoxΛ࡟আ 31

Slide 32

Slide 32 text

Widget Test Failed 32

Slide 33

Slide 33 text

Widget Test Failed 33

Slide 34

Slide 34 text

Error Message 34

Slide 35

Slide 35 text

Fixed 35

Slide 36

Slide 36 text

Widget Test Failed 36

Slide 37

Slide 37 text

࣮૷࣌ͷ஫ҙ఺ • ࣮ࡍʹtextScaleFactorΛมԽͤͯ֬͞ೝͯ͠ΈΔͷ͕Ұ൪ྑ͍😅 • TextͷදࣔྖҬͷߴ͞ or ԣ෯Λݻఆ͍ͯ͠Δ ← ΄΅͜Ε • → PaddingΛ࢖͏ͳͲͯ͠ಈతͳϨΠΞ΢τʹमਖ਼ • → MediaQueryͰWidgetΛWrapͯ͠maxͷtextScaleFactorΛࢦఆ • จݴ͕௕͍έʔε΍2ߦͷέʔε • ยଆͷPadding͕ਖ਼֬ʹઃఆ͞Ε͍ͯͳ͍ 37

Slide 38

Slide 38 text

ิ଍ Display SizeͷରԠ • AndroidͰ͸දࣔαΠζΛมߋ͢Δ͜ͱ͕Ͱ ͖Δ • දࣔαΠζΛมߋ͢Δ͜ͱͰΞϓϦͷදࣔ ͞ΕΔWindowSize͕มΘΔ • Display Sizeখ͘͞ → WindowSize େ͖͘ • Display Sizeେ͖͘ → WindowSize খ͘͞ 38

Slide 39

Slide 39 text

ϨεϙϯγϒͳUI • DisplaySizeΛେ͖͘ʢදࣔྖҬ͕খ͘͞ͳΔʣͱ͖ʹσβΠϯΛҡ࣋ • LayoutBuilder • ImageͷAspectൺͷҡ࣋ • AspectRatio • Document • https://docs. fl utter.dev/development/ui/layout/adaptive- responsive#creating-a-responsive- fl utter-app 39

Slide 40

Slide 40 text

ΞδΣϯμ • Flutter ΞΫηγϏϦςΟ • Scale Factor • Suf fi cient Contrast • Screen Reader 40

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

Contrast Check • Android Ϣʔβʔิॿݕূπʔϧ • https://play.google.com/store/ apps/details? id=com.google.android.apps.ac cessibility.auditor • λοϓྖҬͱίϯτϥετൺͷ֬ೝ ͕Մೳ 42

Slide 43

Slide 43 text

meetsGuideline • widget͕ΞΫηγϏϦςΟΛຬ͍ͨͯ͠Δ͔Λ֬ೝ͢Δ͜ͱ͕Ͱ͖ΔMatcher • AsyncMatcher meetsGuideline(AccessibilityGuideline guideline) • AccessibilityGuideline • textContrastGuideline: ςΩετͷίϯτϥετ • androidTapTargetGuideline: AndroidͷλοϓྖҬ 48 * 48 • iOSTapTargetGuideline: iOSͷλοϓྖҬ 44 * 44 • labeledTapTargetGuideline: λοϓΤϦΞʹηϚϯςΟοΫϥϕϧͷ༗ແ 43

Slide 44

Slide 44 text

textContrastGuideline 44

Slide 45

Slide 45 text

textContrastGuideline 45

Slide 46

Slide 46 text

meetsGuideline • FlutterGalleryͷDemoͷΞΫηγϏ ϦςΟͷςετʹ࢖ΘΕ͍ͯΔ • https://github.com/ fl utter/ fl utter/ blob/ 24207183899d546983873dd6d6e 3b80a2825a982/dev/ integration_tests/ fl utter_gallery/ test/accessibility_test.dart 46

Slide 47

Slide 47 text

ΞδΣϯμ • Flutter ΞΫηγϏϦςΟ • Scale Factor • Suf fi cient Contrast • Screen Reader • ΞΫηγϏϦςΟରԠ 47

Slide 48

Slide 48 text

Screen Reader 48

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

Sample Code • Semantics͸Ͳ͏ͳΔ͔ʁ 54

Slide 55

Slide 55 text

Sample Code 2 ᶃ ᶄ 55

Slide 56

Slide 56 text

Widget Tree and Semantics Tree Card Text Text Button label: 'FlutterKaigi' Label: 'Start' Button: true ɾɾɾলུ Text 56

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

Semantics Class • MergeSemantics: childͷsemanticsΛϚʔδ • ExcludeSemantics: childͷsemanticsΛআ֎ • BlockSemantics: Widgetͷഎޙʹ͋ΔSemanticsΛແޮʢStackͷ WidgetΛҰॹʹ࢖༻Մೳʣ • OrdinalSortKey: ಡΈ্͛ॱংΛorderʹԠͯ͡ιʔτʢSemantics ͷsortKeyʹࢦఆʣ 61

Slide 62

Slide 62 text

SemanticsͷLabelͷ෇͚ํ • WCAG΍WCAGͷୡ੒ํ๏ूΛࢀߟ • https://waic.jp/docs/WCAG21/ • https://waic.jp/docs/WCAG21/Techniques/ • ྫᶃ : ը૾಺ʹίϯςϯπΛཧղ͢ΔͨΊͷจࣈؚ͕·ΕΔ • ಉ͡จࣈΛSemanticsͷLabelʹ෇༩ • ྫᶄɿ૷০໨తͷը૾ • Semanticsͷ৘ใΛ෇༩͠ͳ͍ 62

Slide 63

Slide 63 text

࣮૷࣌ͷ஫ҙ఺ • ࣮ࡍʹ֬ೝͯ͠ΈΔͷ͕Ұ൪ྑ͍😅 • ը૾ • Exclude or Labelͷ෇༩ • CustomWidget • ଐੑͷ෇༩ʢButton, SelectedͳͲʣ • Mergeͯ͠1ͭͷSemanticsNodeͱͯ͠ಡΈ্͛Δ 63

Slide 64

Slide 64 text

ΞδΣϯμ • Flutter ΞΫηγϏϦςΟ • Scale Factor • Suf fi cient Contrast • Screen Reader • ΞΫηγϏϦςΟରԠ 64

Slide 65

Slide 65 text

։ൃͰ͸ʁ ػೳ։ൃ ΞΫηγϏ ϦςΟͷ νΣοΫ ΞΫηγϏ ϦςΟͷ νΣοΫ ΞΫηγϏ ϦςΟͷ νΣοΫ ΞΫηγϏϦ ςΟରԠ ΞΫηγϏϦ ςΟରԠ ΞΫηγϏϦ ςΟରԠ • ݄ʹ1ճͷΞΫηγϏϦςΟΛߦͳ͍ͬͯΔ • ׬੒ͨ͠ػೳ΍ը໘ͷΞΫηγϏϦςΟΛνΣοΫͯ͠ɺͦͷޙ͙͢ ʹमਖ਼ͷରԠΛߦ͏ 65

Slide 66

Slide 66 text

ྑ͔ͬͨ͜ͱ • νʔϜͷΞΫηγϏϦςΟͷϨϕϧ্͕͕Δ • ௨ৗͷ։ൃ͔ΒΞΫηγϏϦςΟΛҙࣝͨ͠ίʔυΛॻ͘͜ͱ͕Ͱ ͖ɺޙ͔ΒͷରԠίετ͕Լ͕Δ • ϨϏϡʔͰͷΞΫηγϏϦςΟͷࢦఠ͕Ͱ͖Δ • UIͷઃܭ࣌ʹΞΫηγϏϦςΟΛߟྀ͢Δ͜ͱ͕Ͱ͖Δ • ڞ௨ͷCustomWidge͸ΞΫηγϏϦςΟରԠࡁΈ 66

Slide 67

Slide 67 text

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