umetaberu

umetaberu

プログラミング技術に関するメモ書き

ActivityLog:アプリ作成時からコメント、ファボを消し、使いやすいようにする

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

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

class MyApp extends StatefulWidget {
  const MyApp({super.key});
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: Text('App名'),
        ),
        body: Container(),
      ),
    );
  }
}

OSに沿ったページ遷移の仕方を正しく実装する

この記事の対象者

Flutterでページ遷移する場合、CupertinoPageRouteとMaterialPageRouteがあるがOSによって変えたいと思っている人向け。

やり方

単純にページ遷移を判断するクラスを作ってしまう。
※「route_config.dart」とする。

[route_config.dart]

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:io' show Platform;

class RouteConfig {
  static Route<dynamic> getRoute(Widget page) {
    if (Platform.isIOS) {
      return CupertinoPageRoute(builder: (_) => page);
    } else if (Platform.isAndroid) {
      return MaterialPageRoute(builder: (_) => page);
    } else {
      return MaterialPageRoute(builder: (_) => page);
    }
  }
}

あとは使いたいところで呼び出してあげること。
[main.dart]

child: ElevatedButton(
                    onPressed:(){
                      Navigator.push(
                        context,
                        RouteConfig.getRoute(Page()),
                      );
                    },
                    child: Text(
                      'ボタン',
                      style: TextStyle(
                        // color: Colors.black87,
                        fontSize: 20,
                      ),),
                  ),

GoogleMap for Flutterを使う(Android)

GoogleMap for Flutterとは?

Flutterで地図を実装する際の手段の一つで、Googleさんが提供しているFlutterの地図プラグイン

使い方

パッケージをインストールする
pub.dev

[pubspec.yaml]

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2
  google_maps_flutter: ^2.2.4 // ←これ

今回はAndroidアプリに実装したいので、以下のファイルにAPIキーを記述する
/android/app/src/main/AndroidManifest.xml

[AndroidManifest.xml]

<application
        android:label="myApp"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
       <!--  ↓追加する     -->
       <meta-data android:name="com.google.android.geo.API_KEY"
           android:value="${MAPS_API_KEY}"/>

直打ちでもいいがGitHubなどに上げたい場合はlocal.propertiesに記述するようにしたほうが良い。
[local.properties]

MAP_API_KEY=xxxxxxxxxxx

アプリのbuild.gradleファイルにSDKの最小バージョンを記述しないとエラーになってしまう。
以下のように記述する。
android/app/build.gradle
[build.gradle]

~~~~~~~~~~~~~~~~~~~~~~省略
flutter {
    source '../..'
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

// ↓を追加
android {
    defaultConfig {
        minSdkVersion 20
    }
}

実装は東京駅の場所を表示するように設定。
APIキーの設定が上手くいっていれば、GoogleMapメソッドをbodyに置くだけで東京駅がどんと表示される。
[map_page.dart]

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

class MapPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('地図テスト'),
        ),
        body: GoogleMap(
          initialCameraPosition: CameraPosition(
              zoom: 17,  // カメラのズームレベル
              target: LatLng(35.6811673, 139.7670516), // カメラが指している地理的な場所。
              tilt: 45.0, // 地底からのカメラアングルの角度
              bearing: 90.0 //北から時計回りに測定された、度単位のカメラの方位。
          ),
        )
    );
  }
}

結果


まとめ

Flutterで地図を実装するにあたりGoogleMap for Flutterを使うのはとても簡単だった。場所の設定にパラメータを渡してあげれば検索などもできる。iOSの方の設定もできればこの記事に更新したい。

Flutterのカレンダー実装をChatGPTに頼ってみる

この記事の目的

・最近話題のChatGPTの使い方がわかる。
・ChatGPTを使ってFlutterアプリにカレンダーを実装することができる。

ChatGPTとは?

OpenAI社が2022年11月に公開したチャットボットでアプリ開発用途にも役立てることができる。
1行でこれを作って!みたいなことを言うとその方法とプログラムのコードまで教えてくれる。

使ってみる

まずはChatGPTを検索してログインが必要らしいのでログインする。
openai.com

シンプルにチャット欄に聞きたいことを聞く。1行でOK。

Flutterのパッケージを使う方法と、自作する方法の2通りを親切に教えてくれた。すごい!
[パッケージを使う方法]

[自作する方法](GridViewとListViewを使うようだ)

自分の場合はとりあえずシンプルにカレンダーを実装したかったからパッケージを使った方法で実装した。

body: Center(
 child: TableCalendar(
  firstDay: DateTime.utc(2023,2,27), // 表示するカレンダーの開始日
   lastDay: DateTime.utc(2023,12,31), // 表示するカレンダーの終了日
          selectedDayPredicate: (day) {
            return isSameDay(_selected, day);  // 日付を選択できるようにする
          },
          onDaySelected: (selected, focused){
            if (!isSameDay(_selected, selected)){
              setState(() {
                _selected = selected;
                _focused = focused;
              });
            }
          },
          focusedDay: _focused,
        )
),

結果


まとめ

ChaGPTを使ってFlutterのカレンダーを実装する方法を知ることが出来た。実際に何をすることが目的なのか明白にしてから検索するともっと使いやすいかもしれない。例えば、今回のようにとりあえずカレンダーを表示させてみたい場合は「作り方」で検索するのではなく、「とりあえずカレンダーを表示する方法」(これは極端すぎる)のように具体的に聞いてあげると良いかもしれない。少し前まではAIを使った検索関連は具体的なことを聞くとヒットしないことが多かったがChatGPTは逆に具体的な内容を聞いてあげることでより良い情報が取得できそうだ。

Riverpodを知る

Riverpodとは?

Widgetにデータを受け渡す時に使うFlutterの状態管理パッケージ。

とりあえず使ってみる

まずはどんなものなのか知るため、Riverpodドキュメントにあるカウントアプリを作ってみる。
riverpod.dev

パッケージをインストールする
pub.dev
最新版をインストール

コードはこんな感じで、わからない所にコメントを入れて理解度を高める。

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

void main() {
  runApp(
    // ProviderScopeでWidgetの上位部分を囲むことで下位でもProviderを使うことができる
    const ProviderScope(child: MyApp()),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: Home());
  }
}

// カウンターの状態管理。グローバル変数として宣言。
// finalで宣言された変数は定数として扱われて再代入できない。
// StateProvider:単純な値(列挙、文字、bool、数値など)を扱うときに利用する。
final counterProvider = StateProvider((ref) => 0);

class Home extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
        appBar: AppBar(
          title: Text('カウントアプリ'),
        ),
        body: Center(
          // Consumerを使うと、部分的な再描画が可能になる。パフォーマンス向上。
          child: Consumer(
            builder: (context, ref, _) {
              // ref.watchでプロバイダを監視することができる。
              final count = ref.watch(counterProvider);
              return Text('$count');
            },
          ),
        ),
        // カウンターアプリのインクリメント用ボタン
        floatingActionButton: FloatingActionButton(
          // このref.readでプロバイダの状態を取得する。ユーザ操作によって呼び出されることが一般的らしい。
          onPressed: () => ref.read(counterProvider.notifier).state++,
          child: const Icon(Icons.add),
        ),
      );
  }
}

結果


まとめ

・RiverpodはProviderと同じ開発者が作成した状態管理パッケージ。Providerの上位互換、改良版。
・Riverpodはデザインパターンのシングルトンに近い。もしくはその代替。
・Riverpodは限定的な箇所のウィジェット更新ができることからパフォーマンス向上につながる。

xcode-select --switchが反映されない時

何が起きた?

git submodule updateをしたときにエラー「active developer path...does not exist」が発生した。
原因はXcodeを複数入れていて古いバージョンを整理した時、Xcodeコマンドラインツールのパス「$DEVELOPER_DIR」のパスが前のXcodeのバージョンのパスになってたことだった。

user@myMacbookPro ~ %  xcode-select -print-path ←今設定されているコマンドラインツールのパスを確認する
/Users/userName/Downloads/Xcode-beta.app/Contents/Developer ←前使ってたベータ版Xcodeのパスになってる

user@myMacbookPro ~ %  sudo xcode-select --switch /Users/userName/Downloads/Xcode-beta.app/Contents/Developer ←管理者権限でパスを書き換える

user@myMacbookPro ~ %  xcode-select -print-path ←再度確認する
/Users/userName/Downloads/Xcode-beta.app/Contents/Developer ←変わらない!?

結論

bash_profile」または「zshrc」の方に$DEVELOPER_DIRを記述していればそっちも変えること

解決に至るまで

はじめに何も考えずにエラー内容で解決方法をググるXcodeコマンドラインツールのパスが存在しないか間違ってるかだった。
コマンドラインツールのパスを確認する方法は下記の2通りあるらしく、どちらも試したが解決できなかった。
Xcodeから確認する方法
②コマンドで確認する方法

なんでや?と思い、ふと環境変数を確認するとそっちにも$DEVELOPER_DIRを記述していて
それを今のXcodeコマンドラインツールの正しいパスに直すと解決できた。

open ~/.bash_profile
open ~/.zshrc ←zshの人はこっち

テキストエディタで編集して保存する

最後に更新することを忘れない

source ~/.zshrc

まとめ

Xcodeコマンドラインツールのパスを確認する方法は2つでなく、3つある(①②でダメなら3つ目が重要)
 ①Xcodeから確認する方法
 ②コマンドで確認する方法
 ③bash_profileかzshrcファイルから確認する方法

・視野を広く持つ
・エラーログ見るときはちゃんと考える。