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

TabBarの色を変えたかっただけなのに

 TabBarの色を変えたかっただけなのに

Flutter Meetup Tokyo #15

FlutterのTabBarの背景色を変たい、と思ったらMaterialやInkの話、そしてTabBarのIndicatorの話まで広がりました。

スライドの最後に紹介しているリンクをこちらにも貼っておきます。
https://qiita.com/mkosuke/items/3e33d71ef4de74364f87
https://qiita.com/mkosuke/items/e506256515179d0f421b

kosuke matsumura

March 18, 2021
Tweet

More Decks by kosuke matsumura

Other Decks in Technology

Transcript

  1. About Me • দଜߤ༟(Kosuke Matsumura) • NAVITIME JAPAN Co., Ltd.

    
 ɹAndroid / iOS • JϦʔά(઒࡚ϑϩϯλʔϨ)αϙʔλʔ • Twitter 
 m.kosuke @kosuke_mtm ɾϓϩμΫτ͕ଟ༷͘ʑͳαʔϏεΛܦݧͰ͖Δʂ ɾ৽نΞϓϦ্ཱͪ͛΍ϦχϡʔΞϧʹࢀըͰ͖Δνϟϯε͕ଟ͍
  2. جຊతͳTabBar @override Widget build(BuildContext context) { return DefaultTabController( length: 2,

    child: Scaffold( appBar: AppBar( title: Text('AppBar'), bottom: TabBar( tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), body: TabBarView( children: [ Page1(), Page2(), ], ), ), ); } "QQ#BS 5BC#BS 5BC#BS7JFX
  3. جຊతͳTabBar @override Widget build(BuildContext context) { return DefaultTabController( length: 2,

    child: Scaffold( appBar: AppBar( title: Text('AppBar'), bottom: TabBar( tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), body: TabBarView( children: [ Page1(), Page2(), ], ), ), ); } "QQ#BS 5BC#BS 5BC#BS7JFX
  4. جຊతͳTabBar @override Widget build(BuildContext context) { return DefaultTabController( length: 2,

    child: Scaffold( appBar: AppBar( title: Text('AppBar'), bottom: TabBar( tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), body: TabBarView( children: [ Page1(), Page2(), ], ), ), ); } "QQ#BS 5BC#BS 5BC#BS7JFX
  5. جຊతͳTabBar @override Widget build(BuildContext context) { return DefaultTabController( length: 2,

    child: Scaffold( appBar: AppBar( title: Text('AppBar'), bottom: TabBar( tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), body: TabBarView( children: [ Page1(), Page2(), ], ), ), ); } "QQ#BS 5BC#BS 5BC#BS7JFX
  6. جຊతͳTabBar @override Widget build(BuildContext context) { return DefaultTabController( length: 2,

    child: Scaffold( appBar: AppBar( title: Text('AppBar'), bottom: TabBar( tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), body: TabBarView( children: [ Page1(), Page2(), ], ), ), ); } "QQ#BS 5BC#BS QSJNBSZ$PMPS JOEJDBUPS$PMPS
  7. جຊతͳTabBar "QQ#BS 5BC#BS QSJNBSZ$PMPS 5BC#BSʹഎܠ৭Λઃఆ͢Δ*'͸ͳ͍ const TabBar({ Key key, @required

    this.tabs, this.controller, this.isScrollable = false, this.indicatorColor, this.indicatorWeight = 2.0, this.indicatorPadding = EdgeInsets.zero, this.indicator, this.indicatorSize, this.labelColor, this.labelStyle, this.labelPadding, this.unselectedLabelColor, this.unselectedLabelStyle, this.dragStartBehavior = DragStartBehavior.s this.mouseCursor, this.onTap, this.physics, }) 5BC#BSͷ৭Λม͍͑ͨʂ ͱ͍͏ͷ͕ࠓճͷओ୊Ͱ͢ɻ
  8. TabBarͷഎܠ৭Λม͍͑ͨ $PMPSFE#PYͳͲΛ5BC#BSͷԼʹෑ͘ DefaultTabController( length: 2, child: Scaffold( appBar: AppBar( title:

    Text('Title'), bottom: PreferredSize( preferredSize: Size.fromHeight(72), child: ColoredBox( color: Colors.redAccent, child: TabBar( tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), ), ), body: TabBarView( children: [ Page1(), Page2(), ], ), ), $PMPSFE#PYͰ5BC#BSΛғΊ͹0,ʂ
  9. TabBarͷഎܠ৭Λม͍͑ͨ $PMPSFE#PYͳͲΛ5BC#BSͷԼʹෑ͘ DefaultTabController( length: 2, child: Scaffold( appBar: AppBar( title:

    Text('Title'), bottom: PreferredSize( preferredSize: Size.fromHeight(72), child: ColoredBox( color: Colors.redAccent, child: TabBar( tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), ), ), body: TabBarView( children: [ Page1(), Page2(), ], ), ), 3JQQMF& ff FDU͕ දࣔ͞Εͳ͍
  10. Ripple Effect͸ʮഎܠʯ ʲ.BUFSJBMͷ্ʹෆಁ໌ͳ8JEHFU͕͋Δ৔߹ʳ "QQ#BS .BUFSJBM 5BC#BS *OL8FMM ɹ$PMPSFE#PY͕अຐͰ3JQQMF& ff FDU͕ݟ͑ͳ͍

    ɹ͜ͷ.BUFSJBMͷ্Ͱ3JQQMF& ff FDU͕ඳը͞ΕΔ λονΠϕϯτ͕*OL8FMM͔Β .BUFSJBM΁఻͑ΒΕΔ $PMPSFE#PY
  11. Ripple Effect΋ޮ͔ͤͭͭɺTabBarͷഎܠ৭Λม͍͑ͨ DefaultTabController( length: 2, child: Scaffold( appBar: AppBar( title:

    Text('Title'), bottom: PreferredSize( preferredSize: Size.fromHeight(72), child: ColoredBox( color: Colors.redAccent, child: TabBar( indicatorColor: Colors.amber, tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), ), ), body: TabBarView( children: [ Page1(), Page2(),
  12. Ripple Effect΋ޮ͔ͤͭͭɺTabBarͷഎܠ৭Λม͍͑ͨ  $PMPSFE#PYͷ୅ΘΓʹɺ 
 *OLͰ5BC#BSΛғΉ  *OLͰഎܠ৭Λࢦఆ͢Δ DefaultTabController( length:

    2, child: Scaffold( appBar: AppBar( title: Text('Title'), bottom: PreferredSize( preferredSize: Size.fromHeight(72), child: ColoredBox( color: Colors.redAccent, child: TabBar( indicatorColor: Colors.amber, tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), ), ), body: TabBarView( children: [ Page1(), Page2(), child: Ink(
  13. Ripple Effect΋ޮ͔ͤͭͭɺTabBarͷഎܠ৭Λม͍͑ͨ "QQ#BS .BUFSJBM 5BC#BS *OL8FMM ɹ͜ͷ.BUFSJBMͷ্Ͱ%FDPSBUJPO͕ඳը͞ΕΔ λονΠϕϯτͷ3JQQMF& ff FDU΋

    มΘΒͣ.BUFSJBMͷ্ *OL ஫ʣ͜ͷ৔߹΋ɺ.BUFSJBMͷ্ʹ ෆಁ໌ͳ8JEHFUΛ͓͘͜ͱ͸ग़དྷͳ͍ ʲ*OLͷ໾ׂʳ
  14. ׬੒ʁ DefaultTabController( length: 2, child: Scaffold( appBar: AppBar( title: Text('Title'),

    bottom: PreferredSize( preferredSize: Size.fromHeight(72), child: Ink( color: Colors.redAccent, child: TabBar( indicatorColor: Colors.amber, tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), ), ), body: TabBarView( children: [ Page1(), Page2(), ], JOEJDBUPS$PMPSͷԫ৭͕ 
 ൓ө͞Εͣɺന͘ͳ͍ͬͯΔ
  15. IndicatorColorͷṖ Decoration get _indicator { if (widget.indicator != null) return

    widget.indicator; final TabBarTheme tabBarTheme = TabBarTheme.of(context); if (tabBarTheme.indicator != null) return tabBarTheme.indicator; Color color = widget.indicatorColor ?? Theme.of(context).indicatorColor; // ThemeData tries to avoid this by having indicatorColor avoid being the // primaryColor. However, it's possible that the tab bar is on a // Material that isn't the primaryColor. In that case, if the indicator // color ends up matching the material's color, then this overrides it. // When that happens, automatic transitions of the theme will likely look // ugly as the indicator color suddenly snaps to white at one end, but it's // not clear how to avoid that any further. // // The material's color might be null (if it's a transparency). In that case // there's no good way for us to find out what the color is so we don't. if (color.value == Material.of(context).color?.value) color = Colors.white; 5BC#BSͷதͷɺJOEJDBUPSͷॲཧ 'MVUUFSҎલ IUUQTHJUIVCDPN fl VUUFS fl VUUFSCMPCQBDLBHFT fl VUUFSMJCTSDNBUFSJBMUBCTEBSU
  16. IndicatorColorͷṖ Decoration get _indicator { if (widget.indicator != null) return

    widget.indicator; final TabBarTheme tabBarTheme = TabBarTheme.of(context); if (tabBarTheme.indicator != null) return tabBarTheme.indicator; Color color = widget.indicatorColor ?? Theme.of(context).indicatorColor; // ThemeData tries to avoid this by having indicatorColor avoid being the // primaryColor. However, it's possible that the tab bar is on a // Material that isn't the primaryColor. In that case, if the indicator // color ends up matching the material's color, then this overrides it. // When that happens, automatic transitions of the theme will likely look // ugly as the indicator color suddenly snaps to white at one end, but it's // not clear how to avoid that any further. // // The material's color might be null (if it's a transparency). In that case // there's no good way for us to find out what the color is so we don't. if (color.value == Material.of(context).color?.value) color = Colors.white; *OEJDBUPS$PMPS͕QSJNBSZ$PMPSͱҰக͢Δ৔߹ɺ നͰ্ॻ͖͍ͯ͠Δ 5BC#BSͷதͷɺJOEJDBUPSͷॲཧ 'MVUUFSҎલ
  17. IndicatorColorͷṖ Decoration get _indicator { if (widget.indicator != null) return

    widget.indicator; final TabBarTheme tabBarTheme = TabBarTheme.of(context); if (tabBarTheme.indicator != null) return tabBarTheme.indicator; Color color = widget.indicatorColor ?? Theme.of(context).indicatorColor; // ThemeData tries to avoid this by having indicatorColor avoid being the // primaryColor. However, it's possible that the tab bar is on a // Material that isn't the primaryColor. In that case, if the indicator // color ends up matching the material's color, then this overrides it. // When that happens, automatic transitions of the theme will likely look // ugly as the indicator color suddenly snaps to white at one end, but it's // not clear how to avoid that any further. // // The material's color might be null (if it's a transparency). In that case // there's no good way for us to find out what the color is so we don't. if (color.value == Material.of(context).color?.value) color = Colors.white; *OEJDBUPS$PMPS͕QSJNBSZ$PMPSͱҰக͢Δ৔߹ɺ നͰ্ॻ͖͍ͯ͠Δ JOEJDBUPS͸جຊతʹQSJNBSZ$PMPSͷ ্ʹඳը͞ΕΔ͜ͱΛ૝ఆ͍ͯ͠ΔͨΊɺ ࣗવͳڍಈ 5BC#BSͷதͷɺJOEJDBUPSͷॲཧ 'MVUUFSҎલ
  18. IndicatorColorͷṖ Decoration get _indicator { …(ུ) Color color = widget.indicatorColor

    ?? Theme.of(context).indicatorColor; // ThemeData tries to avoid this by having indicatorColor avoid being the // primaryColor. However, it's possible that the tab bar is on a // Material that isn't the primaryColor. In that case, if the indicator // color ends up matching the material's color, then this overrides it. // When that happens, automatic transitions of the theme will likely look // ugly as the indicator color suddenly snaps to white at one end, but it's // not clear how to avoid that any further. // // The material's color might be null (if it's a transparency). In that case // there's no good way for us to find out what the color is so we don't. // // TODO(xu-baolin): Remove automatic adjustment to white color indicator // with a better long-term solution. // https://github.com/flutter/flutter/pull/68171#pullrequestreview-517753917 if (widget.automaticIndicatorColorAdjustment && color.value == Material.of(context)?.color?.value) color = Colors.white; 5BC#BSͷதͷɺJOEJDBUPSͷॲཧ 'MVUUFSd IUUQTHJUIVCDPN fl VUUFS fl VUUFSCMPCQBDLBHFT fl VUUFSMJCTSDNBUFSJBMUBCTEBSU 50%0ίϝϯτͱҰॹʹϑϥά͕௥Ճ͞Ε͍ͯΔ
  19. IndicatorColorͷṖ /// Whether this tab bar should automatically adjust the

    [indicatorColor]. /// /// If [automaticIndicatorColorAdjustment] is true, /// then the [indicatorColor] will be automatically adjusted to [Colors.white] /// when the [indicatorColor] is same as [Material.color] of the [Material] parent widget. final bool automaticIndicatorColorAdjustment; BVUPNBUJD*OEJDBUPS$PMPS"EKVTUNFOUͱ͍͏ϑϥά͕௥Ճ USVFͷ৔߹͸طଘͷΑ͏ʹɺJOEJDBUPS$PMPSQSJNBSZ$PMPSͷ৔߹ʹ JOEJDBUPS$PMPSΛࣗಈͰനʹ͢ΔڍಈʹͳΔɻ ͜ΕΛ๷͍͗ͨ৔߹͸ɺϑϥάΛGBMTFʹ͢Δ͜ͱͰରԠՄೳ
  20. IndicatorColorΛ൓өͤ͞ΔͨΊʹ  *OLͰ͸ͳ͘ɺ.BUFSJBM΢ΟδΣοτΛ࢖͏ DefaultTabController( length: 2, child: Scaffold( appBar: AppBar(

    title: Text('Title'), bottom: PreferredSize( preferredSize: Size.fromHeight(72), child: Ink( child: Material( color: Colors.redAccent, child: TabBar( indicatorColor: Colors.amber, tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ), ), ), ), body: TabBarView( 5BC#BS͕ࢀর͢Δ.BUFSJBMͷ DPMPS͕มΘͬͨͨΊɺ JOEJDBUPS$PMPS͕ന্͘ॻ͖͞ Εͳ͍
  21. IndicatorColorΛ൓өͤ͞ΔͨΊʹ  *OEJDBUPSΛ%FDPSBUJPOͱͯ͠ઃఆ͢Δ DefaultTabController( length: 2, child: Scaffold( appBar: AppBar(

    title: Text('Title'), bottom: PreferredSize( preferredSize: Size.fromHeight(72), child: Ink( color: Colors.redAccent, child: TabBar( indicatorColor: Colors.amber, indicator: UnderlineTabIndicator( borderSide: BorderSide( width: 2, color: Colors.amber, ), ), tabs: [ Tab(child: Text('Tab A')), Tab(child: Text('Tab B')), ], ࣗલͰ%FDPSBUJPOΛ࡞Ε͹ɺ ࣗಈͰന্͘ॻ͖͞ΕΔ͜ͱ΋ ͳ͍
  22. Summary • Ripple Effect͸Material΢ΟδΣοτͷ্Ͱඳը͞ΕΔͨΊɺ 
 Material΢ΟδΣοτͷ্ʹෆಁ໌ͳ΢ΟδΣοτ͕ଘࡏ͢Δͱ 
 Ripple Effect͕ݟ͑ͳ͘ͳͬͯ͠·͏ •

    ରԠํ๏ͱͯ͠͸ɺෆಁ໌ͳ΢ΟδΣοτΛInkͰ୅ସ͢Δɺ 
 ·ͨ͸Material΢ΟδΣοτΛ഑ஔ͢Δ • TabBarͷIndicator͸ɺMaterial΢ΟδΣοτͷcolorͱಉ͡৭ʹઃఆ͢Δͱ 
 ࣗಈతʹന͘ͳͬͯ͠·͏ͷͰ஫ҙ