3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Tabの中にTabを出す(それもページ全体ではなくコンテンツの1部として)

Last updated at Posted at 2020-01-06

やりたいこと

react-navigatorで普通にネストすると画面いっぱいになります(そうしないやり方もありますが、めんどくさい)。今回やりたいのは画面の一部としてTabコンテンツを利用したい(かつなるべく簡単に)。

react-navigationのtab-navigationを使うより、そのベースになっているreact-native-tab-viewを使う方が簡単らしいので試してみました。

スクリーンショット 2020-01-06 9.56.31.png

準備

私はexpoを使ってるのですが、2020年1月6日現在、いろいろ依存関係の問題などがあるのでモジュールのインストールはやや複雑?です。

場所の確保

まず場所の確保。言語とかはお好みで。

expo init innerTab
cd innerTab

必要モジュールのインストール

navigationの必須モジュール

まず、react-navigationと必須なモジュール。react-navigationのページにある通りにインストールします。

expo install react-navigation react-native-gesture-handler react-native-reanimated react-native-screens

各種ナビゲーション

次に必要なnavigationをインストール。

expo install npm react-navigation-stack react-navigation-tabs   

エラー対応

下記2つのモジュールが無い!とエラーがでるのでインストール。

expo install react-native-safe-area-context @react-native-community/masked-view

内部Tab用モジュールインストール

内部Tabを作成するためのモジュールをインストール。アイコン表示も試したいので追加。

expo install react-native-tab-view react-native-vector-icons

実装

で、実装。まずApp.jsでレイアウトを行います。
全体を包むTab(HomeTab)を作って、そのうちのHome.jsに子Tabを記述します。

なお、私の趣味でStackNavigationでラップしています(必須ではありません)。

App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';

//import screens
import Home from './screens/Home';
import Profile from './screens/Profile';
import Info from './screens/Info';
import News from './screens/News';

//HomeStack
const HomeStack = createStackNavigator(
    {
        Home: {
            screen: Home,
        }
    }
);

const ProfileStack = createStackNavigator(
    {
        Profile: {
            screen: Profile,
        }
    }
);

//HomeTab
const HomeTab = createBottomTabNavigator(
    {
        _Home: {
            screen: HomeStack,
        },
        _Profile: {
            screen: ProfileStack
        }
    }
);

//AppContainer
const AppContainer = createAppContainer(HomeTab);

class App extends React.Component {
    render() {
        return (
            <AppContainer />
        );
    }
}

export default App;

いよいろ本丸の子Tab。普通は分けてもいいのでしょうけど、Home.jsに全部書いちゃいます。

screens/Home.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

import { TabView, TabBar, SceneMap } from 'react-native-tab-view';
import Icon from 'react-native-vector-icons/FontAwesome';
import Info from './Info';
import News from './News';

class Home extends React.Component {

    state = {
        tabIndex: 0,
        tabRoutes: [
            //普通にアイコン表示
            { key: 'info', title: 'お知らせ', renderIcon: (color) => (<Icon size={24} name="home" color={color} />) },
            //titleと横並び(titleは消す)
            { key: 'news', renderIcon: (color) => (<View style={{ flexDirection: "row", alignItems: 'center' }}><Icon size={24} name="cog" color={color} /><Text style={{ marginLeft: 5 }}>aaa</Text></View>) }
        ],
    }

    render() {
        return (
            <View style={{ flex: 1 }} >
                <View style={{ flex: 1 }}>
                    <Text>Content1</Text>
                </View>
                <TabView
                    style={{ flex: 1 }}
                    navigationState={{
                        index: this.state.tabIndex,
                        routes: this.state.tabRoutes,
                    }}
                    renderScene={SceneMap({
                        info: Info,
                        news: News,
                    })}
                    onIndexChange={(index) => this.setState({ tabIndex: index })}
                    renderTabBar={(props) => (
                        <TabBar
                            {...props}
                            style={{ backgroundColor: "#ccc" }}
                            labelStyle={{ color: "#000" }}
                            indicatorStyle={{ backgroundColor: "#A8E9FF", height: "100%" }} //heightを100%にすれば背景色となる・・・
                            renderIcon={({ route, color }) => route.renderIcon(color)}
                            activeColor={"#00f"}
                            inactiveColor={"#aaa"}
                        />
                    )}
                />
            </ View>
        );
    }
}

export default Home;

その他のページはただページ名を中央に表示しているだけ。Info, Profile, Newsなど。。。
書きを参考にscreensフォルダの中に着くるとよいでしょう。

Info.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

class Info extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text>Info</Text>
            </View>
        );
    }
}

export default Info;

以上です。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?