「.NET 開発基盤部会 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
Flutter の step by step(其の一)。
コチラを参考にして実施
https://flutter.dev/docs/get-started/install/windows
flutter_windows_x.x.x-stable.zip
C:\prog\dev\flutter
// ユーザーの環境変数に設定する例 $path =[System.Environment]::GetEnvironmentVariable('PATH','User') $path +=";" + "C:\prog\dev\flutter\bin"; [System.Environment]::SetEnvironmentVariable('PATH',$path,'User')
以下のCommandを実行し、TODOを確認する。
>flutter doctor
flutter doctor --android-licenses
%USERPROFILE%\AppData\Local\Android\Sdk\tools %USERPROFILE%\AppData\Local\Android\Sdk\tools\bin %USERPROFILE%\AppData\Local\Android\Sdk\platform-tools
%USERPROFILE%\.gradle\wrapper\dists\gradle-6.7-all\cuy9mc7upwgwgeb72wkcrupxe\gradle-6.7\bin
※ 前述のPowerShell?だと、%USERPROFILE%が展開されねぇんだけど...。
「File」メニュー -> 「Settings..」 -> 「Plugins」
以下のCommandを実行し、問題が無いことを確認する。
>flutter doctor Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 2.0.3, on Microsoft Windows [Version 10.0.19041.867], locale ja-JP) [√] Android toolchain - develop for Android devices (Android SDK version 30.0.3) [√] Chrome - develop for the web [√] Android Studio (version 4.1.0) [√] VS Code, 64-bit edition (version 1.47.2) [√] Connected device (2 available) • No issues found! >
SDKのパスを変更する場合、以下の手順に従って変更する。
Android Studioで、新規作成プロジェクトする。
プロジェクトタイプ | 概要 |
Flutter Application | アプリケーション用 |
Flutter Plugin Android | ネイティブAPI用ライブラリ用 |
Flutter Package | 画面部品用 |
Flutter Module | Dartライブラリ用 |
入力項目 | 概要 |
Project Name | プロジェクト名 |
Flutter SDK path Project location | Flutter SDKをインストールしたフォルダを指定。 |
Description | プロジェクト、アプリの説明 |
Package Name | 通常、ドメインを反対にした値を入力 |
手順2で説明する。
Android Studioで1GB、エミュレータで6GB程、メモリを消費するので、
開発機のメモリが16GB程度では少々、スペック不足、故に実機でのデバッグを行うことになる。
%HOMEPATH%\AndroidStudioProjects\(flutter_app)\build\app\outputs\flutter-apk\app-release.apk※ コマンドの実行に、PATH環境変数の設定は必須。
を併用すると、RAD風に開発できる。
RaisedButton( child: const Text('Button'), color: Colors.orange, textColor: Colors.white, onPressed: () {}, ),
onPressedに、任意のメソッドを書く。
ElevatedButton( child: const Text('Button'), style: ElevatedButton.styleFrom( primary: Colors.orange, onPrimary: Colors.white, ), onPressed: () {}, ),
FlatButton( child: const Text('Button'), textColor: Colors.black, onPressed: () {}, ),
onPressedに、任意のメソッドを書く。
TextButton( child: const Text('Button'), style: TextButton.styleFrom( primary: Colors.black, ), onPressed: () {}, ),
OutlineButton( child: const Text('Button'), onPressed: () {}, ),
onPressedに、任意のメソッドを書く。
OutlinedButton( child: const Text('Button'), style: OutlinedButton.styleFrom( primary: Colors.black, ), onPressed: () {}, ),
ボタンでない、任意のWidgetに、イベントを実装できる。
簡単に、Ripple エフェクトを付ける事が出来る。
Material( // 親にMaterialが必須 color: Colors.blue, // Material自体は青を指定 child: Center( // child: Ink( // ここをContainerにするとsplashが効かないので、Inkに変える color: Colors.yellow, // 背景色はここで指定 width: 200.0, height: 100.0, child: InkWell( onTap: () {}, child: Center(child: Text('YELLOW')) ), ), ), )
InkWellのRipple エフェクトは無いが、
他のイベント(ジェスチャー)にも反応する。
GestureDetector( // タッチ検出対象のWidget child: Text( 'How to use GestureDetector', textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: TextStyle(fontWeight: FontWeight.bold), ), // ダブルタップ onDoubleTap: _incrementCounter )
のサイズになる。
body: Container( ... child: Column or Row
body: Center( ... child: Column or Row
body: Column( ... children: <Widget>[ Row(
body: Row( ... children: <Widget>[ Column(
padding: ..., child: ...
内部コンテンツの位置
前述の、...の部分に、
mainAxisAlignment: MainAxisAlignment.XXXXX,
...と書き、主軸方向の配置位置を調整する。
前述の、...の部分に、
crossAxisAlignment: CrossAxisAlignment.XXXXX,
...と書き、交差軸方向の配置位置を調整する。
english_wordsパッケージを追加・利用する。
dependencies: flutter: sdk: flutter english_words: ^4.0.0
import 'package:english_words/english_words.dart';
class _MyHomePageState extends State<MyHomePage> { String _counter = 'hoge'; void _incrementCounter() { setState(() { // This call to setState tells the Flutter framework that something has // changed in this State, which causes it to rerun the build method below // so that the display can reflect the updated values. If we changed // _counter without calling setState(), then the build method would not be // called again, and so nothing would appear to happen. _counter = WordPair.random().asPascalCase; }); }
url_launcherパッケージを追加する必要がある。
dependencies: flutter: sdk: flutter url_launcher: ^6.0.4
import 'package:url_launcher/url_launcher.dart';
_launchURL() async { const url = "http://https://www.google.co.jp/"; if (await canLaunch(url)) { await launch(url); } else { throw 'Could not Launch $url'; } }
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; ... class _MyHomePageState extends State<MyHomePage> { static const platform = const MethodChannel('samples.flutter.dev/battery'); // Get battery level. String _batteryLevel = 'Unknown battery level.'; Future<void> _getBatteryLevel() async { String batteryLevel; try { final int result = await platform.invokeMethod('getBatteryLevel'); batteryLevel = 'Battery level at $result % .'; } on PlatformException catch (e) { batteryLevel = "Failed to get battery level: '${e.message}'."; } setState(() { _batteryLevel = batteryLevel; }); } Widget build(BuildContext context) { ... ElevatedButton( child: const Text('BatteryLevel Button'), style: ElevatedButton.styleFrom( primary: Colors.orange, onPrimary: Colors.white, ), onPressed: _getBatteryLevel, ) ... }
package com.opentouryo.flutter_template import androidx.annotation.NonNull import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import android.content.Context import android.content.ContextWrapper import android.content.Intent import android.content.IntentFilter import android.os.BatteryManager import android.os.Build.VERSION import android.os.Build.VERSION_CODES class MainActivity: FlutterActivity() { private val CHANNEL = "samples.flutter.dev/battery" override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> // Note: this method is invoked on the main thread. // TODO if (call.method == "getBatteryLevel") { val batteryLevel = getBatteryLevel() if (batteryLevel != -1) { result.success(batteryLevel) } else { result.error("UNAVAILABLE", "Battery level not available.", null) } } else { result.notImplemented() } } } private fun getBatteryLevel(): Int { val batteryLevel: Int if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) } else { val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) batteryLevel = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1) } return batteryLevel } }