AppStore公開用のスクリーンショットの作り方
はじめに
iPhoneアプリをAppStoreに公開するときスクリーンショットを提出する必要がある。やる機会も大してないのでいざやろうとすると毎回やり方調べてるのでメモしておく。
最低限必要な画像のサイズは以下を1枚ずつ(2019/07/18時点)
iPhone6.5インチ用の1242x2688
iPhone5.5インチ用の1242x2208
手順はざっくり以下
1. iPhoneシュミレータでアプリのスクリーンショットを保存(1枚)
2. AppLaunchPadで1.でとった画像をiPhoneぽい?画像にする
3. Cacooで2.で作った画像にアプリの説明分や見出しをつける
2. AppLaunchPadで1.でとった画像をiPhoneぽい?画像にする
https://theapplaunchpad.com/
こちらのサイトを使う
画像をアップロードして「Preview and Export」すると各インチの画像がダウンロードできる。この中の5.5インチと6.5インチを使う。
3. Cacooで2.で作った画像にアプリの説明分や見出しをつける
https://cacoo.com/
みんな大好きCacoo
画面下のサイズを「任意のサイズ」を指定して、1242x2688をセット。キャンバスができるのでそこに2.で作った画像を挿入。無料プランだと512K以上の画像をアップできないので、大きい場合はMacの「プレビュー」アプリでリサイズしてからアップする。あとは、テキストを挿入にして文字色や背景色も適当につける
画像が完成したら画面左の「エクスポート」ボタンでダウンロードできる。
画像つきでメモっとかないとまたわからなくなるかな、、以上です
flutter ListViewで無限スクロール
これが答えだったのかあ
https://qiita.com/najeira/items/454462c794c35b3b600a
よくわからず FutureBuilder 使わないといけないのかなとか色々試行錯誤してたらこんなバッチリな記事がありました。ListView作るときってitemCount必須かと思っていたのだが省略できるのか、、
参考記事からhttp通信なくしてListViewで無限スクロールの部分だけ抜き出した。たぶん1番簡単な無限スクロールのコード
import 'package:flutter/material.dart'; void main() { runApp(MaterialApp( home: HomeScreen(), )); } class HomeScreen extends StatefulWidget { @override State<StatefulWidget> createState() { return HomeScreenState(); } } class HomeScreenState extends State<HomeScreen> { List<String> items = []; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("無限スクロール")), body: ListView.builder( itemBuilder: (context, index) { if (index == items.length) { _load(); return Center(child: CircularProgressIndicator()); } else if (items.length < index) { return null; } else { return Container( child: ListTile(title: Text(items[index])), ); } }, ), ); } void _load() async { await new Future.delayed(const Duration(seconds: 3)); setState(() { var s = items.length; for (var i = 0; i < 20; i++) { items.add("アイテム${s + i}"); } }); } }
以上です
ionic cordova-firebase-pluginとphonegap-plugin-pushを併用する
Badノウハウ
今回やりたかったことはphonegap-plugin-pushを使用してプッシュ通知を実装しているプロジェクトに、firebase analyticsを導入したいということ。新規のプロジェクトだったらプッシュ通知もfirebaseに寄せればいいのだろうが古いプロジェクトなのでそうもいかず
両プラグインを入れた状態でxcodeでビルドしようとするとこんなエラーが...
Undefined symbol: _OBJC_CLASS_$_FIRComponent Undefined symbol: _OBJC_CLASS_$_FIRComponentType Undefined symbol: _OBJC_CLASS_$_FIRComponentContainer
調べるとLinked Frameworks and LibrariesのところにGoogleUtilities.frameworkが2ついた。けど、それぞれのプラグインのplugin.xmlを見るとGoogleUtilities.frameworkはない。FirebaseMessaging.frameworkが被ってる
cordova-plugin-firebase/plugin.xml
<framework custom="true" src="src/ios/Firebase/Messaging/FirebaseMessaging.framework" />
phonegap-plugin-push/plugin.xml
<framework src="FirebaseMessaging" type="podspec" spec="~> 2.0.0"/>
それぞれのプラグインが同じframeworkの別バージョンを使用しているのが原因ぽい。今回の対応はphonegap-plugin-pushのFirebaseMessagingを削除して使うこととした。すると次は以下のエラー
.../Plugins/phonegap-plugin-push/PushPlugin.m:316:25: Use of undeclared identifier 'FIRApp' .../Plugins/phonegap-plugin-push/PushPlugin.m:317:26: Use of undeclared identifier 'FIRApp'
前後のソースを見ると
if(isGcmEnabled && [[self fcmSenderId] length] > 0) { NSLog(@"Using FCM Notification"); [self setUsesFCM: YES]; dispatch_async(dispatch_get_main_queue(), ^{ if([FIRApp defaultApp] == nil) [FIRApp configure]; [self initRegistration]; }); } else { NSLog(@"Using APNS Notification"); [self setUsesFCM:NO]; }
となっていて、FIRAppがundeclaredでエラーになっているところはisGcmEnabledがtrueの場合だけ。phonegap-plugin-push使うってことはFCMじゃなくてAPNSのデバイスIDが欲しいはずなのでここは通らないはず。FCMを使わない場合は、GoogleService-Info.plistのIS_GCM_ENABLEDをfalseにするので絶対通らない(はず)。なのでここをコメントアウトした。firebaseのプラグインでAPNSのデバイスID取得できるようにしてくれれば1番キレイな形だとは思うが見た感じそんなメソッドは用意されていなそうだった。
以上です
flutter キーボードに完了ボタンを設置する
https://github.com/diegoveloper/flutter_keyboard_actions
これを使うとできるらしい。サンプルコードはサンプルが多かったのでとりあえず最低限のコードを
// ☆importする import 'package:keyboard_actions/keyboard_actions.dart'; class MainScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Hello")), // ☆ FormKeyboardActionsで囲む body: FormKeyboardActions( child: Content(), ), ); } } class Content extends StatefulWidget { Content({Key key}) : super(key: key); @override _ContentState createState() => new _ContentState(); } class _ContentState extends State<Content> { var _emailFocusNode = FocusNode(); var _passwordFocusNode = FocusNode(); @override void initState() { // ☆ focustNodeをactionsにセット FormKeyboardActions.setKeyboardActions( context, KeyboardActionsConfig( actions: [ KeyboardAction(focusNode: _emailFocusNode), KeyboardAction(focusNode: _passwordFocusNode), ], ) ); super.initState(); } @override Widget build(BuildContext context) { return GestureDetector( onTap: () { _emailFocusNode.unfocus(); _passwordFocusNode.unfocus(); }, child: Container( color: Colors.white, child: Padding( child: Column( children: <Widget>[ // ☆ focusNodeをセット TextField(focusNode: _emailFocusNode), TextField(focusNode: _passwordFocusNode), ], ), ), ) ); } }
以上です
flutter ios 画面タップでキーボードを閉じる
今回やりたかったことはキーボードが表示されているときに画面をタップしたらキーボードを閉じるということ。swiftでの開発でも考慮する必要があるがflutterでも同じだった
以下のようにすればいいとみんな書いてるがなぜか上手くいかず、、
FocusScope.of(context).requestFocus(FocusNode());
仕方がないので別のやり方
class Content extends StatefulWidget { Content({Key key}) : super(key: key); @override _ContentState createState() => new _ContentState(); } class _ContentState extends State<Content> { var _emailFocusNode = FocusNode(); var _passwordFocusNode = FocusNode(); @override Widget build(BuildContext context) { return GestureDetector( onTap: () { // ココ!! _emailFocusNode.unfocus(); _passwordFocusNode.unfocus(); }, child: Container( color: Colors.white, child: Padding( child: Column( children: <Widget>[ TextField(focusNode: _emailFocusNode), TextField(focusNode: _passwordFocusNode), ], ), ), ) ); } }
TextFieldごとにfocusNodeを用意してセットして、画面がタップされたらunfocusを呼ぶ。requestFocus(FocusNode()) のやり方は本当は動くのかな、、なぜ動かないのかな、、以上です
flutter hello worldひな形
flutterが最初に作ってくれるプロジェクトだと大げさなのでこれくらいがいい
StatelessWidget
import 'package:flutter/material.dart'; void main() => runApp(HelloApp()); class HelloApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Hello', home: Scaffold( appBar: AppBar(title: Text("hello")), body: Center( child: Text("hello"), ), ) ); } }
StatefulWidget
import 'package:flutter/material.dart'; void main() => runApp( MaterialApp( title: "Hello", home: MainScreen(), ) ); //Full screen class MainScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Hello"), ), body: Content(), ); } } class Content extends StatefulWidget { Content({Key key}) : super(key: key); @override _ContentState createState() => new _ContentState(); } class _ContentState extends State<Content> { @override Widget build(BuildContext context) { return Container(); } }
以上です
rails urlからパラメータを削除する
これを
https://example.com/?p=1&o=2
これにしたいだけ
https://example.com/
url = 'https://example.com/?p=1&o=2' uri = URI(url) "#{uri.scheme}://#{uri.host}#{uri.path}"
以上です