0
0

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 3 years have passed since last update.

背景の見えるポップアップスクリーンの作り方

Posted at

背景が見えるモーダル画面って個人的には好きです。
今回はその作成方法を紹介します。
output.gif

使用ライブラリ

  • @react-navigation/stack
  • @react-navigation/native
  • react-native-safe-area-context
  • react-native-linear-gradient
  • styled-components

透過するモーダルページ(外枠)の作成

const TransparentModalPage: React.FunctionComponent = ({ children }) => {
  const navigation = useNavigation();
  return (
    <LinearGradient
      colors={['rgba(0,0,0,0)', 'rgba(0,0,0,0.9)']}
      style={{ flex: 1 }}
    >
      <TouchableWithoutFeedback
        style={{ flex: 1, alignSelf: 'stretch' }}
        onPress={() => navigation.goBack()}
      >
        <View style={{ flex: 1 }} />
      </TouchableWithoutFeedback>

      <View style={{ justifyContent: 'center' }}>{children}</View>
    </LinearGradient>
  );
};

ToucableWithoutFeedbackの部分で、子要素のモーダルコンテンツ(children)以外をタップした場合に、ページを閉じるように設定しています。

モーダルのコンテンツを作成

const RoundView = styled(View)`
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
  background-color: 'rgba(255,255,255,1)';
`;

export const ModalCard: React.FunctionComponent = ({ children }) => {
  return (
    <RoundView>
      <View style={{ paddingVertical: 16 }}>
        <View
          style={{
            alignSelf: 'center',
            width: 50,
            borderBottomWidth: 3,
            borderBottomColor: 'rgba(0,0,0,1)',
            borderRadius: 8,
          }}
        />
      </View>

      <View style={{ paddingHorizontal: 32, paddingBottom: 32 }}>
        {children}
      </View>

      {/* To avoid a typescript error. */}
      <SafeAreaView>
        <></>
      </SafeAreaView>
    </RoundView>
  );
};

SafeAreaViewは、モーダル部分が下に詰めすぎないように制御しています。

SafeAreaView あり/なし
Simulator Screen Shot - iPhone 11 Pro Max - 2020-03-22 at 08.08.15.pngSimulator Screen Shot - iPhone 11 Pro Max - 2020-03-22 at 09.21.43.png

画面コンポーネントの作成

const ModalScreen = () => (
  <TransparentModalPage>
    <ModalCard>
      <View
        style={{ height: 50, alignItems: 'center', justifyContent: 'center' }}
      >
        <Text>Modal Area</Text>
      </View>
    </ModalCard>
  </TransparentModalPage>
);

作成したTransparentModalPage, ModalCardに子要素を設定するだけ完了です。

ナビゲーター・スクリーンの作成

const Stack = createStackNavigator();
const StackNavigator = () => {
  return (
    <Stack.Navigator mode="modal" headerMode="screen">
      ...
      <Stack.Screen
        name="ModalScreen"
        component={ModalScreen}
        options={{
          headerShown: false,
          cardStyle: { backgroundColor: 'transparent', opacity: 1 },
        }}
      />
    </Stack.Navigator>
  );
};

ModalScreenの画面オプションは、cardStyleで背景を透明設定にします。
この設定がないと、モーダル画面にグラデーションはかかりますが、背景が表示されません。

以上で設定は完了です。

おわりに

ここでは紹介しませんでしたが、 Animation や GestureHandler を用いると、より「アプリらしい」挙動をさせることができます。
組み合わせ次第で、いろんなモーダル画面が作れるので、ぜひ試してみてください。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?