taiki-t's diary

React Native, Rails そして雑多な記録: The world is waiting for you to give it a meaning.

React Native Tab View with default index to 1

When Using React Native Tav View with defalut index to 1, I happened to face a strange behaviour; automatically swipes to index 0 sometimes when opening the scene. So what I did was to set initialLayout and it fixed it.

Like this:

const initialLayout = {
  height: 0,
  width: Dimensions.get('window').width,
};

render () {
   <TabViewAnimated
       // other props
       initialLayout={initialLayout}
   />
}

github.com


React Native Tab Viewの初期indexを1に指定して使ったところ、画面を開いたとき時々勝手にindex 0の画面にスクロールされることがあった。 initialLayoutを設定したら解決した。

React Nativeで画像のトリミング(cropping)

React Nativeで画像のトリミングができる。特に外部のコンポーネントを入れる必要はない。

標準の ImageEditor を使ってできる。

しかしながらいかんせんドキュメントが少ないのでここに記録も兼ねて残そうと思う。

※ 記事執筆時に使用したReact Nativeのバージョンは 0.44.0

ImageEditorの使い方

これはドキュメントにある通りだけど、シグネチャは以下の通り

static cropImage(uri, cropData, success, failure)

トリミングしたい画像のuriを渡して、あとはトリミングの設定(cropData)と成功、失敗時のコールバックを渡す。

Promiseでつつむ

コールバックを渡す形式だとコードの見通しがよくないので以下の通りPromiseで包んで使うことにする。

// Reactコンポーネントの中
_crop(uri, cropConfig) {
  return new Promise((resolve, reject) => {
    ImageEditor.cropImage(uri, cropConfig, resolve, reject)
  })
}

これで、呼び出し時にはthis._crop(uri, cropConfig)とだけやってあとはasync/awaitの流れで処理すれば良いようになった。 画像をトリミングする全体的な流れは次のようなメソッドになる。

// Reactコンポーネントの中

async _cropImage(imageUri) {
  try {

   let cropConfig = {/*offset, size を指定*/}

   return await this._crop(imageUri, cropConfig)
  } catch (error) {
     console.log(error)
  } 
}

オプションの設定

シグネチャにはcropDataとあるけどcropConfigの方が個人的にはわかりやすかったのでコード例中ではそういう名前で使っている。 このcropConfigに指定する値の例を示すとこのようになる

cropConfig = {
  offset: {
    y: yOffset,
    x: xOffset
  },
  size: {
    height: alteredHeight,
    width: alteredWidth,
  },
}

オプションの詳細については: https://github.com/facebook/react-native/blob/9ee815f6b52e0c2417c04e5a05e1e31df26daed2/Libraries/Image/ImageEditor.js#L16

offsetの指定の仕方

ImageEditorを使うときの全体の流れは上述の通り。ここでは、トリミングする際のoffsetの設定についてかく。 offsetは上記cropConfigで渡すもの。

offsetはトリミング前画像の左上隅からの距離になる。図示すると以下の感じ。

f:id:taiki-t:20170706160138p:plain

ので、上記のように中央でトリミングする場合、x軸側のoffsetは

(元画像の横サイズ - トリミング後画像の横サイズ) / 2

とかで求められる。y軸は0

画像サイズの取得

上記のところまで、やって、「で、どうやって元画像のサイズを取得するの?」というのがあると思うのでそこについて少し。 ImagegetSize関数を使う。

https://facebook.github.io/react-native/docs/image.html#getsize

これもPromiseでラップしてやればいいと思う。

_getSize(uri) {
  return new Promise((resolve, reject) => {
    Image.getSize(uri, (width, height) => { resolve({width, height}) }, reject)
  })
}

それで、使うときはこんな感じ

let { width, height } = await this._getSize(imageUri)

画像の削除

と、一点注意が必要だった。トリミングされた画像はImageStoreに保存されているので、cropImageの戻り値として返されるuriをstateなりに保存しておいて、アップロードなど必要な処理が終わったときはImageStoreから消しておく。 こんな感じ。

ImageStore.removeImageForTag(this.state.imageData.uri)

参考リンク

https://facebook.github.io/react-native/docs/image.html#getsize

ImageEditor

ImageStore

react-native/ImageEditor.js at 9ee815f6b52e0c2417c04e5a05e1e31df26daed2 · facebook/react-native · GitHub

React Nativeで動いている実例はこのアプリで: Lylica - 「近くの今が分かる」位置情報SNS

このアプリでは画像のトリミングのほか、リサイズもしている。リサイズには GitHub - bamlab/react-native-image-resizer: 🗻 Resize local images with React Native を使っている。

React NativeのImageを使うときの注意

React Native のImageを使うときの注意

とりあえずImage要素にサイズ(widthとheight)は指定する。じゃないと表示されない。

バージョン: 0.44.0


追記: 2017/07/07: 0.47.0以降のバージョンでこの制約は消えそう。Using <Image> with nested content now causes warning (yellowbox) · facebook/react-native@279f5f1 · GitHub

React Native のTouchableなんとか使うときの注意

TouchableWithoutFeedbackとか使うとき、 とりあえず内部の要素はTextだろうがImageだろうがViewでラップしておくのが無難。 余計なハマりポイントを回避できる。

バージョン: 0.44.0

Lylicaというサービスをリリースした。

Lylica (りりか) というサービスをリリースした。iOSアプリで。

f:id:taiki-t:20170621160719p:plain:w500

Lylica - 街のおすすめが分かるSNSを App Store で

「世界をもっとダイナミックにしたい」

そう思って作ってきた。きっかけは、昨年(2016)に翻訳書1を出版したことに遡る。

昼間は会社、夜は翻訳、週末も翻訳。そういう生活を1年半近く過ごしてきて実感したのは、 息抜きにどこかに出かけたいけど調べる時間もない、ということだった。

何かをやるには調べる必要があって、調べるにはスキルと知識2が必要で、そして時間も必要で。 僕はその余裕がなかったので、結局いつも決まったカフェにいくルーティーンで日常は終わった。

けれど世の中というのは自分の知らないところでも回っていて。 あの時近くでこれがやってたと後から知ったり、偶然通りがかった時にお祭りをやってることを発見したりだとか、 そういうことを多々経験した。その時に思ったことはいつも

「近所のことぐらいすぐ手元でわかったらいいのに」

だった。

「世界をダイナミックにする。」その答えの一つは、そのような人の人生により多くの選択肢をその場で提供することにある。 そうすれば、調べる時間がなくても、調べる言葉が思いつかなくても、その人はもっと色々なものに参加できるようになるかもしれない。 つまり、その人の人生はもっと豊かに、ダイナミックになるかもしれない。

そういうことを、実現したい。

f:id:taiki-t:20170621163109j:plain:w620

偶然通りかかったお祭りにて -- 2016/08/20 18:47

Lylicaでできることは今のところ主に次の2つとなっている。

  • その場のできごとを写真にとってシェアする
  • 付近の投稿を閲覧する3

世界をダイナミックにする、それだけだったら別の方法もあると思う。 それをなぜこういう機能にしたのかというと、他に実現したいことが2つあるからだ。

  • 「人と場所、人とできごとを繋げる」
  • 「人のその場所での営みを残す」

世界をダイナミックにすると同時に、これらのことも実現したい。

僕の両親は自営業だった。いわゆる個人商店。幼い時からずっと見てきた光景の一つが、人集めの苦労だ。 僕は、そのように個人で物事をやる人たちの手元に助けとなるツールを提供したい。4 低コストで、かつ簡単に地域の人たちに情報を届けられるツールを。

人と場所、人とできごとを繋げれることができれば、世界をダイナミックにできると同時にそのツールを提供できる。

そして、

実家は福島にある。2011年、震災を経験した。いろんなことが変わった。景色、生活、習慣。 それは失われたと言っていいのか、新しいものを得たと言えばいいのかわからないけど、僕が経験したのは喪失感だった。 それは今でも変わらない。

無くしたものを数えてもしょうがないんだけど、でもそれはこれからに向けて対策を取らないこととは異なる。

人がその土地で営んだ記憶、記録を残したいと思ったのはそれからだ5Googleの使命が世界中の情報を整理し、世界中の人々がアクセスできて使えるようにすることならば、 Lylicaの使命の一つは、人々がその土地で営んだ記録を残し、整理しアクセスできるようにすることだろう。

そうすれば、僕が失ったものの半分は失われずに済むような気がしている。

そういうわけで、Lylicaは簡素ながらも、

  • 「世界をもっとダイナミックにする」
  • 「人と場所、人とできごとを繋げる」
  • 「人のその場所での営みを残す」

の3つの目標を全て実現できる可能性を秘めたプロダクトとして生まれた。 この3つが実現できるかはこれからの運用にかかっている。機能の追加は、その3つの目標の元に行われていく6

なにか思うところがあった人はなんでも連絡をしてもらえると嬉しい。TwitterのDMにでも。この記事は特にそんな人のために書いている。

そして何より、インストールして使って、フィードバックをいただけたらと思う。

ダウンロードはこちららから: Lylica - 街のおすすめが分かるSNSを App Store で

始まったばかりのサービスですが、何卒よろしくお願いします。

f:id:taiki-t:20170621173917j:plain:w620

少し曇りだったけど変わらずきれいな三春の滝桜 -- 2017/04/22 05:59


  1. オブジェクト指向設計実践ガイド 「日本のITエンジニアの生産性をあげる」という個人プロジェクトの一環で取り組んだ。

  2. 例えば乗馬ができる土地に立ち寄ったとして、そこで乗馬ができることを知らないのにどうして「乗馬体験 地名」というような検索ワードをGoogleなりに打ち込むことができるのだろうか。何かを知るためにはそもそも知っていなければならないというパラドックスがある。知識ゼロでその土地に降り立ったとしても人は自分の選択肢を知ることができなければならない。

  3. こういう機能、地域SNSっぽいけどコミュニティ構築をしようとは思っていない。個人的には、向かい合って手を取り合うような属し方は不得意。そういう文脈で言えば実現したいのは「街の映画館で映画を見てて、ふと笑ったら隣の人も同じところで笑ってた」感。そういう空気感がある地域は、いざという時にも強そう。

  4. toBに関しては、以前のチームであるMisocaで取り組んできた。個人で物事を行う人たちの時間を節約するということは、僕のような子供が両親と過ごす時間が増えるということだ。それはよいことだと思っている。

  5. 被災地においては、歩いて行けるぐらいの距離の違いでも物資配給の列の長さが全く異なるという光景を目にした。そういうのも解決できたらと思う。

  6. 間近の目標としては、2020年には誰もが1ブロック先の情報を気軽に把握できるようにしていたい。このままじゃそうなっていない未来がきてしまう。

メモ:React Native で e2eテストできそうな detox

https://github.com/wix/detox

これ使えそうと思ったけど、Permission用Alert周りの処理で詰んだ。 工夫すればできそうだけどまた後ほどtryする。 導入自体はすごく簡単だった。

このIssueがcloseする頃にはそこらへんいい感じになってるのではと期待:

github.com