LoginSignup
0
0

More than 3 years have passed since last update.

Flutter, React Native(Expo), Xamarin.Formsでボタンを押したらModal表示する実装を比べる

Last updated at Posted at 2020-09-28

Flutter, React Native(Expo), Xamarin.Formsで、振る舞いが同じアプリを作っているんですが、その時にそれぞれのフレームワークで、Modalの実装はどうなるのか調べました。今回はボタンを押したらModalが表示する実装にしました。
調べた時に「要点となる実装部分だけの記載」という記事が多くて、初心者にとっては実装する時に「このコードはどこに追加(置き換え)するんだろうか?」って思ったので、FlutterとReact Native(expo)はコピペで動作するように記載しました。Xamarin.Formsはコピペの後でnamespaceを書き換えてください。

留意事項

その1

「こう実装すればこう動く、ってことが分かればそれでOK!」を方針に実装を進めた個人開発の内容を記載しましたので、「なぜその実装が必要なのか?」や「なぜその実装で動くのか?」は分かってない部分多数です。。。 :bow:

その2

筆者は実戦経験が乏しい(というより、アプリ開発は個人開発を除いて、現場での開発が未経験。。)、なので、ご指摘は「ここは、こうした方が良いよ:wink:」くらいのノリでお願いします。:pray::pray::pray:

その3

「HelloWorldはできたけど、他にはこんなことできたら嬉しいな〜」って思っていた時のことを思い出して書きました。そのため、強々エンジニアや超人エンジニアの方々はこのページを参考にしない方が良いと思います。:expressionless::sleepy: :cold_sweat:

※iOSとAndroidのバージョン
iOS-13.3Android-29(API Level)

Flutter

以下の記事を参考に、FlutterでModal(Dialog)の実装を行いました。
参照記事:https://stackoverflow.com/questions/60047676/flutter-display-photo-or-image-as-modal-popup

概要

ボタンを押したらshowDialogを呼んで、showDialogからModalを呼び出します。(これだけです!)

実装

Flutter-1.20.3

main.dart
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text('Image Popup example')
        ),
        backgroundColor: Colors.grey[800],
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              FlatButton(
                onPressed:  () async {
                  await showDialog(
                      context: context,
                      builder: (_) => ImageDialog()
                  );
                },
                color: Colors.blue,
                child: Text(
                  'Open Modal',
                  style: TextStyle(
                      color:Colors.white,
                      fontSize: 20.0
                  ),
                ),
              ),
            ],
          ),
        )
    );
  }
}

class ImageDialog extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Dialog(
      child: Image.network(
        'https://picsum.photos/250?image=9',
        width: 500,
        height: 500,
      ),
    );
  }
}

React Native(Expo)

以下の記事を参考に、React Native(Expo)でModal(Dialog)の実装を行いました。

参照記事:https://reactnative.dev/docs/modal

概要

React Nativeで用意されているModalを利用するんですが、Modalを閉じる場合にModalの枠外をタップしてもModalが閉じないため、Modalに閉じるボタンを実装しました。

実装

React Native cli-2.0.1Expo-3.23.3

App.js
import React, { useState } from "react";
import { Modal, StyleSheet, Text, TouchableHighlight, View, Image } from "react-native";

export default function App() {

  const [modalVisible, setModalVisible] = useState(false);

  return (
    <View style={styles.centeredView}>
      <Modal
        animationType="slide"
        transparent={true}
        visible={modalVisible}
      >
        <View style={styles.centeredView}>
          <View style={styles.modalView}>
            <Image style={styles.image}
              source={{uri: 'https://picsum.photos/250?image=9'}}
            />

            <TouchableHighlight
              style={{ ...styles.openButton, backgroundColor: "#2196F3" }}
              onPress={() => {
                setModalVisible(!modalVisible);
              }}
            >
              <Text style={styles.textStyle}>Hide Modal</Text>
            </TouchableHighlight>
          </View>
        </View>
      </Modal>

      <TouchableHighlight
        style={styles.openButton}
        onPress={() => {
          setModalVisible(true);
        }}
      >
        <Text style={styles.textStyle}>Open Modal</Text>
      </TouchableHighlight>
    </View>
  );
}

const styles = StyleSheet.create({
  centeredView: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    marginTop: 22
  },
  modalView: {
    width: 300,
    height: 200,
    margin: 20,
    backgroundColor: "white",
    borderRadius: 20,
    padding: 35,
    alignItems: "center",
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 2
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
    elevation: 5
  },
  openButton: {
    backgroundColor: "#F194FF",
    padding: 10,
    elevation: 2
  },
  textStyle: {
    color: "white",
    fontWeight: "bold",
    textAlign: "center"
  },
  modalText: {
    marginBottom: 15,
    textAlign: "center"
  },
  image: {
    width: 400,
    height: 300,
    marginLeft: 10,
    marginTop: 10,
  }
});

Xamarin.Forms

以下の記事を参考に、Xamarin.FormsでModal(Dialog)の実装を行いました。

参照記事:https://docs.microsoft.com/ja-jp/xamarin/xamarin-forms/app-fundamentals/navigation/modal

概要

ボタンを押した時に別Class(ModalPage.xaml, ModalPage.xaml.cs)としてModalを呼び出す方法で実装しました。また、Modalを閉じる場合にModalの枠外をタップしてもModalが閉じないため、Modalに閉じるボタンを実装しました。

実装

Xamarin.Forms-4.6.0.1141

ModalPage.xaml.cs
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="xamarin.forms_project.ModalPage">
    <StackLayout x:Name="layout">
        <Image Source="https://picsum.photos/250?image=9" />
        <Button x:Name="closeButton" Command="{Binding PopupCommand}" Text="Close Modal" Clicked="OnClicked" />
    </StackLayout>
</ContentPage>
ModalPage.xaml.cs
using System;
using Xamarin.Forms;

namespace xamarin.forms_project
{
    public partial class ModalPage : ContentPage
    {
        public ModalPage()
        {
            InitializeComponent();
        }

        async void OnClicked(object sender, EventArgs e)
        {
            await Navigation.PopModalAsync();
        }
    }
}

MainPage.xamlに以下を記述します。

MainPage.xaml
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="xamarin.forms_project.MainPage">
    <StackLayout>
        <Button x:Name="button" Command="{Binding PopupCommand}" Text="Open Modal" Clicked="OnSelected" />
    </StackLayout>
</ContentPage>
MainPage.xaml.cs
using System;
using Xamarin.Forms;

namespace xamarin.forms_project
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        async void OnSelected(object sender, EventArgs e)
        {
            await Navigation.PushModalAsync(new ModalPage());
        }
    }
}

気になったこと

Xamarin.Formsで「Rg.Plugins.Popup」を入れた時にModal + Imageでは動作するんですが、modalにscrollviewやpinch-in/outを実装するとなぜか動作しませんでした。。:sweat:
(動作させる方法をご存知の方、教えてくださいっっっっ!!)

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