LoginSignup
1
1

More than 3 years have passed since last update.

クロスプラットフォームでローカル画像を3枚表示したいだけなのに、、

Last updated at Posted at 2021-02-15

Flutter, React Native(Expo), Xamarin.Formsで、振る舞いが同じアプリを作っているんですが、い〜〜〜つっも、ローカール画像を表示する方法を忘れる!!! :weary:
(だから、ここにメモっとく!)

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

フレームワークごとの要点

  • Flutter

    • pubspec.yamlに画像があるフォルダを設定
  • React Native (Expo)

    • requireを配列に格納して、Imageから呼び出す
      • requireの文字列(ファイルpath)を動的に変更できない!
  • Xamarin.Forms

    • ビルドアクションを「EmbeddedResource」に設定する
    • AndroidとiOSのResource配下に画像のリンクを追加する

Flutter

Flutter-1.20.3

  1. assetsフォルダの配下に「images」フォルダを新規作成
    スクリーンショット 2021-02-13 15.41.08.png
    スクリーンショット 2021-02-13 15.41.30.png

  2. 新規作成したimagesフォルダをローカル環境で開いて、imagesフォルダに画像を追加
    スクリーンショット 2021-02-13 15.53.55.png
    スクリーンショット 2021-02-13 15.54.19.png

  3. pubspec.yamlのassetsに上記のフォルダを設定

    • imagesフォルダ配下の画像を全て使う場合は「assets/images/」
pubspec.yaml
name: flutterproject
description: A new Flutter application.

version: 1.0.0+1

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.2

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:

  uses-material-design: true

  assets:
    - assets/images/

4.ローカル画像を表示する場合は「Image.asset」を利用

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

  List<int> imageCountList = [1, 2, 3];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          children: new List.generate(imageCountList.length, (index){
            return new Image.asset(
              'assets/images/image' + imageCountList[index].toString().padLeft(3, "0") + '.jpg',
              height: 200.0,
              width: 100.0,
            );
          }),
        ),
      ),
    );
  }
}

React Native(Expo)

React Native cli-2.0.1Expo-3.23.3

1.assetsフォルダの配下にimagesフォルダを新規作成
スクリーンショット 2021-02-13 16.16.56.png
スクリーンショット 2021-02-13 16.17.14.png

2.新規作成したimagesフォルダをローカル環境で開いて、imagesフォルダに画像を追加
スクリーンショット 2021-02-13 16.19.51.png
スクリーンショット 2021-02-13 16.21.31.png
スクリーンショット 2021-02-13 16.22.10.png

3.画像pathの文字列をrequireに設定し、key-value形式で定義

4.key-value形式で定義したrequireを配列に格納

5.imageコンポーネントのsourceに、requireが格納された配列のkeyを設定(Keyからrequireを取得)

App.js
import React, { Component } from 'react';
import { SafeAreaView, StyleSheet, FlatList, Image } from 'react-native';

export default class App extends Component {

  state = {
    numColumns:3,
    items:[
      {id : "1", req : require('./assets/images/image001.jpg')},
      {id : "2", req : require('./assets/images/image002.jpg')},
      {id : "3", req : require('./assets/images/image003.jpg')},
    ]
  };

  renderItem = ({index}) => {
    return (
      <Image
        style={styles.image}
        source={this.state.items[index].req}
      />
    );
  }

  render() {
    return (
      <SafeAreaView style={styles.container}>
        <FlatList
          data={this.state.items}
          renderItem={this.renderItem}
          keyExtractor={index => index.id}/>
      </SafeAreaView>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 100,
    marginLeft: 100,
  },
  itemContainer: {
    justifyContent: 'flex-end',
    borderRadius: 5,
    padding: 10,
    height: 700,
    width: 500,
  },
  image: {
    width: 200,
    height: 100,
    marginLeft: 10,
    marginTop: 10,
  }
});

Xamarin.Forms

Xamarin.Forms-4.6.0.1141

Xamarin.Formsでは、画像を新規に追加する場合と削除してから追加する場合で、少しやり方が異なるので以下にまとめました。

プロジェクトに新規で画像を追加する場合

1.imagesフォルダを新規追加
スクリーンショット 2021-02-13 17.12.47.png
スクリーンショット 2021-02-13 17.13.11.png

2.imagesフォルダに画像を追加(ダイアログが出た場合は「ファイルをディレクトリにコピーします」を選択)
スクリーンショット 2021-02-13 17.14.33.png
スクリーンショット 2021-02-13 17.14.23.png

3.追加した全ての画像を選択して、「右クリック」→「ビルドアクション」→「EmbeddedResource」を選択
スクリーンショット 2021-02-13 17.15.07.png

4.「プロジェクト名.Android/Resources/layout」を選択して、「右クリック」→「追加」→「既存のフォルダー」を選択
スクリーンショット 2021-02-13 17.21.12.png

5.プロジェクト配下にある新規追加したimagesフォルダを選択して「OK」を押下
スクリーンショット 2021-02-13 17.21.31.png

6.「すべて含める」を押下して、「OK」を押下
スクリーンショット 2021-02-13 17.21.39.png

7.「ファイルに対するリンクを追加する」を選択し、「OK」を押下
スクリーンショット 2021-02-13 17.21.47.png

8.「プロジェクト名.iOS/Resources」を選択して、「右クリック」→「追加」→「既存のフォルダー」を選択
スクリーンショット 2021-02-13 17.22.15.png

9.プロジェクト配下にある新規追加したimagesフォルダを選択して「OK」を押下
スクリーンショット 2021-02-13 17.22.27.png

10.「すべて含める」を押下して、「OK」を押下
スクリーンショット 2021-02-13 17.22.35.png

11.「ファイルに対するリンクを追加する」を選択し、「OK」を押下
スクリーンショット 2021-02-13 17.22.43.png

12.利用したい画像を選択して、「右クリック」→「プロパティ」を押下
スクリーンショット 2021-02-13 18.33.21.png

13.「リソースID」をコピペしておく
(リソースIDは「プロジェクト名.フォルダ名.画像ファイル名.画像ファイルの拡張子」となっている)
スクリーンショット 2021-02-13 17.15.40.png

14.利用したい画像の枚数分、手順12~手順13を繰り返し

15.XAMLファイルにStackLayoutを追加してx:Name(変数名)を追加

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"
    xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" 
    ios:Page.UseSafeArea="true"
    x:Class="xamarin.forms_project.MainPage">
    <StackLayout x:Name="Layout">
    </StackLayout>
</ContentPage>

16.コードビハインド(C#)でImageSource.FromResourceに手順14でコピペしたリソースIDを引数に設定

17.コードビハインド(C#)でStackLayoutに付けた変数名に手順16で追加したImageオブジェクトを追加

MainPage.xaml.cs
using System;
using System.Collections.Generic;
using Xamarin.Forms;

namespace xamarin.forms_project
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            for(int index = 1; index < 4; index++)
            {
                var image = new Image()
                {
                    Source = ImageSource.FromResource("xamarin.forms_project.images.image" + String.Format("{0:D3}", index) + ".jpg"),
                    HorizontalOptions = LayoutOptions.Center,
                    VerticalOptions = LayoutOptions.Center,
                    WidthRequest = 200,
                    HeightRequest = 100,
                };
                Layout.Children.Add(image);
            }
        }
    }
}

(ハァ〜〜、疲れた:tired_face:

画像を削除してから再度追加する場合

画像を削除する時は「プロジェクト名/プロジェクト名.csproj」を手動での編集が必要な時があります。

例:プロジェクト名が「xamarin.forms_project」の場合、「xamarin.forms_project/xamarin.forms_project.csproj」を編集する。
スクリーンショット 2021-02-13 16.51.42.png

過去に起こったケースでは、VisualStudioからでなく、imagesフォルダやimagesフォルダにある画像ファイルを、ローカルから直接削除して、そのままビルドしてしまった場合に発生しました。こんなエラーでした。

重複する 'EmbeddedResource' 個のアイテムが含められました。.NET SDK には、既定でプロジェクト ディレクトリからのアイテムが 'EmbeddedResource' 個含まれています。これらのアイテムをプロジェクト ファイルから削除するか、'EnableDefaultEmbeddedResourceItems' プロパティを 'false' に設定してプロジェクト ファイルに明示的に含めることができます。

「プロジェクトに新規で画像を追加する場合」の手順1~手順11で追加した「images」フォルダ、「プロジェクト名.Android」と「プロジェクト名.iOS」にあるimagesフォルダを削除します。その後、「プロジェクト名/プロジェクト名.csproj」をテキストエディタで開き、NoneタグとEmbeddedResourceタグをItemGroupタグごと削除します。そしてVisualStudioで再読み込みします。

before
スクリーンショット 2021-02-13 16.51.02.png

after
スクリーンショット 2021-02-13 16.51.17.png

これらを行なった後で、「プロジェクトに新規で画像を追加する場合」を再度行います。

感想

見てもらったらわかりますが、煩雑さは
Flutter < React Native(Expo) < Xamarin.Forms
です!
Xamarin.Forms、、:rage::rage:

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