[react-native-router-flux] フォーカスされてるタブのアイコンにアクティブカラーをつける方法


react-native-router-fluxを使ってRouter設計するとき、タブバーUI用にTabsコンポーネントがある。アプリのスクリーン下部にあるナビゲーションUIのことだ。

タブバーデザインにおいてよほどの理由がない限りは、Tabsコンポーネントを使う。UIコンポーネントを利用すれば同様のものが設置できるし、自作タブバーにすることもできるが、わざわざそうする理由もない。なにより遷移設定が面倒くさい。

そんなTabsコンポーネントであるが、アクティブ時のカラーや非アクティブ時のカラーをカスタマイズするpropsがある。これを書き加えることで、タップしたときに色を変えられるわけだ。

しかしアイコン表示において手こずった事案があった。

このエントリーでは、フォーカスされているタブのアイコンにアクティブカラーをつける方法を共有したい。

  • react-native ^0.59.8
  • react-native-router-flux ^4.0.6
  • native-base ^2.13.4

タブバーにアイコンを表示する

まずはRouter設定をする。使うコンポーネントは、

  • <Router>
  • <Tabs>
  • <Scene>

の3つ。タブは「ホーム、カート、設定」を切り替える単純なものを想定している。

export default function AppScreen () {
  return (
    <Router>
      <Tabs
        key='main'
        swipeEnabled={ true }
        animationEnabled={ false }
        tabBarStyle={{backgroundColor:'#F8F8F8'}}
      >
        <Scene
          key="homeScreen"
          component={ HomeScreen }
          title="ホーム"
          tabBarLabel="ホーム"
          navigationBarStyle={{backgroundColor:'#F8F8F8'}}
          icon={() => <Icon active name="home" />} // 👈
        />
        <Scene
          key="cartScreen"
          component={ CartScreen }
          title="カート"
          tabBarLabel="カート"
          navigationBarStyle={{backgroundColor:'#F8F8F8'}}
          icon={() => <Icon active name="ios-basket" />} // 👈
        />
        <Scene
          key="otherScreen"
          component={ OtherScreen }
          title="設定"
          tabBarLabel="設定"
          navigationBarStyle={{backgroundColor:'#F8F8F8'}}
          icon={() => <Icon active name="settings" />} // 👈
        />
      </Tabs>
    </Router>
  );
}

上記ソースコードのコメントアウト行を見てほしい。

各タブにアイコン設置するため、<Icon>を使っている。これはNativeBaseのIconコンポーネントだ。<Scene>にそれぞれ設定することでアイコンが表示される。以下のようになると思う。

つづいては、タブがフォーカスされたときにアクティブカラーを着色する工程だ。

タブがフォーカスされているとき(されていないとき)のカラーを指定する

タブをタップしてフォーカスされたときに、テキストおよびアイコンがアクティブであるとわかるようにカラーを変えたい。

export default function AppScreen () {
  return (
    <Router>
      <Tabs
        key='main'
        swipeEnabled={ true }
        animationEnabled={ false }
        tabBarStyle={{backgroundColor:'#F8F8F8'}}
        activeTintColor="#e17055" // 👈  アクティブのとき
        inactiveTintColor="#a39f9d"// 👈  非アクティブのとき
      >
        ...
      </Tabs>
    </Router>
  );
}

上記ソースコードのコメントアウト行を見てほしい。

activeTintColor propsがアクティブ時のカラーコードで、inactiveTintColor propsが非アクティブ時のカラーコードを設定している。いずれのpropsも文字列を受け付ける。

現在フォーカスされているホームタブのテキストはアクティブカラーになっている。ところが、アイコンのカラーは変わっていない。それもそのはずで、外部のコンポーネントなのだから仕方がない。

<Icon>は、NativeBaseのコンポーネントだった。アイコンのカラーを変更するには、style propsにオブジェクト形式で、CSSを記述すればよい。

export default function AppScreen () {
  return (
    <Router>
      <Tabs
        ...
      >
        <Scene
          key="homeScreen"
          component={ HomeScreen }
          title="ホーム"
          tabBarLabel="ホーム"
          navigationBarStyle={{backgroundColor:'#F8F8F8'}}
          icon={({focused}) => <Icon active name="home" style={{color: focused ? '#e17055' : '#a39f9d'}} />} // 👈
        />
        ...
      </Tabs>
    </Router>
  );
}

上記ソースコードのコメントアウト行を見てほしい。

<Scene>のicon propsに設定した関数の引数から、focusedを受け取っている。これは真偽値が格納されている。つまりタブがフォーカスならtrueというわけだ。

style propsに、focusedがtrueならアクティブカラーで、falseなら非アクティブカラーがを渡している。これにてアイコンにもアクティブカラーを付与することができた。

まとめ

フォーカスされているタブのアイコンにアクティブカラーをつける方法の共有だった。

この内容では、NativeBaseのIconコンポーネントを使っているが、自作のsvgアイコンやほかのUIコンポーネントであっても同様のことができるはずだ。focusedを受け取ってフォーカスか否かを確認して切り替えればよいのだから。

このエントリーが、あなたのクリエイティビティを刺激するものであると期待したい。


Leave a Reply

Your email address will not be published. Required fields are marked *