【ReactNative】AndroidとiOSではキーボードが開いた時の挙動が違う
※タイトルにRNとかいてますが、おそらくRNに関係ない話だと思います。多分。
ReactNativeを使ってて、キーボードが開いた時の挙動がOS間で違うのでは?と思って調べてみたらやっぱりそうだった、という話。
どっかに書いてるかな、と思ったけど見つけられなかったのでここに書き残す。
結論 どう違うのか
なにがどう違うかというのをアニメGIFで撮ったので貼ります。
(追記: いらんとは思うけどコードあげました。 GitHub - uutarou10/rn-view-height-test )
(width/heightのラベルはそれぞれが100%に指定してある親Viewの値です)
キーボードの分、Viewが縮むのがAndroidの挙動で、そうではないのがiOSの挙動です。
なので、キーボードが開いた時にキーボードの下に要素が隠れないようにするとか、そういうものを作ろうとするとちょっと工夫する必要が出てきます。
でも…
Androidのキーボードが開いた時の挙動はAndroidManifest.xmlというファイルにあるandroid:windowSoftInputMode
という値で設定されているようです。(この辺、Android開発者ではないのでかなり怪しめです。)
react-native-cliで作ったアプリは、この値が最初adjustResize
になっています。(ちなみにAndroidManifest.xmlはRNの場合、android/app/src/main/AndroidManifest.xml
にあります)
こちらのページに書いていますが、この値をadjustPan
にすると、フォーカス位置が隠れないように画面をズラしてくれます。
adjustPan
に設定した場合の挙動はこうなります。
ただ、画面をズラしてくれると書いたように、Inputがキーボードが出る位置の下にある場合、フォーカスが当たると全体的に画面がズレます。
当然画面上にある要素は見えなくなってしまうので、実際に使うには注意が必要です。
実際、先ほどのAndroid公式のドキュメントには、
一般にこの方法はサイズ変更に比べると望ましくありません。ユーザーがソフト キーボードを閉じて、ウィンドウの隠れた部分を操作する必要が生じる可能性があるためです。
と書いています。
じゃあお前どうすりゃええねん、という話はまた調査して書こうかなと。
最近知ったTypeScriptのちょっとしたTipsとか
相変わらずインターンではTypeScriptを書いています。
最近は、ちょっと自分でも成長したなと思うのですが、バグの原因を追い求めてライブラリの中をウロウロしていたりします。
人生22年、ライブラリの中をのぞいてみよう、なんならバグ見つけてPRだそうとか考えたこともなかったですが、人間必要になればやるし、やってみると案外できるもんですね。(もちろん楽ではないけど、一個ずつ読み解くことくらいは、努力次第でできるな、と思った。)
雑談はさておき、そんなこんなの業務の中で知って、「へー」と思ったTypeScriptの諸々をメモ書き程度に書いておきます。
tsc
のメッセージを日本語にする
まぁ公式に書いていることなんですけど。(この記事に出てくることは、私が知らなかったというだけで、全部公式に書いていることです。私の勉強不足です。)
オプションとして--locale ja
を渡してあげると、いろいろ日本語になります。
たとえばこんなの
$ tsc --locale ja バージョン 3.2.4 構文: tsc [オプション] [ファイル...] 例: tsc hello.ts tsc --outFile file.js file.ts tsc @args.txt tsc --build tsconfig.json オプション: -h, --help このメッセージを表示します。 -w, --watch 入力ファイルを監視します。 --pretty 色とコンテキストを使用してエラーとメッセージにスタイルを適用します (試験的)。 --all コンパイラ オプションをすべて表示します。 -v, --version コンパイラのバージョンを表示します。 --init TypeScript プロジェクトを初期化して、tsconfig.json ファイルを作成します。 -p ファイルまたはディレクトリ, --project ファイルまたはディレクトリ 構成ファイルか、'tsconfig.json' を含むフォルダーにパスが指定されたプロジェクトをコンパイルします。 -b, --build 最新でない場合は、1 つ以上のプロジェクトとその依存関係をビルドします -t バージョン, --target バージョン ECMAScript のターゲット バージョンを指定します: 'ES3' (既定)、'ES5'、'ES2015'、'ES2016'、'ES2017'、'ES2018'、'ESNEXT'。 -m 種類, --module 種類 モジュール コード生成を指定します: 'none'、'commonjs'、'amd'、'system'、'umd'、'es2015'、'ESNext'。 --lib コンパイルに含めるライブラリ ファイルを指定します。
例がぱっと用意できなかったですが、コンパイルエラーなどももちろん日本語になります。
英語がわからんとき、やってみると救われるかもしれない。
(TSのコンパイルエラー自体そんなに難しい英語は一切出てこないので、必要かと言われれば微妙ですが)
(変数名)!
(Non-null assertion operator)
コード読んでいたら、hoge!
(hoge
は変数)みたいなのが出てきて、これはなんだ?と思ったという話。
!
という時点で察しのいい人は分かりそうな気もしますが、これはコンパイラに対して、変数が強制的にnullにならないと伝えるためのオペレーターみたいです。(Non-null assertion operatorと言うらしい)
つまり、hoge
変数の型がstring | undefined
だったとき、hoge!
とするとhoge as string
とした時と同じ動きをすることができるようです。asなんちゃらと書くとどうしても長くなるので、これは使っていきたいテク。(本来はキャストなんぞ使いたくないが)
ここに書いてた。
型と型を&
でつなぐ(Intersection Types)
うまい例が思いつかないですが、こんな感じ。(公式の例をパクってシンプルにした)
interface Person { name: string; age: number; } interface Speakable { greet(): void; } const kanameRin: Person & Speakable = { name: '鹿目凛', age: 22, greet() { console.log('イラストも描けちゃうあなたの彼女♡'); } }
Person
とSpeakable
というインタフェースが宣言されていて、定数kanameRin
はPerson & Speakable
型になっています。
右辺を見てもらえれば一目瞭然ですが、型名と型名を&でつなぐことで、型を組み合わせることができます。
(ちなみに、サンプルコードの元ネタはこちら。最近の推しです。)
ちなみに
interface A { hoge: string; } interface B { hoge: number; } const aAndB: A & B = { hoge: 'hoge' // ここでコンパイルエラーになる、hogeはstring & number型 };
こんな感じで、同名で別の方が存在すると、hogeはstirng & number
型として扱われるみたいです。(なので上記の例はエラーになります。)
これ、string | number
として扱ってくれた方がいいような気がしなくないけど、そうでもないのかしら。
あ、ちなみにこのような感じで、型を&でつなぐのをIntersection Typesというみたいで、以下に載ってます。
インターンを始めて1週間が経った。
表題の通りなのだが、4月から就職する内定先で、入社に先立って、インターンを始めて約1週間が経過したので、今の気持ちをまとめておこうかな、というのがこの記事の主旨。お気持ちポエムなので、スルーしてほしい。
何をやっているか
どこまで書くと怒られが発生してしまうのかわからないので、適当にぼやかして書くと、TypeScriptで書かれたReact Nativeアプリの機能開発をしています。
とは言いつつ、1週間では環境構築→設計の理解→追加する機能の設計→見た目に関係のない部分の実装というところまでしか到達しなかったので、RN要素はほぼ無で、ひたすらTypeScriptと戯れていた感じの1週間でした。
1週間過ごしてみての所感
技術以外のところで結構課題を感じたので、とりあえず書いておく。
初日、出社したらきているはずのSlackの招待が来ていないというトラブルに見舞われた。おまけに、一緒のチームの人たちは朝からミーティングで席を外してしまうという…。
自分の席の周りに誰もいなくなってしまって、Slackの招待も来ていなくておどおどしてしまった。
結局、数分おどおどしたあと、なんとか顔見知りのエンジニアの人を捕まえて、指示を仰ぐことができたが、どうしてもっとサクッとできないかなーと、ちょっと自己嫌悪に陥った。
実際仕事を始めてみると、様々な機会でコミュニケーションをとる必要があることを知った。既存の実装のわからないところを開発メンバーに聞いたり、API仕様を聞くためにサーバーサイドのエンジニアのところに行ったり。
幸いなことに、関わる人は皆さんいい人で、私が新人であることも理解してくれているので、どんな小さなことでも聞いたら丁寧に教えていただけるので、1週間経ってやっと慣れてきた感じがあるが、それでも初めての人に声をかけるのは精神的に結構くる。
これから先、入社したらもっと多くの人と関わる機会があると思うし、チームの入れ替えとかも結構激しくやってるような話を聞いたりするので、コミュニケーション能力の強化は真っ先に今後の課題になった。
ひとまず、精神的にきつくてもガンガン話しかけるということを目標に週の後半は過ごしてみた。
仕様の確認とかも、トレーナーが代わりにやってくれていたのを、誰に聞けばいいかだけ聞いて自分で行くようにしたり、ディスプレイがなかったので、貸してほしいとCTO(!!)に言いに行ったり。
CTOに直接言いに行くのは、さすがに緊張してしまって、喋る言葉がフェードアウトするというコミュ障大爆発っぷりだった。
ちょっと与えた印象悪かったかもなぁ…とか考えちゃうけど、そんなことずっと考えてても仕方がないので、忘れることにする。
技術編
技術的なところでももちろん課題に感じたことはたくさんあった。
割としっかり触ってきたつもりのTypeScriptも、業務レベルになれば全然理解が足りてないし、でかいコードの動きを追うのは本当に厳しいし、ついでに環境構築でも結構つまづいたし。
そんな感じのレベルでも、呆れず懇切丁寧に教えてくれるトレーナーをはじめとする周りの皆さんには頭が上がらないし、現状は時給泥棒状態なので、早く給料に見合った働きをできるレベルまで成長していきたいです。
本当は、技術以外編と同じくらいの分量、技術編も書いていたんだけど、技術は(少なくとも自分の現在のレベルでは)やればやるだけ伸びる状態にあると思うので、あえて書かないこととしてみた。
お尻に火のついた僕は強い。
結局何が言いたかったのか
文章書くの苦手なのに、オチを考えずに書くので、いつも駄文が出来上がる。この辺も今後の課題としていきたい。
ここまで読んでしまった方がいたら、ごめんなさい。言ってくれたらお詫びにコーヒーおごります。
結局何が言いたかったのか僕もわかりませんが、月曜から始まる次の1週間は、
- 頑張ってコミュニケーション取っていく。コミュ力の底上げにチャレンジする。
- 頑張らずにコミュニケーション取れるようになるのは頑張った後なのではないかなという仮説
- 自分の限界を決めず、(少なくとも今はまだ限界が見える段階じゃない)貪欲に学ぶ。フロントエンド書いているけど、必要ならサーバーサイドも読むとか、今開発している機能以外の部分についても、理解を進める。
とかこん感じでチャレンジしていこうかな。
月曜が楽しみです。
実は土曜日は1週間の疲れで丸一日死んでいたので、日曜は月曜に備えて勉強したりしたい。(インターン生はコードを持ち帰れないので、きついなーとか思っていたけど、実際の実装という超具体的なものではなく、もっと抽象的なところを学べというメッセージなのかもとか勝手に思った。多分違うけど)
【iOS12】iOS Simulatorにペーストするのがうまくいかない時
久しぶりの更新です。ずっと書いてないと書く習慣が失われそうなので、ちっちゃなネタでもどんどん投下していきます。
昨日から始めたバイト?インターン?での知見。
Macでコピーした文字列などをiOS端末上で貼り付ける方法。iOSはv12、Xcodeはv10.1です。古いバージョンだと違うかも。
通常はCmd + Vで通常通り貼り付けられます。なんの問題もないです。
ところが、開発していたら急に効かなくなってしまいました。
長いURL手打ちするのかよ〜と思っていたのですが、
Edit > Automatically Sync Pasteboardのチェックが外れていました。
この状態でコピペを使う方法は2通りあって、
です。
古い情報に惑わされたりして地味に時間を潰したので書いてみました。
PuppeteerのちょっとしたTipsいろいろ
ちょっと用事があってPuppeteerを初めて触ってみました。
以前、バイトをしていた時にSeleniumを触っていたことがありましたが、そちらと比べると、サクッとインストールできるし(npmだけで入る)、async/awaitで現代的だし、素晴らしいです。
Puppeteer触ってて調べたことをメモしておく。ちなみにv1.12.1。
PDFにマージンを設定する
const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://example.com'); await page.pdf({ path: savePath, format: 'A4', margin: { top: 30, left: 30, right: 30, bottom: 30 } }); await browser.close()
こんな感じ。
ブラウザを表示する(非ヘッドレスにする)
launch()
を呼ぶ時に、
await puppeteer.launch({headless: false});
としてあげる。
ちなみに、要注意な点として、非ヘッドレス状態では、PDF出力は利用できずエラーになります。
(Error: Protocol error (Page.printToPDF): PrintToPDF is not implemented
となる)
直接HTMLをブラウザに流し込む
Webサイトを開くのではなく、直接HTMLの文字列を流し込みたい時。
await page.setContent('<h1>Hello Puppeteer!!</h1>');
こんな感じ。
これと、ejsを組み合わせてちょっと企んでますが、その話はまた今度。
findコマンドでパスを検索する(ディレクトリも含めて検索する)
ド初心者かよ、という話。(普段からシェル慣れしている人なら、当たり前に知っていそうな話)
あまりそのようなシチュエーションもないかもしれませんが、弊研究室は、卒論発表のスライド資料を全員共通のGitリポジトリで管理しています。
ディレクトリ構成は(user name)/卒論/(ユーザー名).pptx
みたいな感じになっています。(実際とは少し違うけどだいたいこういう感じ)
これをうまいことスライドだけ集めて発表用PCにコピーしたいという話。
-name
オプションはファイル名に合致するものしか検索できないので、どうしたものかと思っていたら-path
というオプションがあるみたいです。(-wholename
でも同じ)
というわけで、
$ find -path "*/卒論/*.pptx" -exec cp {} ./slides +
みたいにすることで、うまくいきました。めでたしめでたし。というわけで、これから卒論発表してきます😀
ちなみに、findのexecでハマったところ↓
22歳になりました。気が狂いそうな話。
22歳になりました。
もう誕生日も終わりそうですが、本日2月2日で22歳になりました。めちゃ2が並ぶ。
今年はというと、就職というビッグイベントが待っているので、激動の1年になりそうです。頑張ります。
人生の目標としては、自立することでしょうか。なんだかんだ、親に頼りながらここまできたので、就職をきっかけに、経済的にも心理的にも自立して生きていけるようになりたいです。
具体的なアクションとしては、一人暮らしがあるのかなと現状では考えています。資金貯めたりして、2019年内くらいで引っ越ししたいな、という目標です。
気が狂いそうな話
そして、気が狂いそうな話。
悲しいことに、10年弱使ってきたTwitterアカウントがロックされました。
ことの発端は、2月1日。何気なくTwitterのプロフィールにある誕生日を登録したところ、突然↑の画面に。
実は、今まで使っていたアカウント、2009年に登録したものなので、当時12歳。これがマズかったようで、Twitterのガイドラインに違反してロックと相成りました。
フォームから、解除の申請は出してみたものの、希望は薄そうです。
僕くらい、Twitter漬けの日々を送っていると、Twitterアカウントのロックは致命傷のようなもの。
何も表示されないタイムラインを見るために、5分おきくらいにTwitterのアプリを開いてしまう始末。凍結されたことを報告するためにTwitterアプリを開くアホさ。
愚痴や、情報源や、昔のサークルの人々との連絡も全てTwitterでやっていたので、アカウントが死んだことで、孤独老人のようなお気持ちになってしまいました。知らんけど。
アカウントは最悪どうでもいいので、フォロー、フォロワーだけ復元させてほしい…。Twitterさん…。